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}'"); }
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); }
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)); }
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)); }
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); }); }); } }
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); }