From 8d7472fd8de0be15fe120c5152d67883ff0f1881 Mon Sep 17 00:00:00 2001 From: John Crim Date: Wed, 26 Jun 2024 19:59:20 -0700 Subject: [PATCH] fix(telemetry transmission): Include ILogger CategoryName in logger output Previously this field was omitted, which was not consistent with normal ILogger behavior, or with Application Insights classic behavior. fixes: #44746 --- .../src/Internals/LogsHelper.cs | 6 +++ .../E2ETelemetryItemValidation/LogsTests.cs | 2 +- .../LogsHelperTests.cs | 42 +++++++++++++++---- .../MessageDataTests.cs | 2 +- 4 files changed, 42 insertions(+), 10 deletions(-) diff --git a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/LogsHelper.cs b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/LogsHelper.cs index 2892fbec5edfd..fadb7b70e3374 100644 --- a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/LogsHelper.cs +++ b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/LogsHelper.cs @@ -124,6 +124,12 @@ internal static List OtelToAzureMonitorLogs(Batch batc logRecord.ForEachScope(s_processScope, properties); + var categoryName = logRecord.CategoryName; + if (!string.IsNullOrEmpty(categoryName)) + { + properties.Add("CategoryName", categoryName.Truncate(SchemaConstants.KVP_MaxValueLength)!); + } + if (logRecord.EventId.Id != 0) { properties.Add("EventId", logRecord.EventId.Id.ToString(CultureInfo.InvariantCulture)); diff --git a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/E2ETelemetryItemValidation/LogsTests.cs b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/E2ETelemetryItemValidation/LogsTests.cs index cb95fd64e3388..437390eed8258 100644 --- a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/E2ETelemetryItemValidation/LogsTests.cs +++ b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/E2ETelemetryItemValidation/LogsTests.cs @@ -83,7 +83,7 @@ public void VerifyLog(LogLevel logLevel, string expectedSeverityLevel) telemetryItem: telemetryItem!, expectedSeverityLevel: expectedSeverityLevel, expectedMessage: "Hello {name}.", - expectedMessageProperties: new Dictionary { { "name", "World" }}, + expectedMessageProperties: new Dictionary { { "name", "World" }, { "CategoryName", logCategoryName } }, expectedSpanId: null, expectedTraceId: null); } diff --git a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/LogsHelperTests.cs b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/LogsHelperTests.cs index 3905ea097d64f..a86e52a02dadc 100644 --- a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/LogsHelperTests.cs +++ b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/LogsHelperTests.cs @@ -61,7 +61,7 @@ public void MessageIsSetToExceptionMessage(bool parseStateValues) Assert.Equal("tomato", name); Assert.True(properties.TryGetValue("price", out string price)); Assert.Equal("2.99", price); - Assert.Equal(3, properties.Count); + Assert.Equal(4, properties.Count); } [Fact] @@ -91,7 +91,7 @@ public void MessageIsSetToFormattedMessageWhenIncludeFormattedMessageIsSet() Assert.Equal("tomato", name); Assert.True(properties.TryGetValue("price", out string price)); Assert.Equal("2.99", price); - Assert.Equal(2, properties.Count); + Assert.Equal(3, properties.Count); } [Fact] @@ -121,7 +121,7 @@ public void MessageIsSetToOriginalFormatWhenIncludeFormattedMessageIsNotSet() Assert.Equal("tomato", name); Assert.True(properties.TryGetValue("price", out string price)); Assert.Equal("2.99", price); - Assert.Equal(2, properties.Count); + Assert.Equal(3, properties.Count); } [Theory] @@ -152,7 +152,7 @@ public void PropertiesContainFieldsFromStructuredLogs(bool parseStateValues) Assert.Equal("tomato", name); Assert.True(properties.TryGetValue("price", out string price)); Assert.Equal("2.99", price); - Assert.Equal(2, properties.Count); + Assert.Equal(3, properties.Count); } [Fact] @@ -180,7 +180,33 @@ public void PropertiesContainEventIdAndEventNameIfSetOnLog() Assert.Equal("1", eventId); Assert.True(properties.TryGetValue("EventName", out string eventName)); Assert.Equal("TestEvent", eventName); - Assert.Equal(2, properties.Count); + Assert.Equal(3, properties.Count); + } + + [Fact] + public void PropertiesContainLoggerName() + { + var logRecords = new List(); + using var loggerFactory = LoggerFactory.Create(builder => + { + builder.AddOpenTelemetry(options => + { + options.AddInMemoryExporter(logRecords); + }); + builder.AddFilter(typeof(LogsHelperTests).FullName, LogLevel.Trace); + }); + + var categoryName = nameof(LogsHelperTests); + var logger = loggerFactory.CreateLogger(categoryName); + + logger.LogInformation("Information goes here"); + + var properties = new ChangeTrackingDictionary(); + LogsHelper.GetMessageAndSetProperties(logRecords[0], properties); + + Assert.True(properties.TryGetValue("CategoryName", out string loggedCategoryName)); + Assert.Equal(categoryName, loggedCategoryName); + Assert.Single(properties); } [Fact] @@ -318,13 +344,13 @@ public void VerifyHandlingOfVariousScopeDataTypes(object scopeValue) if (scopeValue != null) { - Assert.Single(properties); // Assert that there is exactly one property + Assert.Equal(2, properties.Count); // Scope property + CategoryName Assert.True(properties.TryGetValue(expectedScopeKey, out string actualScopeValue)); Assert.Equal(scopeValue.ToString(), actualScopeValue); } else { - Assert.Empty(properties); // Assert that properties are empty + Assert.Single(properties); // Single property expected (CategoryName) } } @@ -408,7 +434,7 @@ public void DuplicateKeysInLogRecordAttributesAndLogScope() var properties = new ChangeTrackingDictionary(); LogsHelper.GetMessageAndSetProperties(logRecords[0], properties); - Assert.Equal(2, properties.Count); + Assert.Equal(3, properties.Count); Assert.True(properties.TryGetValue(expectedScopeKey, out string actualScopeValue)); Assert.Equal(expectedScopeValue, actualScopeValue); Assert.True(properties.TryGetValue("attributeKey", out string actualAttributeValue)); diff --git a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/MessageDataTests.cs b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/MessageDataTests.cs index ebeacb8c1d83b..a26f8d7da911f 100644 --- a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/MessageDataTests.cs +++ b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/MessageDataTests.cs @@ -41,7 +41,7 @@ public void ValidateMessageData(LogLevel logLevel) Assert.Equal("Log Message", messageData.Message); Assert.Equal(LogsHelper.GetSeverityLevel(logLevel), messageData.SeverityLevel); - Assert.Empty(messageData.Properties); + Assert.Single(messageData.Properties); // CategoryName property expected Assert.Empty(messageData.Measurements); } }