diff --git a/examples/Example.MinimalApi/Program.cs b/examples/Example.MinimalApi/Program.cs index 08ff003e..4ee8b8c0 100644 --- a/examples/Example.MinimalApi/Program.cs +++ b/examples/Example.MinimalApi/Program.cs @@ -5,7 +5,6 @@ using System.Diagnostics; using Example.MinimalApi; using OpenTelemetry; -using OpenTelemetry.Exporter; using OpenTelemetry.Trace; var builder = WebApplication.CreateBuilder(args); @@ -45,23 +44,34 @@ app.UseHttpsRedirection(); -app.MapGet("/", (IHttpClientFactory httpClientFactory, ILoggerFactory loggerFactory) => - Api.HandleRoot(httpClientFactory, loggerFactory)); +app.MapGet("/", (IHttpClientFactory httpClientFactory, ILogger logger) => + Api.HandleRoot(httpClientFactory, logger)); app.Run(); namespace Example.MinimalApi { - internal static class Api + internal class Api { public static string ActivitySourceName = "CustomActivitySource"; private static readonly ActivitySource ActivitySource = new(ActivitySourceName); - public static async Task HandleRoot(IHttpClientFactory httpClientFactory, ILoggerFactory loggerFactory) + public static async Task HandleRoot(IHttpClientFactory httpClientFactory, ILogger logger) { - var logger = loggerFactory.CreateLogger("Example.Api"); + using (logger.BeginScope(new List> + { + new("TransactionId", "12345"), + })) + { + using (logger.BeginScope("InnerScope for {TransactionId}", "99999")) + { + logger.LogInformation("Doing stuff inside inner scope"); + } + + logger.LogInformation("Doing stuff inside outer scope"); + } - logger.LogInformation("Doing stuff"); + logger.LogInformation("Doing stuff without a scope"); using var client = httpClientFactory.CreateClient(); diff --git a/src/Elastic.OpenTelemetry.Core/Diagnostics/LoggerMessages.cs b/src/Elastic.OpenTelemetry.Core/Diagnostics/LoggerMessages.cs index d3c1da81..1b969540 100644 --- a/src/Elastic.OpenTelemetry.Core/Diagnostics/LoggerMessages.cs +++ b/src/Elastic.OpenTelemetry.Core/Diagnostics/LoggerMessages.cs @@ -164,11 +164,6 @@ internal static partial class LoggerMessages - [LoggerMessage(EventId = 60, EventName = "DetectedIncludeScopes", Level = LogLevel.Warning, Message = "IncludeScopes is enabled and may cause export issues. See https://www.elastic.co/docs/reference/opentelemetry/edot-sdks/dotnet/troubleshooting.html#missing-log-records")] - internal static partial void LogDetectedIncludeScopesWarning(this ILogger logger); - - - [LoggerMessage(EventId = 70, EventName = "CompositeLoggerActivated", Level = LogLevel.Debug, Message = "CompositeLogger has been activated and drained {DeferredLogEntries} log entries.")] internal static partial void LogCompositeLoggerActivated(this ILogger logger, int deferredLogEntries); diff --git a/src/Elastic.OpenTelemetry.Core/Extensions/OpenTelemetryLoggerOptionsExtensions.cs b/src/Elastic.OpenTelemetry.Core/Extensions/OpenTelemetryLoggerOptionsExtensions.cs index 94e00e26..7b8f32a9 100644 --- a/src/Elastic.OpenTelemetry.Core/Extensions/OpenTelemetryLoggerOptionsExtensions.cs +++ b/src/Elastic.OpenTelemetry.Core/Extensions/OpenTelemetryLoggerOptionsExtensions.cs @@ -45,14 +45,10 @@ internal static void WithElasticDefaults(this OpenTelemetryLoggerOptions options options.IncludeFormattedMessage = true; - // IncludeScopes is disabled until we have a resolution to duplicate attributes - // See: - // - https://github.com/open-telemetry/opentelemetry-dotnet/issues/4324 - // - https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/39304 - // options.IncludeScopes = true; - - // TODO - Verify if we can configure the OTLP exporter to add the user agent header. - // See: https://github.com/elastic/elastic-otel-dotnet/issues/338 + // NOTE: The OTLP exporter may emit duplicate attributes when IncludeScopes is enabled, as scopes are emitted as attributes on the log record. + // This is not strictly spec compliant. When using EDOT collector or the managed OTLP endpoint, these duplicate attributes will be deduplicated. + // This works by including the first occurrence of the attribute and ignoring subsequent occurrences with the same key. + options.IncludeScopes = true; logger.LogConfiguredSignalProvider(nameof(Signals.Logs), nameof(OpenTelemetryLoggerOptions), ""); } diff --git a/src/Elastic.OpenTelemetry/Extensions/LoggerProviderBuilderExtensions.cs b/src/Elastic.OpenTelemetry/Extensions/LoggerProviderBuilderExtensions.cs index 9ce6e1e8..54bca31b 100644 --- a/src/Elastic.OpenTelemetry/Extensions/LoggerProviderBuilderExtensions.cs +++ b/src/Elastic.OpenTelemetry/Extensions/LoggerProviderBuilderExtensions.cs @@ -485,27 +485,6 @@ static void ConfigureBuilder(BuilderContext builderContex builder.ConfigureServices(sc => sc.Configure(o => o.WithElasticDefaults(logger))); - // This check is to detect if ASP.NET Core is present in the application. - // If it is, we check if IncludeScopes is enabled and log a warning because the upstream OTLP exporter - // exports duplicate attributes which does not conform to the spec and breaks the EDOT Collector. - if (builder is IDeferredLoggerProviderBuilder deferredBuilder) - { - var httpContextType = Type.GetType("Microsoft.AspNetCore.Http.HttpContext, Microsoft.AspNetCore.Http.Abstractions"); - - if (httpContextType is not null) - { - var options = deferredBuilder.Configure((sp, _) => - { - var options = sp.GetService>(); - - if (options is not null && options.Value.IncludeScopes == true) - { - logger.LogDetectedIncludeScopesWarning(); - } - }); - } - } - // Invoke any user-provided configuration. var userProvidedConfigureBuilder = builderContext.BuilderOptions.UserProvidedConfigureBuilder; if (userProvidedConfigureBuilder is not null) diff --git a/tests/Elastic.OpenTelemetry.Tests/Diagnostics/event-id-snapshot.json b/tests/Elastic.OpenTelemetry.Tests/Diagnostics/event-id-snapshot.json index 609e9d19..75c9ee2f 100644 --- a/tests/Elastic.OpenTelemetry.Tests/Diagnostics/event-id-snapshot.json +++ b/tests/Elastic.OpenTelemetry.Tests/Diagnostics/event-id-snapshot.json @@ -148,10 +148,6 @@ "eventId": 51, "eventName": "SetTag" }, - { - "eventId": 60, - "eventName": "DetectedIncludeScopes" - }, { "eventId": 70, "eventName": "CompositeLoggerActivated"