opentelemetry-dotnet-contrib icon indicating copy to clipboard operation
opentelemetry-dotnet-contrib copied to clipboard

[AspNetCoreInstrumentation] Incorrect value for `http.route` when using conventional routing

Open alanwest opened this issue 1 year ago • 5 comments

Bug

The http.route attribute is one of the more important HTTP attributes because users commonly wish to facet their metric and span data on http.route in order to understand the performance characteristics of specific endpoints in their applications.

ASP.NET Core apps that use conventional routing are not well supported. With conventional routing, it is common that a single route template matches many distinct routes. For these applications the instrumentation sets http.route to the value of the route template and not to a value that represents the actual route invoked. In turn, this means users lose the ability to understand the performance of specific endpoints.

This bug was introduced in open-telemetry/opentelemetry-dotnet#5026 to conform with the behavior of ASP.NET Core 8 which natively emits the http.server.request.duration metric. We wanted to avoid a surprise change in behavior for users migrating from earlier versions of .NET to .NET 8. Fixing this bug should be done in coordination with the ASP.NET Core team.

Reproduce

Run:

dotnet new mvc

The following is abbreviated, but Program.cs will look something like:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();

var app = builder.Build();
app.UseRouting();
app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

The application's HomeController contains multiple actions - e.g., Index, Privacy, etc. Invoking any of these endpoints will result in a metric and span with the http.route attribute set to {controller=Home}/{action=Index}/{id?}.

Suggested fix

Well-known route parameters (e.g., controller, action) should be replaced by their actual values. Using the HttpContext.GetRouteData() method is one way to get the actual route parameter values.

One potential option would be to apply the fix for .NET 6 and .NET 7 users gated by an environment variable.

alanwest avatar Nov 16 '23 00:11 alanwest