Expose LookupResult params field
devillecodes opened this issue · comments
We would like to be able to instrument httptreemux for observability with Datadog, similar to what was done for julienschmidt/httprouter in DataDog/dd-trace-go/contrib/julienschmidt/httprouter/httprouter.go.
In short, in order to build the Datadog resource name from the request path we need access to the LookupResult params field. For this reason we would like to export this struct field, i.e. rename LookupResult.params
to LookupResult.Params
.
This is what the router could could look like to add Datadog trace support to httptreemux:
// Package httptreemux provides functions to trace the dimfeld/httptreemux/v5 package (https://github.com/dimfeld/httptreemux).
package httptreemux // import "gopkg.in/DataDog/dd-trace-go.v1/contrib/dimfeld/httptreemux/v5"
import (
"math"
"net/http"
"strings"
httptrace "gopkg.in/DataDog/dd-trace-go.v1/contrib/net/http"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
"gopkg.in/DataDog/dd-trace-go.v1/internal/log"
"github.com/dimfeld/httptreemux/v5"
)
// Router is a traced version of httptreemux.TreeMux.
type Router struct {
*httptreemux.TreeMux
config *routerConfig
}
// New returns a new router augmented with tracing.
func New(opts ...RouterOption) *Router {
cfg := new(routerConfig)
defaults(cfg)
for _, fn := range opts {
fn(cfg)
}
if !math.IsNaN(cfg.analyticsRate) {
cfg.spanOpts = append(cfg.spanOpts, tracer.Tag(ext.EventSampleRate, cfg.analyticsRate))
}
cfg.spanOpts = append(cfg.spanOpts, tracer.Measured())
log.Debug("contrib/dimfeld/httptreemux/v5: Configuring Router: %#v", cfg)
return &Router{httptreemux.New(), cfg}
}
// ServeHTTP implements http.Handler.
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// get the resource associated to this request
route := req.URL.Path
lr, _ := r.Lookup(w, req)
for k, v := range lr.Params {
// replace parameter values in URL path with their names
route = strings.Replace(route, v, ":"+k, 1)
}
resource := req.Method + " " + route
// pass r.TreeMux to avoid a circular reference panic on calling r.ServeHTTP
httptrace.TraceAndServe(r.TreeMux, w, req, &httptrace.ServeConfig{
Service: r.config.serviceName,
Resource: resource,
SpanOpts: r.config.spanOpts,
})
}
The plan is to submit a PR against DataDog/dd-trace-go once the necessary access to the LookupResult params is granted.