diff --git a/sdk/monitor/Microsoft.OpenTelemetry.Exporter.AzureMonitor/tests/Microsoft.OpenTelemetry.Exporter.AzureMonitor.Integration.Tests/TelemetryItemTests.cs b/sdk/monitor/Microsoft.OpenTelemetry.Exporter.AzureMonitor/tests/Microsoft.OpenTelemetry.Exporter.AzureMonitor.Integration.Tests/TelemetryItemTests.cs index c370e60acdce..6f5b1bae6a61 100644 --- a/sdk/monitor/Microsoft.OpenTelemetry.Exporter.AzureMonitor/tests/Microsoft.OpenTelemetry.Exporter.AzureMonitor.Integration.Tests/TelemetryItemTests.cs +++ b/sdk/monitor/Microsoft.OpenTelemetry.Exporter.AzureMonitor/tests/Microsoft.OpenTelemetry.Exporter.AzureMonitor.Integration.Tests/TelemetryItemTests.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -77,7 +76,9 @@ public void VerifyILogger(LogLevel logLevel, string expectedSeverityLevel) { var message = "Hello World!"; + var activity = new Activity("test activity").Start(); var telemetryItem = this.RunLoggerTest(x => x.Log(logLevel: logLevel, message: message)); + activity.Stop(); VerifyTelemetryItem.VerifyEvent( telemetryItem: telemetryItem, @@ -85,24 +86,26 @@ public void VerifyILogger(LogLevel logLevel, string expectedSeverityLevel) { Message = message, SeverityLevel = expectedSeverityLevel, + SpanId = activity.SpanId.ToHexString(), + TraceId = activity.TraceId.ToHexString(), }); } private TelemetryItem RunActivityTest(Action testScenario) { // SETUP - var ActivitySourceName = "MyCompany.MyProduct.MyLibrary"; + var ActivitySourceName = $"{nameof(TelemetryItemTests)}.{nameof(RunActivityTest)}"; using var activitySource = new ActivitySource(ActivitySourceName); - var transmitter = new MockTransmitter(); + var mockTransmitter = new MockTransmitter(); var processor = new BatchExportProcessor(new AzureMonitorTraceExporter( options: new AzureMonitorExporterOptions { ConnectionString = EmptyConnectionString, }, - transmitter: transmitter)); + transmitter: mockTransmitter)); - Sdk.CreateTracerProviderBuilder() + using var tracerProvider = Sdk.CreateTracerProviderBuilder() .SetSampler(new AlwaysOnSampler()) .AddSource(ActivitySourceName) .AddProcessor(processor) @@ -113,43 +116,109 @@ private TelemetryItem RunActivityTest(Action testScenario) // CLEANUP processor.ForceFlush(); - //Task.Delay(100).Wait(); //TODO: HOW TO REMOVE THIS WAIT? - Assert.True(transmitter.TelemetryItems.Any(), "test project did not capture telemetry"); - return transmitter.TelemetryItems.Single(); + Assert.True(mockTransmitter.TelemetryItems.Any(), "test project did not capture telemetry"); + return mockTransmitter.TelemetryItems.Single(); } private TelemetryItem RunLoggerTest(Action> testScenario) { // SETUP - var transmitter = new MockTransmitter(); + var mockTransmitter = new MockTransmitter(); var processor = new BatchExportProcessor(new AzureMonitorLogExporter( options: new AzureMonitorExporterOptions { ConnectionString = EmptyConnectionString, }, - transmitter: transmitter)); + transmitter: mockTransmitter)); var serviceCollection = new ServiceCollection().AddLogging(builder => { builder.SetMinimumLevel(LogLevel.Trace) .AddOpenTelemetry(options => options - .AddProcessor(processor)); + .AddProcessor(processor)); }); - // ACT using var serviceProvider = serviceCollection.BuildServiceProvider(); var logger = serviceProvider.GetRequiredService>(); + + // ACT testScenario(logger); // CLEANUP processor.ForceFlush(); - //Task.Delay(100).Wait(); //TODO: HOW TO REMOVE THIS WAIT? - Assert.True(transmitter.TelemetryItems.Any(), "test project did not capture telemetry"); - return transmitter.TelemetryItems.Single(); + Assert.True(mockTransmitter.TelemetryItems.Any(), "test project did not capture telemetry"); + return mockTransmitter.TelemetryItems.Single(); } - // TODO: INCLUDE ADDITIONAL TESTS VALIDATING ILOGGER + ACTIVITY + /// + /// This test is to verify that the correlation Ids from Activity are set on Log Telemetry. + /// This test will generate two telemetry items and their Ids are expected to match. + /// This test does not inspect any other fields. + /// + [Fact] + public void VerifyLoggerWithActivity() + { + // SETUP + var ActivitySourceName = $"{nameof(TelemetryItemTests)}.{nameof(VerifyLoggerWithActivity)}"; + using var activitySource = new ActivitySource(ActivitySourceName); + + var mockTransmitter = new MockTransmitter(); + + var azureMonitorExporterOptions = new AzureMonitorExporterOptions + { + ConnectionString = EmptyConnectionString, + }; + + var processor1 = new BatchExportProcessor(new AzureMonitorTraceExporter( + options: azureMonitorExporterOptions, + transmitter: mockTransmitter)); + + var processor2 = new BatchExportProcessor(new AzureMonitorLogExporter( + options: azureMonitorExporterOptions, + transmitter: mockTransmitter)); + + using var tracerProvider = Sdk.CreateTracerProviderBuilder() + .SetSampler(new AlwaysOnSampler()) + .AddSource(ActivitySourceName) + .AddProcessor(processor1) + .Build(); + + var serviceCollection = new ServiceCollection().AddLogging(builder => + { + builder.SetMinimumLevel(LogLevel.Trace) + .AddOpenTelemetry(options => options + .AddProcessor(processor2)); + }); + + using var serviceProvider = serviceCollection.BuildServiceProvider(); + var logger = serviceProvider.GetRequiredService>(); + + // ACT + using (var activity = activitySource.StartActivity(name: "test activity", kind: ActivityKind.Server)) + { + activity.SetTag("message", "hello activity!"); + + logger.LogWarning("hello ilogger"); + } + + // CLEANUP + processor1.ForceFlush(); + processor2.ForceFlush(); + + // VERIFY + Assert.True(mockTransmitter.TelemetryItems.Any(), "test project did not capture telemetry"); + Assert.Equal(2, mockTransmitter.TelemetryItems.Count); + + var logTelemetry = mockTransmitter.TelemetryItems.Single(x => x.Name == "Message"); + var activityTelemetry = mockTransmitter.TelemetryItems.Single(x => x.Name == "Request"); + + var activityId = ((RequestData)activityTelemetry.Data.BaseData).Id; + var operationId = activityTelemetry.Tags["ai.operation.id"]; + + Assert.Equal(activityId, logTelemetry.Tags["ai.operation.parentId"]); + Assert.Equal(operationId, logTelemetry.Tags["ai.operation.id"]); + } } } diff --git a/sdk/monitor/Microsoft.OpenTelemetry.Exporter.AzureMonitor/tests/Microsoft.OpenTelemetry.Exporter.AzureMonitor.Integration.Tests/TestFramework/ExpectedTelemetryItemValues.cs b/sdk/monitor/Microsoft.OpenTelemetry.Exporter.AzureMonitor/tests/Microsoft.OpenTelemetry.Exporter.AzureMonitor.Integration.Tests/TestFramework/ExpectedTelemetryItemValues.cs index 751df0394216..235c77874c6d 100644 --- a/sdk/monitor/Microsoft.OpenTelemetry.Exporter.AzureMonitor/tests/Microsoft.OpenTelemetry.Exporter.AzureMonitor.Integration.Tests/TestFramework/ExpectedTelemetryItemValues.cs +++ b/sdk/monitor/Microsoft.OpenTelemetry.Exporter.AzureMonitor/tests/Microsoft.OpenTelemetry.Exporter.AzureMonitor.Integration.Tests/TestFramework/ExpectedTelemetryItemValues.cs @@ -13,5 +13,7 @@ internal struct ExpectedTelemetryItemValues public string Message; public Dictionary CustomProperties; public SeverityLevel SeverityLevel; + public string SpanId; + public string TraceId; } } diff --git a/sdk/monitor/Microsoft.OpenTelemetry.Exporter.AzureMonitor/tests/Microsoft.OpenTelemetry.Exporter.AzureMonitor.Integration.Tests/TestFramework/VerifyTelemetryItem.cs b/sdk/monitor/Microsoft.OpenTelemetry.Exporter.AzureMonitor/tests/Microsoft.OpenTelemetry.Exporter.AzureMonitor.Integration.Tests/TestFramework/VerifyTelemetryItem.cs index 57fb6734fbbf..2e485ac75aac 100644 --- a/sdk/monitor/Microsoft.OpenTelemetry.Exporter.AzureMonitor/tests/Microsoft.OpenTelemetry.Exporter.AzureMonitor.Integration.Tests/TestFramework/VerifyTelemetryItem.cs +++ b/sdk/monitor/Microsoft.OpenTelemetry.Exporter.AzureMonitor/tests/Microsoft.OpenTelemetry.Exporter.AzureMonitor.Integration.Tests/TestFramework/VerifyTelemetryItem.cs @@ -12,7 +12,6 @@ namespace Microsoft.OpenTelemetry.Exporter.AzureMonitor.Integration.Tests.TestFr { internal static class VerifyTelemetryItem { - public static void Verify(TelemetryItem telemetryItem, ActivityKind activityKind, ExpectedTelemetryItemValues expectedVars) { switch (activityKind) @@ -59,6 +58,8 @@ public static void VerifyEvent(TelemetryItem telemetryItem, ExpectedTelemetryIte var data = (MessageData)telemetryItem.Data.BaseData; Assert.Equal(expectedVars.Message, data.Message); Assert.Equal(expectedVars.SeverityLevel, data.SeverityLevel); + Assert.Equal(expectedVars.SpanId, telemetryItem.Tags["ai.operation.parentId"]); + Assert.Equal(expectedVars.TraceId, telemetryItem.Tags["ai.operation.id"]); } } }