apm-agent-dotnet icon indicating copy to clipboard operation
apm-agent-dotnet copied to clipboard

Allow controlling the transaction name

Open alexanderpino opened this issue 5 months ago • 1 comments

Summary

When the .NET APM agent bridges OpenTelemetry Activity, transactions without a meaningful DisplayName fall back to "unknown". In desktop or background apps (WinForms/WPF, console, services) you want to stay within the Activity API surface entirely—no direct calls into Elastic.APM—yet still be able to assign descriptive transaction names.

Current Behavior

  • The agent’s ElasticActivityListener creates transactions from Activity.DisplayName, defaulting to "unknown" if none is set.
  • There is no hook for users to influence the name without touching Agent.Tracer or other Elastic-specific APIs.
  • As a result, UI-driven or batch-job Activitys often show up as "unknown" in APM.

Desired Behavior

  1. Respect a well-known Activity tag
    If an Activity carries a tag like "otel.elastic.transaction_name", use its value as the transaction name.

  2. Allow a naming delegate in options
    Expose, via configuration, a Func<Activity, string?> that runs before transaction creation—so users can customize names purely in terms of Activity.

  3. Fallback to Kind when appropriate
    When no DisplayName or custom tag is present, fall back to Activity.Kind.ToString() rather than "unknown".

Rationale

  • Zero Elastic API dependency: Instruments built around ActivitySource remain free of Elastic-specific calls.
  • Uniform tracing model: Desktop, background, and web apps can all use the same Activity-based naming strategy.
  • Better observability: Eliminates "unknown" transactions and surfaces meaningful names without boilerplate.

Example Configuration

// During agent initialization:
Agent.Setup(new AgentComponents
{
    TelemetryConfiguration = new TelemetryConfiguration
    {
        // Called whenever an Activity would spawn a transaction
        ActivityNameFormatter = activity =>
            activity.GetTagValue("otel.elastic.transaction_name")
            as string
            ?? activity.DisplayName
            ?? activity.Kind.ToString()
    }
});

// In your WinForms code, you only need to set a tag:
var activity = ActivitySource.StartActivity("SomeOp", ActivityKind.Internal);
activity?.SetTag("otel.elastic.transaction_name", "LoadCustomerDetails");
// … some logic …
activity?.Stop();

alexanderpino avatar Jun 12 '25 12:06 alexanderpino

Thanks for putting some thought into this and raising this issue, @alexanderpino.

The proposal seems reasonable. However, we now recommend the (recently GA'd) Elastic Distribution of OpenTelemetry (EDOT) for an OTel-native experience in .NET. If you do not need/want to interact with the Elastic APM APIs, the EDOT is likely a better fit for a richer OTel experience with the .NET Activity APIs. Our focus for engineering effort is on improving the EDOT and the experience of using OTel-native tools with Elastic Observability.

I'm curious, were you aware of the EDOT, and if so, have you given it a try?

stevejgordon avatar Jun 12 '25 12:06 stevejgordon

Closing as unplanned.

stevejgordon avatar Jul 25 '25 12:07 stevejgordon