Shuzheng
Shuzheng

Reputation: 14018

How can I configure Azure.Monitor.OpenTelemetry.AspNetCore to add custom properties to any type of telemetry, not just request traces?

I'm using a OTEL tracer processor (CorrelationIdActivityEnrichingProcessor) to add a custom properties to traces emitted to Application Insights.

However, while it successfully add custom properties to request telemetry, nothing is added to trace telemetry:

enter image description here

How can I configure Azure.Monitor.OpenTelemetry.AspNetCore to add custom properties to any type of telemetry, not just request traces?

Code:

        // Add correlation ID to Application Insights telemetry as a custom property
        builder.Services.ConfigureOpenTelemetryTracerProvider((sp, tracerBuilder) => tracerBuilder.AddProcessor(
            new CorrelationIdActivityEnrichingProcessor(
                sp.GetRequiredService<IHttpContextAccessor>(),
                sp.GetRequiredService<ILogger<CorrelationIdActivityEnrichingProcessor>>()
            )
        ));

        builder.Services.AddOpenTelemetry()
        .UseAzureMonitor(options =>
        {
            options.EnableLiveMetrics = true;
        }).ConfigureResource(resourceBuilder =>
        {
            resourceBuilder.AddAttributes([
                new KeyValuePair<string, object>("service.name", "MyApp")
            ]);
        });


public class CorrelationIdActivityEnrichingProcessor(IHttpContextAccessor httpContextAccessor, ILogger<CorrelationIdActivityEnrichingProcessor> logger) : BaseProcessor<Activity>
{
    public override void OnStart(Activity activity)
    {
        var httpContext = httpContextAccessor.HttpContext;
        var correlationId = httpContext?.Request.Headers["correlation-id"].FirstOrDefault();
        if (correlationId != null)
        {
            // logger.LogDebug("Enriching activity with correlation ID: {CorrelationId}", correlationId);
            activity.SetTag("CorrelationId", correlationId);
        }
    }
}

Upvotes: 0

Views: 59

Answers (2)

cijothomas
cijothomas

Reputation: 3196

CorrelationIdActivityEnrichingProcessor is an ActivityProcessor and only applies to Activity, which is what becomes RequestTelemetry, DependencyTelemetry. TraceTelemetry is coming from ILogger logs, so you need to write a similar LogRecordProcessor to achieve that.

Or it maybe easier to put the CorrelationId into ILogger Scopes:

logger.BeginScope(new List<KeyValuePair<string, object>>
        {
            new KeyValuePair<string, object>("CorrelationId", correlationId),
        }

(Remember to turn on Scopes via https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggerOptions.cs#L36)

Upvotes: 1

Suresh Chikkam
Suresh Chikkam

Reputation: 3448

Instead of only adding the custom processor to the tracer provider using the old method (ConfigureOpenTelemetryTracerProvider), use the AddOpenTelemetry() method to configure the tracer and check custom properties are added to all traces.

builder.Services.AddOpenTelemetry()
    .WithTracing(tracingBuilder =>
    {
        tracingBuilder
            .AddAspNetCoreInstrumentation() // Ensure ASP.NET Core tracing is enabled
            .AddAzureMonitorTraceExporter(options =>
            {
                options.ConnectionString = "InstrumentationKey=YOUR_INSTRUMENTATION_KEY"; // Add your key
            })
            .AddProcessor(new CustomTelemetryProcessor(
                builder.Services.BuildServiceProvider().GetRequiredService<ILogger<CustomTelemetryProcessor>>()
            ));
    });
  • In the custom processor (CustomTelemetryProcessor), override the OnStart method to add custom properties such as CorrelationId and MyCustomProperty to all traces
public class CustomTelemetryProcessor : BaseProcessor<Activity>
{
    private readonly ILogger<CustomTelemetryProcessor> _logger;

    public CustomTelemetryProcessor(ILogger<CustomTelemetryProcessor> logger)
    {
        _logger = logger;
    }

    public override void OnStart(Activity activity)
    {
        _logger.LogInformation("Adding custom property to activity: {ActivityId}", activity.Id);

        // Add custom properties to the activity
        activity.SetTag("MyCustomProperty", "CustomValue123");

        // Generate and add CorrelationId if not present
        if (string.IsNullOrEmpty(activity.ParentId))
        {
            string correlationId = Guid.NewGuid().ToString();
            activity.SetTag("CorrelationId", correlationId);
        }
    }

    public override void OnEnd(Activity activity)
    {
        _logger.LogInformation("Activity ended with ID: {ActivityId}", activity.Id);
    }
}

By using this processor, the MyCustomProperty and CorrelationId will be applied to every trace, including dependencies, exceptions, and other telemetry types, not just HTTP requests.

Result:

enter image description here

Upvotes: 1

Related Questions