Skip to content

Endpoint diagnostics metadata #11785

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

Open
JamesNK opened this issue Jul 2, 2019 · 4 comments
Open

Endpoint diagnostics metadata #11785

JamesNK opened this issue Jul 2, 2019 · 4 comments
Labels
affected-few This issue impacts only small number of customers area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates enhancement This issue represents an ask for new feature or an enhancement to an existing one feature-routing severity-major This label is used by an internal tool
Milestone

Comments

@JamesNK
Copy link
Member

JamesNK commented Jul 2, 2019

We've just added an endpoint matched event to diagnostic listeners with #11685

From this event AppInsights/OpenTelemetry can get the HttpContext, and the matched endpoint via HttpContext.GetEndpoint() and then look at endpoint metadata. Endpoints produced by app frameworks are adding typed metadata about the endpoint to Endpoint.Metadata. For example, gRPC adds GrpcMethodMetadata to gRPC endpoints, MVC adds ActionDescriptor to MVC endpoints, etc. Using this metadata telemetry frameworks can figure out what the request is for.

The problem with this is the metadata is all strongly typed, which means telemetry frameworks will either need complex reflection or dependencies to query it.

// Getting gRPC method name from metadata
var methodName = HttpContext.GetEndpoint().Metadata.GetMetadata<GrpcMethodMetadata>().Method.FullName;

We could make this easier by having some generic diagnostic metadata that app frameworks set when building endpoints:

public class EndpointDiagnosticsMetadata
{
    public Dictionary<string, string> Diagnostics { get; set; }
}
EndpointBuilder endpointBuilder = CreateGrpcEndpoint(method);

// Loosely typed diagnostics values
var diagnostics = new Dictionary<string, string>
{
    ["grpc.method_name"] = method.FullName,
    ["grpc.method_type"] = method.Type.ToString(),
    ["grpc.service"] = typeof(TService).FullName,
};
endpointBuilder.Metadata.Add(new EndpointDiagnosticsMetadata(diagnostics));

// Continue to add strongly typed endpoint metadata
endpointBuilder.Metadata.Add(new GrpcMethodMetadata(method));

var endpoint = endpointBuilder.Build();

Now telemetry frameworks can simply copy name/values from the diagnostics collection.

Benefits:

  • Remove the need for complex reflection or dependencies in telemetry frameworks
  • New and community web frameworks could add diagnostics about endpoints that would automatically light up in telemetry frameworks. They don't need to add support for app frameworks one-by-one.

@davidfowl @rynowak @lmolkova @SergeyKanzhelev

@JamesNK
Copy link
Member Author

JamesNK commented Jul 2, 2019

Thinking about this more, it does kind of serve the same purpose as the hosting activity and its tags collection. Tags are already untyped string name/values.

Maybe the contents of EndpointDiagnosticsMetadata.Diagnostics would automatically be set to in the hosting activity's tags by EndpointRoutingMiddleware if diagnostics is enabled.

The benefit is telemetry frameworks can get this info when an endpoint is matched rather than wait for the request to end. This is useful for long lived requests (gRPC streaming, SignalR long polling)

@Eilon Eilon added the area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates label Jul 2, 2019
@lmolkova
Copy link

lmolkova commented Jul 2, 2019

ndpoints produced by app frameworks are adding typed metadata about the endpoint to Endpoint.Metadata. For example, gRPC adds GrpcMethodMetadata to gRPC endpoints, MVC adds ActionDescriptor to MVC endpoints, etc. Using this metadata telemetry frameworks can figure out what the request is for.

Can you help me understand how we can tell the difference between endpoint today? By looking into the type of HttpContext.GetEndpoint() or some properties on it?

From the telemetry framework standpoint Activity.Tags is the best place for any metadata.

Historically, there are two kinds of instrumentation approaches with Activity

  1. ASP.NET Core/HttpClient - telemetry system is well aware of DS payloads and uses reflection to parse them to extract exactly what they need.
  2. The rest (all non-standard libraries) - tracing system cannot depend on e.g. ServiceBus SDK to parse ServiceBus DS payloads. Assuming 100s of libraries are instrumented, tracing systems cannot know how to parse their payloads - it does not scale. So we rely on ServiceBus SDK/particular library to put everything they think are important into the Activity.Tags - we know how to access them.

So the bottom line:

  • reflection for ASP.NET Core is not a problem - we depend on ASP.NET Core libs and their behavior a lot anyway - not just to parse the payloads, but use DI and integrate nicely.
  • if you what to add more things - tracing systems will be happy to use Activity.Tags without reflection

@rynowak
Copy link
Member

rynowak commented Jul 2, 2019

@lmolkova @davidfowl

I think we have to made a decision about whether we want things like the controller/action name (and the equivalent for SignalR/gRPC/etc) to be part of the activity or not.

I kinda expect that if we attach a loosely-typed property bag of "info" to endpoints, it's not going to be good enough for some of our scenarios.

@JamesNK
Copy link
Member Author

JamesNK commented Jul 3, 2019

Can you help me understand how we can tell the difference between endpoint today? By looking into the type of HttpContext.GetEndpoint() or some properties on it?

Brief overview of endpoints and metadata:

  1. Application starts up. Endpoints are registered:

    app.UseRouting();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapBlazorHub(typeof(Hub));
        endpoints.MapGrpcService<ExampleService>();
        endpoints.MapControllerRoute("/{controller}/{action}");
    });

    Each of these different framework calls could register multiple endpoints. For example, an endpoint is created for each gRPC method on ExampleService type. Each gRPC endpoint will have its own metadata: route pattern, method name, method type, etc.

    MVC, Razor pages, SignalR, Blazor, will each do the same thing. Endpoints are create for each MVC action, Razor page file, SignalR hub, etc. Each created endpoint has metadata about itself.

    It's key to keep in mind that endpoints are denormalized. MapControllerRoute("/{controller}/{action}") doesn't create one endpoint with that pattern. It creates one endpoint for every matching action using the pattern. This is why metadata like ActionDescriptor can be added to each endpoint.

  2. Request comes in, is matched to an endpoint using its pattern. The diagnostic event David added is raised after matching - Add a diagnostic source event that fires when a route is matched #11685

  3. Any middleware configured between UseRouting and UseEndpoints executes (e.g. authZ, authN). Middleware can use metadata from the endpoint. For example, authz middleware will look for AuthorizeAttribute on the matched endpoint.

  4. Endpoint is executed. This is when MVC, Razor pages, SignalR, Blazor, gRPC run.

@mkArtakMSFT mkArtakMSFT added this to the Backlog milestone Jul 3, 2019
@mkArtakMSFT mkArtakMSFT added the enhancement This issue represents an ask for new feature or an enhancement to an existing one label Jul 3, 2019
@SteveSandersonMS SteveSandersonMS added affected-few This issue impacts only small number of customers severity-major This label is used by an internal tool labels Nov 6, 2020 — with ASP.NET Core Issue Ranking
@javiercn javiercn added the jcn-p1 label Nov 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
affected-few This issue impacts only small number of customers area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates enhancement This issue represents an ask for new feature or an enhancement to an existing one feature-routing severity-major This label is used by an internal tool
Projects
None yet
Development

No branches or pull requests

7 participants