diff --git a/CHANGELOG.md b/CHANGELOG.md
index cd75134dde..bf13d60fde 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,7 @@
## VNext
- [ILogger LogError and LogWarning variants write exception `ExceptionStackTrace` when `TrackExceptionsAsExceptionTelemetry` flag is set to `false`](https://github.com/microsoft/ApplicationInsights-dotnet/pull/2065)
- [The `{OriginalFormat}` field in ILogger will be emitted as `OriginalFormat` with the braces removed](https://github.com/microsoft/ApplicationInsights-dotnet/pull/2071)
+- ApplicationInsightsLoggerProvider populates structured logging key/values irrespective of whether Scopes are enabled or not.
## Version 2.15.0
- EventCounterCollector module does not add AggregationInterval as a dimension to the metric.
diff --git a/LOGGING/src/ILogger/ApplicationInsightsLogger.cs b/LOGGING/src/ILogger/ApplicationInsightsLogger.cs
index 2767dc7b5c..dfbb0d44b5 100644
--- a/LOGGING/src/ILogger/ApplicationInsightsLogger.cs
+++ b/LOGGING/src/ILogger/ApplicationInsightsLogger.cs
@@ -1,6 +1,6 @@
// -----------------------------------------------------------------------
//
-// Copyright (c) Microsoft Corporation.
+// Copyright (c) Microsoft Corporation.
// All rights reserved. 2013
//
// -----------------------------------------------------------------------
@@ -168,23 +168,23 @@ private void PopulateTelemetry(ISupportProperties telemetryItem, TState
dict["EventName"] = eventId.Name;
}
- if (this.applicationInsightsLoggerOptions.IncludeScopes)
+ if (state is IReadOnlyCollection> stateDictionary)
{
- if (state is IReadOnlyCollection> stateDictionary)
+ foreach (KeyValuePair item in stateDictionary)
{
- foreach (KeyValuePair item in stateDictionary)
+ if (item.Key == "{OriginalFormat}")
{
- if (item.Key == "{OriginalFormat}")
- {
- dict["OriginalFormat"] = Convert.ToString(item.Value, CultureInfo.InvariantCulture);
- }
- else
- {
- dict[item.Key] = Convert.ToString(item.Value, CultureInfo.InvariantCulture);
- }
+ dict["OriginalFormat"] = Convert.ToString(item.Value, CultureInfo.InvariantCulture);
+ }
+ else
+ {
+ dict[item.Key] = Convert.ToString(item.Value, CultureInfo.InvariantCulture);
}
}
+ }
+ if (this.applicationInsightsLoggerOptions.IncludeScopes)
+ {
if (this.ExternalScopeProvider != null)
{
StringBuilder stringBuilder = new StringBuilder();
diff --git a/LOGGING/test/ILogger.Tests/ILoggerIntegrationTests.cs b/LOGGING/test/ILogger.Tests/ILoggerIntegrationTests.cs
index 1a5918964c..72e1168a4b 100644
--- a/LOGGING/test/ILogger.Tests/ILoggerIntegrationTests.cs
+++ b/LOGGING/test/ILogger.Tests/ILoggerIntegrationTests.cs
@@ -23,6 +23,54 @@ namespace Microsoft.ApplicationInsights
[TestClass]
public class ILoggerIntegrationTests
{
+ ///
+ /// Ensures that populates params for structured logging into custom properties .
+ ///
+ [TestMethod]
+ [TestCategory("ILogger")]
+ public void ApplicationInsightsLoggerPopulateStructureLoggingParamsIntoCustomProperties()
+ {
+ List itemsReceived = new List();
+
+ // Scopes are enabled.
+ IServiceProvider serviceProvider = ILoggerIntegrationTests.SetupApplicationInsightsLoggerIntegration(
+ (telemetryItem, telemetryProcessor) => itemsReceived.Add(telemetryItem),
+ configureTelemetryConfiguration: null,
+ configureApplicationInsightsOptions: (appInsightsLoggerOptions) => appInsightsLoggerOptions.IncludeScopes = true);
+
+ ILogger testLogger = serviceProvider.GetRequiredService>();
+ testLogger.LogInformation("Testing structured with {CustomerName} {Age}", "TestCustomerName", 20);
+
+ Assert.AreEqual("Testing structured with TestCustomerName 20", (itemsReceived[0] as TraceTelemetry).Message);
+ var customProperties = (itemsReceived[0] as TraceTelemetry).Properties;
+ Assert.IsTrue(customProperties["CustomerName"].Equals("TestCustomerName"));
+ Assert.IsTrue(customProperties["Age"].Equals("20"));
+ }
+
+ ///
+ /// Ensures that populates params for structured logging into custom properties .
+ ///
+ [TestMethod]
+ [TestCategory("ILogger")]
+ public void ApplicationInsightsLoggerPopulateStructureLoggingParamsIntoCustomPropertiesWhenScopeDisabled()
+ {
+ List itemsReceived = new List();
+
+ // Disable scope
+ IServiceProvider serviceProvider = ILoggerIntegrationTests.SetupApplicationInsightsLoggerIntegration(
+ (telemetryItem, telemetryProcessor) => itemsReceived.Add(telemetryItem),
+ configureTelemetryConfiguration: null,
+ configureApplicationInsightsOptions: (appInsightsLoggerOptions) => appInsightsLoggerOptions.IncludeScopes = false);
+
+ ILogger testLogger = serviceProvider.GetRequiredService>();
+ testLogger.LogInformation("Testing structured with {CustomerName} {Age}", "TestCustomerName", 20);
+
+ Assert.AreEqual("Testing structured with TestCustomerName 20", (itemsReceived[0] as TraceTelemetry).Message);
+ var customProperties = (itemsReceived[0] as TraceTelemetry).Properties;
+ Assert.IsTrue(customProperties["CustomerName"].Equals("TestCustomerName"));
+ Assert.IsTrue(customProperties["Age"].Equals("20"));
+ }
+
///
/// Ensures that is invoked when user logs using .
///
@@ -142,7 +190,7 @@ public void ApplicationInsightsLoggerLogsExceptionAsTraceWhenSwitchIsFalse()
Assert.AreEqual(SeverityLevel.Error, (itemsReceived[1] as TraceTelemetry).SeverityLevel);
Assert.AreEqual("LoggerMessage", (itemsReceived[1] as TraceTelemetry).Message);
-
+
Assert.IsTrue((itemsReceived[1] as TraceTelemetry).Properties["ExceptionMessage"].Contains("StackTraceEnabled"));
Assert.IsTrue((itemsReceived[1] as TraceTelemetry).Properties.ContainsKey("ExceptionStackTrace"));
@@ -263,7 +311,7 @@ public void DefaultLoggerOptionsAreCorrectlyRegistered()
IServiceProvider serviceProvider = ILoggerIntegrationTests.SetupApplicationInsightsLoggerIntegration(
(telemetryItem, telemetryProcessor) => { });
- IOptions registeredOptions =
+ IOptions registeredOptions =
serviceProvider.GetRequiredService>();
Assert.IsTrue(registeredOptions.Value.TrackExceptionsAsExceptionTelemetry);