diff --git a/contrib/gorilla/mux/mux.go b/contrib/gorilla/mux/mux.go index 35a276a67b..ae95e3156c 100644 --- a/contrib/gorilla/mux/mux.go +++ b/contrib/gorilla/mux/mux.go @@ -94,6 +94,10 @@ func NewRouter(opts ...RouterOption) *Router { // We only need to rewrite this function to be able to trace // all the incoming requests to the underlying multiplexer func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { + if r.config.ignoreRequest(req) { + r.Router.ServeHTTP(w, req) + return + } var ( match mux.RouteMatch spanopts []ddtrace.StartSpanOption diff --git a/contrib/gorilla/mux/mux_test.go b/contrib/gorilla/mux/mux_test.go index 632d1c3ce7..5ff748c70d 100644 --- a/contrib/gorilla/mux/mux_test.go +++ b/contrib/gorilla/mux/mux_test.go @@ -199,6 +199,40 @@ func TestAnalyticsSettings(t *testing.T) { }) } +func TestIgnoreRequestOption(t *testing.T) { + tests := []struct { + url string + spanCount int + }{ + { + url: "/skip", + spanCount: 0, + }, + { + url: "/200", + spanCount: 1, + }, + } + mux := NewRouter(WithIgnoreRequest(func(req *http.Request) bool { + return req.URL.Path == "/skip" + })) + mux.Handle("/skip", okHandler()).Host("localhost") + mux.Handle("/200", okHandler()).Host("localhost") + + for _, test := range tests { + t.Run(test.url, func(t *testing.T) { + mt := mocktracer.Start() + defer mt.Stop() + r := httptest.NewRequest("GET", "http://localhost"+test.url, nil) + w := httptest.NewRecorder() + mux.ServeHTTP(w, r) + + spans := mt.FinishedSpans() + assert.Equal(t, test.spanCount, len(spans)) + }) + } +} + func TestResourceNamer(t *testing.T) { staticName := "static resource name" staticNamer := func(*Router, *http.Request) string { diff --git a/contrib/gorilla/mux/option.go b/contrib/gorilla/mux/option.go index f03ce3e39c..704650295c 100644 --- a/contrib/gorilla/mux/option.go +++ b/contrib/gorilla/mux/option.go @@ -21,6 +21,7 @@ type routerConfig struct { finishOpts []ddtrace.FinishOption // span finish options to be applied analyticsRate float64 resourceNamer func(*Router, *http.Request) string + ignoreRequest func(*http.Request) bool } // RouterOption represents an option that can be passed to NewRouter. @@ -37,6 +38,15 @@ func defaults(cfg *routerConfig) { cfg.serviceName = svc } cfg.resourceNamer = defaultResourceNamer + cfg.ignoreRequest = func(_ *http.Request) bool { return false } +} + +// WithIgnoreRequest holds the function to use for determining if the +// incoming HTTP request tracing should be skipped. +func WithIgnoreRequest(f func(*http.Request) bool) RouterOption { + return func(cfg *routerConfig) { + cfg.ignoreRequest = f + } } // WithServiceName sets the given service name for the router.