Skip to content

[release/10.0-rc1] Initialize hosting trace with OTEL tags for sampling #63338

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Aug 20, 2025

Conversation

github-actions[bot]
Copy link
Contributor

@github-actions github-actions bot commented Aug 19, 2025

Backport of #62090 to release/10.0-rc1

/cc @JamesNK @rkargMsft

Initialize hosting trace with OTEL tags for sampling

Description

ASP.NET Core hosting layer creates an Activity for tracing HTTP requests. This can be listened to using ActivityListener. One of the features of ActivityListener is deciding whether to sample the activity. i.e. a callback that decides whether to invest resources to create and record the activity. See https://www.jimmybogard.com/activitysource-and-listener-in-net-5/ for more info.

.NET 9 and earlier the activity was created without any metadata about the HTTP request. It isn't possible to use info about the current HTTP request decide to sample activities based on the matching route. For example, I want my app to sample all /api/* requests and ignore everything else.

This PR adds HTTP tags to the activity as it's being created so apps can improve trace sampling. These HTTP tags are off by default and are opt-in in .NET 10 by setting AppContext.SetSwitch("Microsoft.AspNetCore.Hosting.SuppressActivityOpenTelemetryData", false). They're defaulted to off because we don't want ASP.NET Core to add only some OTEL HTTP info to the activity.

(in .NET 11 we'll do more work to improve default telemetry experience in ASP.NET Core. All OTEL HTTP info will be added to the activity. The OTEL tags will be on by default and are opt-out in .NET 11 by setting AppContext.SetSwitch("Microsoft.AspNetCore.Hosting.SuppressActivityOpenTelemetryData", true))

Fixes #50488

Customer Impact

Apps are unable to sample traces based on HTTP request information.

(note: you can do this kind of sampling if you using .NET OTEL SDK which adds its own mechanism for sampling, but not everyone uses that library)

Regression?

  • Yes
  • No

[If yes, specify the version the behavior has regressed from]

Risk

  • High
  • Medium
  • Low

Changes default to off by default. Users who want this functionality will have to set AppContext.SetSwitch("Microsoft.AspNetCore.Hosting.SuppressActivityOpenTelemetryData", false).

Verification

  • Manual (required)
  • Automated

Packaging changes reviewed?

  • Yes
  • No
  • N/A

When servicing release/2.1

  • Make necessary changes in eng/PatchConfig.props

@github-actions github-actions bot requested a review from halter73 as a code owner August 19, 2025 22:36
@JamesNK JamesNK added this to the 10.0-rc1 milestone Aug 19, 2025
@JamesNK JamesNK added the Servicing-consider Shiproom approval is required for the issue label Aug 19, 2025
@JamesNK
Copy link
Member

JamesNK commented Aug 19, 2025

Testing:

Switch added (tags now present on creation):
image

No switch (no tags, default behavior):
image

Source code:

AppContext.SetSwitch("Microsoft.AspNetCore.Hosting.SuppressActivityOpenTelemetryData", false);

var listener = new ActivityListener
{
    ShouldListenTo = source =>
    {
        // ASP.NET Core typically uses these sources:
        // "Microsoft.AspNetCore", "Microsoft.AspNetCore.Hosting", "Microsoft.AspNetCore.Server.Kestrel"
        return source.Name.StartsWith("Microsoft.AspNetCore", StringComparison.Ordinal);
    },
    Sample = (ref ActivityCreationOptions<ActivityContext> options) =>
    {
        if (options.Tags != null)
        {
            foreach (var tag in options.Tags)
            {
                Console.WriteLine($"Creation Tag: {tag.Key} = {tag.Value}");
            }
        }
        return ActivitySamplingResult.AllDataAndRecorded;
    },
    ActivityStarted = activity =>
    {
        Console.WriteLine($"Started: {activity.DisplayName}, TraceId={activity.TraceId}, SpanId={activity.SpanId}");
    },
    ActivityStopped = activity =>
    {
        Console.WriteLine($"Stopped: {activity.DisplayName}, Duration={activity.Duration}");
    }
};

ActivitySource.AddActivityListener(listener);

@danmoseley danmoseley added Servicing-approved Shiproom has approved the issue and removed Servicing-consider Shiproom approval is required for the issue labels Aug 20, 2025
Copy link
Contributor

Hi @@github-actions[bot]. This PR was just approved to be included in the upcoming servicing release. Somebody from the @dotnet/aspnet-build team will get it merged when the branches are open. Until then, please make sure all the CI checks pass and the PR is reviewed.

@wtgodbe wtgodbe merged commit 231674f into release/10.0-rc1 Aug 20, 2025
28 checks passed
@wtgodbe wtgodbe deleted the backport/pr-62090-to-release/10.0-rc1 branch August 20, 2025 15:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Servicing-approved Shiproom has approved the issue
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants