public void LogEvent_WithDefaultCorrelationInfoAccessor_HasOperationIdAndTransactionId()
        {
            // Arrange
            string expectedOperationId   = $"operation-{Guid.NewGuid()}";
            string expectedTransactionId = $"transaction-{Guid.NewGuid()}";

            var spySink = new InMemoryLogSink();
            var correlationInfoAccessor = new DefaultCorrelationInfoAccessor();

            correlationInfoAccessor.SetCorrelationInfo(new CorrelationInfo(expectedOperationId, expectedTransactionId));

            ILogger logger = new LoggerConfiguration()
                             .Enrich.WithCorrelationInfo(correlationInfoAccessor)
                             .WriteTo.Sink(spySink)
                             .CreateLogger();

            // Act
            logger.Information("This message will be enriched with correlation information");

            // Assert
            LogEvent logEvent = Assert.Single(spySink.CurrentLogEmits);

            Assert.True(
                logEvent.ContainsProperty(ContextProperties.Correlation.OperationId, expectedOperationId),
                $"Expected to have a log property operation ID '{ContextProperties.Correlation.OperationId}' with the value '{expectedOperationId}'");
            Assert.True(
                logEvent.ContainsProperty(ContextProperties.Correlation.TransactionId, expectedTransactionId),
                $"Expected to have a log property transaction ID '{ContextProperties.Correlation.TransactionId}' with the value '{expectedTransactionId}'");
        }
Exemple #2
0
        public void TryCorrelate_WithIncorrectOperationParentId_DoesntSetExpectedOperationId(string prefix, string postfix)
        {
            // Arrange
            var operationId = $"operation-{Guid.NewGuid()}";
            var headers     = new Dictionary <string, StringValues>
            {
                ["Request-Id"] = prefix + operationId + postfix
            };

            HttpContext context         = CreateHttpContext(headers);
            var         contextAccessor = new Mock <IHttpContextAccessor>();

            contextAccessor.Setup(accessor => accessor.HttpContext).Returns(context);
            var correlationAccessor = new DefaultCorrelationInfoAccessor();

            var options     = Options.Create(new HttpCorrelationInfoOptions());
            var correlation = new HttpCorrelation(options, contextAccessor.Object, correlationAccessor, NullLogger <HttpCorrelation> .Instance);

            // Act / Assert
            Assert.True(correlation.TryHttpCorrelate(out string errorMessage), errorMessage);
            Assert.Null(errorMessage);
            var correlationInfo = context.Features.Get <CorrelationInfo>();

            Assert.NotEqual(operationId, correlationInfo.OperationId);
            Assert.Null(correlationInfo.OperationParentId);
        }
Exemple #3
0
        public void Create_WithoutHttpContextAccessor_Fails()
        {
            // Arrange
            IOptions <HttpCorrelationInfoOptions> options = Options.Create(new HttpCorrelationInfoOptions());
            ICorrelationInfoAccessor  correlationAccessor = new DefaultCorrelationInfoAccessor();
            ILogger <HttpCorrelation> logger = NullLogger <HttpCorrelation> .Instance;

            // Act / Assert
            Assert.ThrowsAny <ArgumentException>(() =>
                                                 new HttpCorrelation(options, httpContextAccessor: null, correlationInfoAccessor: correlationAccessor, logger: logger));
        }
Exemple #4
0
        public void Create_WithoutOptions_Fails()
        {
            // Arrange
            ICorrelationInfoAccessor  correlationAccessor = new DefaultCorrelationInfoAccessor();
            IHttpContextAccessor      contextAccessor     = Mock.Of <IHttpContextAccessor>();
            ILogger <HttpCorrelation> logger = NullLogger <HttpCorrelation> .Instance;

            // Act / Assert
            Assert.ThrowsAny <ArgumentException>(() =>
                                                 new HttpCorrelation(options: null, httpContextAccessor: contextAccessor, correlationInfoAccessor: correlationAccessor, logger: logger));
        }
Exemple #5
0
        public void Correlation_GetCorrelationInfo_UsesStubbedCorrelation()
        {
            // Arrange
            var expected            = new CorrelationInfo($"operation-{Guid.NewGuid()}", $"transaction-{Guid.NewGuid()}");
            var correlationAccessor = new DefaultCorrelationInfoAccessor();

            correlationAccessor.SetCorrelationInfo(expected);

            IOptions <HttpCorrelationInfoOptions> options = Options.Create(new HttpCorrelationInfoOptions());
            IHttpContextAccessor      contextAccessor     = Mock.Of <IHttpContextAccessor>();
            ILogger <HttpCorrelation> logger = NullLogger <HttpCorrelation> .Instance;
            var correlation = new HttpCorrelation(options, contextAccessor, correlationAccessor, logger);

            // Act
            CorrelationInfo actual = correlation.GetCorrelationInfo();

            // Assert
            Assert.Same(expected, actual);
        }
        public async Task LogEventWithCorrelationInfo_SinksToApplicationInsights_ResultsInTelemetryWithCorrelationInfo()
        {
            // Arrange
            string message           = "Message that will be correlated";
            string operationId       = $"operation-{Guid.NewGuid()}";
            string transactionId     = $"transaction-{Guid.NewGuid()}";
            string operationParentId = $"operation-parent-{Guid.NewGuid()}";

            var correlationInfoAccessor = new DefaultCorrelationInfoAccessor();

            correlationInfoAccessor.SetCorrelationInfo(new CorrelationInfo(operationId, transactionId, operationParentId));

            using (ILoggerFactory loggerFactory = CreateLoggerFactory(config => config.Enrich.WithCorrelationInfo(correlationInfoAccessor)))
            {
                ILogger logger = loggerFactory.CreateLogger <ApplicationInsightsSinkTests>();

                // Act
                logger.LogInformation(message);
            }

            // Assert
            using (ApplicationInsightsDataClient client = CreateApplicationInsightsClient())
            {
                await RetryAssertUntilTelemetryShouldBeAvailableAsync(async() =>
                {
                    EventsResults <EventsTraceResult> traceEvents = await client.Events.GetTraceEventsAsync(ApplicationId, filter: OnlyLastHourFilter);

                    AssertX.Any(traceEvents.Value, trace =>
                    {
                        Assert.Equal(message, trace.Trace.Message);
                        Assert.True(trace.CustomDimensions.TryGetValue(ContextProperties.Correlation.OperationId, out string actualOperationId), "Requires a operation ID in the custom dimensions");
                        Assert.True(trace.CustomDimensions.TryGetValue(ContextProperties.Correlation.TransactionId, out string actualTransactionId), "Requires a transaction ID in the custom dimensions");
                        Assert.True(trace.CustomDimensions.TryGetValue(ContextProperties.Correlation.OperationParentId, out string actualOperationParentId), "Requires a operation parent ID in the custom dimensions");

                        Assert.Equal(operationId, actualOperationId);
                        Assert.Equal(transactionId, actualTransactionId);
                        Assert.Equal(operationParentId, actualOperationParentId);
                        Assert.Equal(operationId, trace.Operation.Id);
                        Assert.Equal(operationParentId, trace.Operation.ParentId);
                    });
                });
        public async Task LogExceptionWithCorrelationInfo_SinksToApplicationInsights_ResultsInTelemetryWithCorrelationInfo()
        {
            // Arrange
            string message   = BogusGenerator.Lorem.Sentence();
            var    exception = new PlatformNotSupportedException(message);

            string operationId       = $"operation-{Guid.NewGuid()}";
            string transactionId     = $"transaction-{Guid.NewGuid()}";
            string operationParentId = $"operation-parent-{Guid.NewGuid()}";

            var correlationInfoAccessor = new DefaultCorrelationInfoAccessor();

            correlationInfoAccessor.SetCorrelationInfo(new CorrelationInfo(operationId, transactionId, operationParentId));

            using (ILoggerFactory loggerFactory = CreateLoggerFactory(config => config.Enrich.WithCorrelationInfo(correlationInfoAccessor)))
            {
                ILogger logger = loggerFactory.CreateLogger <ApplicationInsightsSinkTests>();

                // Act
                logger.LogCritical(exception, exception.Message);
            }

            // Assert
            using (ApplicationInsightsDataClient client = CreateApplicationInsightsClient())
            {
                await RetryAssertUntilTelemetryShouldBeAvailableAsync(async() =>
                {
                    EventsResults <EventsExceptionResult> results = await client.Events.GetExceptionEventsAsync(ApplicationId, filter: OnlyLastHourFilter);
                    Assert.NotEmpty(results.Value);

                    AssertX.Any(results.Value, result =>
                    {
                        Assert.Equal(exception.Message, result.Exception.OuterMessage);
                        Assert.Equal(operationId, result.Operation.Id);
                        Assert.Equal(operationParentId, result.Operation.ParentId);
                    });
                });
            }
        }
Exemple #8
0
        public void TryCorrelate_WithCorrectOperationParentIdWithDisabledUpstreamExtraction_DoesntSetExpectedOperationId()
        {
            // Arrange
            var    operationIdFromGeneration = $"operation-{Guid.NewGuid()}";
            var    operationIdFromUpstream   = $"operation-{Guid.NewGuid()}";
            string operationParentId         = $"|{operationIdFromUpstream}.";
            var    headers = new Dictionary <string, StringValues>
            {
                ["Request-Id"] = operationParentId
            };

            HttpContext context         = CreateHttpContext(headers);
            var         contextAccessor = new Mock <IHttpContextAccessor>();

            contextAccessor.Setup(accessor => accessor.HttpContext).Returns(context);
            var correlationAccessor = new DefaultCorrelationInfoAccessor();

            var options = Options.Create(new HttpCorrelationInfoOptions
            {
                Operation       = { GenerateId = () => operationIdFromGeneration },
                UpstreamService = { ExtractFromRequest = false }
            });
            var correlation = new HttpCorrelation(options, contextAccessor.Object, correlationAccessor, NullLogger <HttpCorrelation> .Instance);

            // Act
            bool isCorrelated = correlation.TryHttpCorrelate(out string errorMessage);

            // Assert
            Assert.True(isCorrelated, errorMessage);
            Assert.Null(errorMessage);
            var correlationInfo = context.Features.Get <CorrelationInfo>();

            Assert.NotEqual(operationIdFromUpstream, correlationInfo.OperationId);
            Assert.Equal(operationIdFromGeneration, correlationInfo.OperationId);
            Assert.Null(correlationInfo.OperationParentId);
        }