diff --git a/.vscode/settings.json b/.vscode/settings.json index 0815e2dfa70..80311886304 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,10 +9,13 @@ "contoso", "cref", "grafana", + "ilogger", "inheritdoc", "janotti", "kanzhelev", + "langword", "liudmila", + "loglevel", "mikel", "molkova", "monocytogenes", @@ -42,6 +45,7 @@ "Tracestate", "triager", "typeparam", + "ulong", "umesan", "unencrypted", "unvalidated", diff --git a/examples/Console/TestLogs.cs b/examples/Console/TestLogs.cs index 76158593796..809dda82ee3 100644 --- a/examples/Console/TestLogs.cs +++ b/examples/Console/TestLogs.cs @@ -90,8 +90,8 @@ internal static object Run(LogsOptions options) }); var logger = loggerFactory.CreateLogger(); - using (logger.BeginScope("My scope 1 with {food} and {color}", "apple", "green")) - using (logger.BeginScope("My scope 2 with {food} and {color}", "banana", "yellow")) + using (logger.BeginScope("{city}", "Seattle")) + using (logger.BeginScope("{storeType}", "Physical")) { logger.LogInformation("Hello from {name} {price}.", "tomato", 2.99); } diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md index 878fadd3638..e65a0286438 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md @@ -2,6 +2,11 @@ ## Unreleased +* Log Exporter modified to no longer prefix scope-depth when exporting ILogger + scopes as attributes. Empty keys and {OriginalFormat} key will be ignored from + scopes. + ([3843](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3843)) + ## 1.4.0-beta.2 Released 2022-Oct-17 diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/LogRecordExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/LogRecordExtensions.cs index 71811bded0f..a32c8198f97 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/LogRecordExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/LogRecordExtensions.cs @@ -78,7 +78,8 @@ internal static OtlpLogs.LogRecord ToOtlpLog(this LogRecord logRecord, SdkLimitO var attributeValueLengthLimit = sdkLimitOptions.AttributeValueLengthLimit; var attributeCountLimit = sdkLimitOptions.AttributeCountLimit ?? int.MaxValue; - // First add the generic attributes like category, eventid and exception, so they are less likely being dropped because of AttributeCountLimit + // First add the generic attributes like Category, EventId and Exception, + // so they are less likely being dropped because of AttributeCountLimit. if (!string.IsNullOrEmpty(logRecord.CategoryName)) { @@ -145,18 +146,40 @@ internal static OtlpLogs.LogRecord ToOtlpLog(this LogRecord logRecord, SdkLimitO otlpLogRecord.Flags = (uint)logRecord.TraceFlags; } - int scopeDepth = -1; logRecord.ForEachScope(ProcessScope, otlpLogRecord); void ProcessScope(LogRecordScope scope, OtlpLogs.LogRecord otlpLog) { - scopeDepth++; foreach (var scopeItem in scope) { - var scopeItemWithDepthInfo = new KeyValuePair($"[Scope.{scopeDepth}]:{scopeItem.Key}", scopeItem.Value); - if (OtlpKeyValueTransformer.Instance.TryTransformTag(scopeItemWithDepthInfo, out var result, attributeValueLengthLimit)) + if (scopeItem.Key.Equals("{OriginalFormat}") || string.IsNullOrEmpty(scopeItem.Key)) { - otlpLog.AddAttribute(result, attributeCountLimit); + // Ignore if the scope key is empty. + // Ignore if the scope key is {OriginalFormat} + // Attributes should not contain duplicates, + // and it is expensive to de-dup, so this + // exporter is going to pass the scope items as is. + // {OriginalFormat} is going to be the key + // if one uses formatted string for scopes + // and if there are nested scopes, this is + // guaranteed to create duplicate keys. + // Similar for empty keys, which is what the + // key is going to be if user simply + // passes a string as scope. + // To summarize this exporter only allows + // IReadOnlyList> + // or IEnumerable>. + // and expect users to provide unique keys. + // Note: It is possible that we allow users + // to override this exporter feature. So not blocking + // empty/{OriginalFormat} in the SDK itself. + } + else + { + if (OtlpKeyValueTransformer.Instance.TryTransformTag(scopeItem, out var result, attributeValueLengthLimit)) + { + otlpLog.AddAttribute(result, attributeCountLimit); + } } } }