public void MessageTemplates_WhenRateLimitingEnabled_IncludesTheNumberOfSkippedMessages()
        {
            const int secondsBetweenLogs = 60;
            var       rateLimiter        = new LogRateLimiter(secondsBetweenLogs);
            var       logger             = new DatadogSerilogLogger(_logger, rateLimiter);
            var       clock = new SimpleClock();

            _clockDisposable = Clock.SetForCurrentThread(clock);

            WriteRateLimitedLogMessage(logger, "Warning level message");

            // these aren't written, as rate limited
            WriteRateLimitedLogMessage(logger, "Warning level message");
            WriteRateLimitedLogMessage(logger, "Warning level message");
            WriteRateLimitedLogMessage(logger, "Warning level message");

            clock.UtcNow = clock.UtcNow.AddSeconds(secondsBetweenLogs);
            WriteRateLimitedLogMessage(logger, "Warning level message");

            Assert.True(
                _logEventSink.Events.Count == 2,
                $"Found {_logEventSink.Events.Count} messages: \r\n{string.Join("\r\n", _logEventSink.Events.Select(l => l.RenderMessage()))}");

            Assert.Collection(
                _logEventSink.Events,
                log => log.RenderMessage().EndsWith(", 0 additional messages skipped"),
                log => log.RenderMessage().EndsWith(", 3 additional messages skipped"));
        }
        public void ErrorsDuringRateLimiting_DontBubbleUp()
        {
            var rateLimiter = new FailingRateLimiter();
            var logger      = new DatadogSerilogLogger(_logger, rateLimiter);

            // Should not throw
            logger.Warning("Warning level message");

            Assert.True(rateLimiter.WasInvoked);
            Assert.Empty(_logEventSink.Events);
        }
        public void ErrorsDuringLogging_DontBubbleUp()
        {
            var mockLogger = new Mock <ILogger>();

            mockLogger
            .Setup(x => x.Write(It.IsAny <LogEventLevel>(), It.IsAny <Exception>(), It.IsAny <string>(), It.IsAny <object[]>()))
            .Throws(new NotImplementedException());

            var logger = new DatadogSerilogLogger(mockLogger.Object, new NullLogRateLimiter());

            // Should not throw
            logger.Warning("Warning level message");

            Assert.Empty(_logEventSink.Events);
            mockLogger.Verify();
        }
        public void RateLimiting_ConsidersLogMessagesOnSameLineToBeSame()
        {
            const int secondsBetweenLogs = 60;
            var       rateLimiter        = new LogRateLimiter(secondsBetweenLogs);
            var       logger             = new DatadogSerilogLogger(_logger, rateLimiter);

            var clock = new SimpleClock();

            _clockDisposable = Clock.SetForCurrentThread(clock);

#pragma warning disable SA1107 // Code must not contain multiple statements on one line
            logger.Warning("Warning level message"); logger.Warning("Warning level message");
#pragma warning restore SA1107 // Code must not contain multiple statements on one line

            Assert.True(
                _logEventSink.Events.Count == 1,
                $"Found {_logEventSink.Events.Count} messages: \r\n{string.Join("\r\n", _logEventSink.Events.Select(l => l.RenderMessage()))}");
        }
        public void RateLimiting_WhenLoggingIsOnSeparateLines_DoesntRateLimit()
        {
            const int secondsBetweenLogs = 60;
            var       rateLimiter        = new LogRateLimiter(secondsBetweenLogs);
            var       logger             = new DatadogSerilogLogger(_logger, rateLimiter);

            var clock = new SimpleClock();

            _clockDisposable = Clock.SetForCurrentThread(clock);

            logger.Warning("Warning level message");
            logger.Warning("Warning level message");
            logger.Warning("Warning level message");

            clock.UtcNow = clock.UtcNow.AddSeconds(secondsBetweenLogs);
            logger.Warning("Warning level message");

            Assert.True(
                _logEventSink.Events.Count == 4,
                $"Found {_logEventSink.Events.Count} messages: \r\n{string.Join("\r\n", _logEventSink.Events.Select(l => l.RenderMessage()))}");
        }