diff --git a/contrib/gorilla/mux/mux.go b/contrib/gorilla/mux/mux.go index 9f7d996813..c8968e2100 100644 --- a/contrib/gorilla/mux/mux.go +++ b/contrib/gorilla/mux/mux.go @@ -97,18 +97,27 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { var ( match mux.RouteMatch spanopts []ddtrace.StartSpanOption - route = "unknown" ) // get the resource associated to this request if r.Match(req, &match) && match.Route != nil { - if r, err := match.Route.GetPathTemplate(); err == nil { - route = r - } if h, err := match.Route.GetHostTemplate(); err == nil { spanopts = append(spanopts, tracer.Tag("mux.host", h)) } } spanopts = append(spanopts, r.config.spanOpts...) - resource := req.Method + " " + route + resource := r.config.resourceNamer(r, req) httputil.TraceAndServe(r.Router, w, req, r.config.serviceName, resource, spanopts...) } + +// defaultResourceNamer attempts to quantize the resource for an HTTP request by +// retrieving the path template associated with the route from the request. +func defaultResourceNamer(router *Router, req *http.Request) string { + var match mux.RouteMatch + // get the resource associated with the given request + if router.Match(req, &match) && match.Route != nil { + if r, err := match.Route.GetPathTemplate(); err == nil { + return req.Method + " " + r + } + } + return req.Method + " unknown" +} diff --git a/contrib/gorilla/mux/mux_test.go b/contrib/gorilla/mux/mux_test.go index 9943c2a11f..b681f29de6 100644 --- a/contrib/gorilla/mux/mux_test.go +++ b/contrib/gorilla/mux/mux_test.go @@ -182,6 +182,26 @@ func TestAnalyticsSettings(t *testing.T) { }) } +func TestResourceNamer(t *testing.T) { + staticName := "static resource name" + staticNamer := func(*Router, *http.Request) string { + return staticName + } + + assert := assert.New(t) + mt := mocktracer.Start() + defer mt.Stop() + mux := NewRouter(WithResourceNamer(staticNamer)) + mux.Handle("/200", okHandler()).Host("localhost") + r := httptest.NewRequest("GET", "http://localhost/200", nil) + w := httptest.NewRecorder() + mux.ServeHTTP(w, r) + + spans := mt.FinishedSpans() + assert.Equal(1, len(spans)) + assert.Equal(staticName, spans[0].Tag(ext.ResourceName)) +} + func router() http.Handler { mux := NewRouter(WithServiceName("my-service")) mux.Handle("/200", okHandler()) diff --git a/contrib/gorilla/mux/option.go b/contrib/gorilla/mux/option.go index 166dcda852..2283fb887c 100644 --- a/contrib/gorilla/mux/option.go +++ b/contrib/gorilla/mux/option.go @@ -7,6 +7,7 @@ package mux import ( "math" + "net/http" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace" "gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig" @@ -16,6 +17,7 @@ type routerConfig struct { serviceName string spanOpts []ddtrace.StartSpanOption // additional span options to be applied analyticsRate float64 + resourceNamer func(*Router, *http.Request) string } // RouterOption represents an option that can be passed to NewRouter. @@ -24,6 +26,7 @@ type RouterOption func(*routerConfig) func defaults(cfg *routerConfig) { cfg.analyticsRate = globalconfig.AnalyticsRate() cfg.serviceName = "mux.router" + cfg.resourceNamer = defaultResourceNamer } // WithServiceName sets the given service name for the router. @@ -63,3 +66,11 @@ func WithAnalyticsRate(rate float64) RouterOption { } } } + +// WithResourceNamer specifies a quantizing function which will be used to +// obtain the resource name for a given request. +func WithResourceNamer(namer func(router *Router, req *http.Request) string) RouterOption { + return func(cfg *routerConfig) { + cfg.resourceNamer = namer + } +}