Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions examples/Example.MinimalApi/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System.Diagnostics;
using Example.MinimalApi;
using OpenTelemetry;
using OpenTelemetry.Exporter;
using OpenTelemetry.Trace;

var builder = WebApplication.CreateBuilder(args);
Expand Down Expand Up @@ -45,23 +44,34 @@

app.UseHttpsRedirection();

app.MapGet("/", (IHttpClientFactory httpClientFactory, ILoggerFactory loggerFactory) =>
Api.HandleRoot(httpClientFactory, loggerFactory));
app.MapGet("/", (IHttpClientFactory httpClientFactory, ILogger<Api> 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<IResult> HandleRoot(IHttpClientFactory httpClientFactory, ILoggerFactory loggerFactory)
public static async Task<IResult> HandleRoot(IHttpClientFactory httpClientFactory, ILogger logger)
{
var logger = loggerFactory.CreateLogger("Example.Api");
using (logger.BeginScope(new List<KeyValuePair<string, object>>
{
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();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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), "<n/a>");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -485,27 +485,6 @@ static void ConfigureBuilder(BuilderContext<LoggerProviderBuilder> builderContex

builder.ConfigureServices(sc => sc.Configure<OpenTelemetryLoggerOptions>(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<IOptions<OpenTelemetryLoggerOptions>>();

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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,6 @@
"eventId": 51,
"eventName": "SetTag"
},
{
"eventId": 60,
"eventName": "DetectedIncludeScopes"
},
{
"eventId": 70,
"eventName": "CompositeLoggerActivated"
Expand Down
Loading