-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Description
🚀 Feature
I should note that I am trying to integrate the Datadog APM, but I believe this applies to OpenTracing/OpenTelemetry as well.
In trying to integration the Datadog APM, I realized that the the annotated context containing the path pattern is available only after HTTP handlers are called. At a high level, I understand why this is the case, but it complicates adding context to telemetry.
For example, when integrating the Datadog APM, the most straightforward way is to use the WrapHandler function:
mux := runtime.NewServeMux()
handler = httptrace.WrapHandler(mux, "service_name", "")The second parameters here is meant to be the resource name. Datadog also offers a WithResourceNamer to dynamically generate the resource name (typically the HTTP method and path pattern). Unfortunately, WithResourceNamer works at the handler level and therefore it cannot be used to access the path pattern, just the full URL.
When looking at how Datadog integrates with other HTTP libraries, including the standard ServerMux, there is usually some capability to lookup the handler and route based on the request.
Unfortunately, grpc-gateway doesn't expose the route matching logic in a way that can be accessed outside of ServeHTTP, making it very difficult to know the parameterized route at the "wrapping" layer.
Ultimately, it would be nice if the route matching logic could be extracted from ServeHTTP in a way that it was both fast and re-usable to be able to lookup the route given a request.
Workarounds
Yes, I could also use the gRPC client/server integration as the docs suggest. In fact, I also do this. However, telemetry at the HTTP layer is very useful.
As a workaround, I am able to use runtime.WithMetadata as recommended here to inject the resource name as a span tag, but it feels a bit hacky and disjointed:
runtime.WithMetadata(func(ctx context.Context, req *http.Request) metadata.MD {
span, ok := tracer.SpanFromContext(ctx)
if ok {
if path, ok := runtime.HTTPPathPattern(ctx); ok {
span.SetTag(ext.ResourceName, req.Method+" "+path)
}
}
return metadata.MD{}
}),