Skip to content

Commit

Permalink
contrib: implement http.route in missing contribs (#2234)
Browse files Browse the repository at this point in the history
  • Loading branch information
rarguelloF committed Oct 23, 2023
1 parent 00055c7 commit e1a2437
Show file tree
Hide file tree
Showing 11 changed files with 82 additions and 23 deletions.
16 changes: 14 additions & 2 deletions contrib/dimfeld/httptreemux.v5/httptreemux.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,13 @@ func New(opts ...RouterOption) *Router {
// ServeHTTP implements http.Handler.
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
resource := r.config.resourceNamer(r.TreeMux, w, req)
route, _ := getRoute(r.TreeMux, w, req)
// 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,
Route: route,
})
}

Expand Down Expand Up @@ -82,11 +84,13 @@ func NewWithContext(opts ...RouterOption) *ContextRouter {
// ServeHTTP implements http.Handler.
func (r *ContextRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
resource := r.config.resourceNamer(r.TreeMux, w, req)
route, _ := getRoute(r.TreeMux, w, req)
// 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,
Route: route,
})
}

Expand All @@ -95,10 +99,18 @@ func (r *ContextRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// route from the request. If the lookup fails to find a match the route is set
// to "unknown".
func defaultResourceNamer(router *httptreemux.TreeMux, w http.ResponseWriter, req *http.Request) string {
route, ok := getRoute(router, w, req)
if !ok {
route = "unknown"
}
return req.Method + " " + route
}

func getRoute(router *httptreemux.TreeMux, w http.ResponseWriter, req *http.Request) (string, bool) {
route := req.URL.Path
lr, found := router.Lookup(w, req)
if !found {
return req.Method + " unknown"
return "", false
}
for k, v := range lr.Params {
// replace parameter surrounded by a set of "/", i.e. ".../:param/..."
Expand All @@ -113,5 +125,5 @@ func defaultResourceNamer(router *httptreemux.TreeMux, w http.ResponseWriter, re
newP = "/:" + k
route = strings.Replace(route, oldP, newP, 1)
}
return req.Method + " " + route
return route, true
}
4 changes: 4 additions & 0 deletions contrib/dimfeld/httptreemux.v5/httptreemux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func TestHttpTracer200(t *testing.T) {
assert.Equal("http://example.com"+url, s.Tag(ext.HTTPURL))
assert.Equal("testvalue", s.Tag("testkey"))
assert.Equal(nil, s.Tag(ext.Error))
assert.Equal("/200", s.Tag(ext.HTTPRoute))
}

func TestHttpTracer404(t *testing.T) {
Expand Down Expand Up @@ -71,6 +72,7 @@ func TestHttpTracer404(t *testing.T) {
assert.Equal("http://example.com"+url, s.Tag(ext.HTTPURL))
assert.Equal("testvalue", s.Tag("testkey"))
assert.Equal(nil, s.Tag(ext.Error))
assert.NotContains(s.Tags(), ext.HTTPRoute)
}

func TestHttpTracer500(t *testing.T) {
Expand Down Expand Up @@ -98,6 +100,7 @@ func TestHttpTracer500(t *testing.T) {
assert.Equal("http://example.com"+url, s.Tag(ext.HTTPURL))
assert.Equal("testvalue", s.Tag("testkey"))
assert.Equal("500: Internal Server Error", s.Tag(ext.Error).(error).Error())
assert.Equal("/500", s.Tag(ext.HTTPRoute))
}

func TestDefaultResourceNamer(t *testing.T) {
Expand Down Expand Up @@ -170,6 +173,7 @@ func TestDefaultResourceNamer(t *testing.T) {
assert.Equal(tc.method, s.Tag(ext.HTTPMethod))
assert.Equal("http://example.com"+tc.url, s.Tag(ext.HTTPURL))
assert.Equal(nil, s.Tag(ext.Error))
assert.Equal(tc.path, s.Tag(ext.HTTPRoute))
})
}
}
Expand Down
11 changes: 7 additions & 4 deletions contrib/emicklei/go-restful.v3/restful.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,13 @@ func FilterFunc(configOpts ...Option) restful.FilterFunction {
log.Debug("contrib/emicklei/go-restful/v3: Creating tracing filter: %#v", cfg)
spanOpts := []ddtrace.StartSpanOption{tracer.ServiceName(cfg.serviceName)}
return func(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
spanOpts := append(spanOpts, tracer.ResourceName(req.SelectedRoutePath()))
spanOpts = append(spanOpts, tracer.Tag(ext.Component, componentName))
spanOpts = append(spanOpts, tracer.Tag(ext.SpanKind, ext.SpanKindServer))

spanOpts := append(
spanOpts,
tracer.ResourceName(req.SelectedRoutePath()),
tracer.Tag(ext.Component, componentName),
tracer.Tag(ext.SpanKind, ext.SpanKindServer),
tracer.Tag(ext.HTTPRoute, req.SelectedRoutePath()),
)
if !math.IsNaN(cfg.analyticsRate) {
spanOpts = append(spanOpts, tracer.Tag(ext.EventSampleRate, cfg.analyticsRate))
}
Expand Down
1 change: 1 addition & 0 deletions contrib/emicklei/go-restful.v3/restful_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ func TestTrace200(t *testing.T) {
assert.Equal("http://example.com/user/123", span.Tag(ext.HTTPURL))
assert.Equal(ext.SpanKindServer, span.Tag(ext.SpanKind))
assert.Equal("emicklei/go-restful.v3", span.Tag(ext.Component))
assert.Equal("/user/{id}", span.Tag(ext.HTTPRoute))
}

func TestError(t *testing.T) {
Expand Down
7 changes: 5 additions & 2 deletions contrib/gofiber/fiber.v2/fiber.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,10 @@ func Middleware(opts ...Option) func(c *fiber.Ctx) error {
opts = append(opts, tracer.ChildOf(spanctx))
}
opts = append(opts, cfg.spanOpts...)
opts = append(opts, tracer.Tag(ext.Component, componentName))
opts = append(opts, tracer.Tag(ext.SpanKind, ext.SpanKindServer))
opts = append(opts,
tracer.Tag(ext.Component, componentName),
tracer.Tag(ext.SpanKind, ext.SpanKindServer),
)
span, ctx := tracer.StartSpanFromContext(c.Context(), cfg.spanName, opts...)

defer span.Finish()
Expand All @@ -74,6 +76,7 @@ func Middleware(opts ...Option) func(c *fiber.Ctx) error {
err := c.Next()

span.SetTag(ext.ResourceName, cfg.resourceNamer(c))
span.SetTag(ext.HTTPRoute, c.Route().Path)

status := c.Response().StatusCode()
// on the off chance we don't yet have a status after the rest of the things have run
Expand Down
3 changes: 3 additions & 0 deletions contrib/gofiber/fiber.v2/fiber_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ func TestTrace200(t *testing.T) {
assert.Equal("/user/123", span.Tag(ext.HTTPURL))
assert.Equal(ext.SpanKindServer, span.Tag(ext.SpanKind))
assert.Equal("gofiber/fiber.v2", span.Tag(ext.Component))
assert.Equal("/user/:id", span.Tag(ext.HTTPRoute))
}

t.Run("response", func(t *testing.T) {
Expand Down Expand Up @@ -132,6 +133,7 @@ func TestStatusError(t *testing.T) {
assert.Equal("http.request", span.OperationName())
assert.Equal("foobar", span.Tag(ext.ServiceName))
assert.Equal("500", span.Tag(ext.HTTPCode))
assert.Equal("/err", span.Tag(ext.HTTPRoute))
assert.Equal(wantErr, span.Tag(ext.Error).(error).Error())
}

Expand Down Expand Up @@ -166,6 +168,7 @@ func TestCustomError(t *testing.T) {
assert.Equal(fiber.ErrBadRequest, span.Tag(ext.Error).(*fiber.Error))
assert.Equal(ext.SpanKindServer, span.Tag(ext.SpanKind))
assert.Equal("gofiber/fiber.v2", span.Tag(ext.Component))
assert.Equal("/err", span.Tag(ext.HTTPRoute))
}

func TestUserContext(t *testing.T) {
Expand Down
46 changes: 35 additions & 11 deletions contrib/gorilla/mux/mux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,39 +29,57 @@ import (

func TestHttpTracer(t *testing.T) {
for _, ht := range []struct {
name string
code int
method string
url string
resourceName string
errorStr string
wantResource string
wantErr string
wantRoute string
}{
{
name: "200",
code: http.StatusOK,
method: "GET",
url: "/200",
resourceName: "GET /200",
wantResource: "GET /200",
wantRoute: "/200",
},
{
name: "users/{id}",
code: http.StatusOK,
method: "GET",
url: "/users/123",
wantResource: "GET /users/{id}",
wantRoute: "/users/{id}",
},
{
name: "404",
code: http.StatusNotFound,
method: "GET",
url: "/not_a_real_route",
resourceName: "GET unknown",
wantResource: "GET unknown",
wantRoute: "",
},
{
name: "405",
code: http.StatusMethodNotAllowed,
method: "POST",
url: "/405",
resourceName: "POST unknown",
wantResource: "POST unknown",
wantRoute: "",
},
{
name: "500",
code: http.StatusInternalServerError,
method: "GET",
url: "/500",
resourceName: "GET /500",
errorStr: "500: Internal Server Error",
wantResource: "GET /500",
wantErr: "500: Internal Server Error",
wantRoute: "/500",
},
} {
t.Run(http.StatusText(ht.code), func(t *testing.T) {
t.Run(ht.name, func(t *testing.T) {
assert := assert.New(t)
mt := mocktracer.Start()
defer mt.Stop()
Expand All @@ -83,12 +101,17 @@ func TestHttpTracer(t *testing.T) {
assert.Equal(codeStr, s.Tag(ext.HTTPCode))
assert.Equal(ht.method, s.Tag(ext.HTTPMethod))
assert.Equal("http://example.com"+ht.url, s.Tag(ext.HTTPURL))
assert.Equal(ht.resourceName, s.Tag(ext.ResourceName))
assert.Equal(ht.wantResource, s.Tag(ext.ResourceName))
assert.Equal(ext.SpanKindServer, s.Tag(ext.SpanKind))
assert.Equal("gorilla/mux", s.Tag(ext.Component))
if ht.wantRoute != "" {
assert.Equal(ht.wantRoute, s.Tag(ext.HTTPRoute))
} else {
assert.NotContains(s.Tags(), ext.HTTPRoute)
}

if ht.errorStr != "" {
assert.Equal(ht.errorStr, s.Tag(ext.Error).(error).Error())
if ht.wantErr != "" {
assert.Equal(ht.wantErr, s.Tag(ext.Error).(error).Error())
}
})
}
Expand Down Expand Up @@ -365,6 +388,7 @@ func router() http.Handler {
mux.Handle("/200", okHandler())
mux.Handle("/500", errorHandler(http.StatusInternalServerError))
mux.Handle("/405", okHandler()).Methods("GET")
mux.Handle("/users/{id}", okHandler())
mux.NotFoundHandler = errorHandler(http.StatusNotFound)
mux.MethodNotAllowedHandler = errorHandler(http.StatusMethodNotAllowed)
return mux
Expand Down
1 change: 1 addition & 0 deletions contrib/labstack/echo.v4/echotrace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ func TestTrace200(t *testing.T) {
assert.Equal(root.Context().SpanID(), span.ParentID())
assert.Equal("labstack/echo.v4", span.Tag(ext.Component))
assert.Equal(ext.SpanKindServer, span.Tag(ext.SpanKind))
assert.Equal("/user/:id", span.Tag(ext.HTTPRoute))

assert.Equal("http://example.com/user/123", span.Tag(ext.HTTPURL))
}
Expand Down
9 changes: 6 additions & 3 deletions contrib/urfave/negroni/negroni.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,15 @@ type DatadogMiddleware struct {
}

func (m *DatadogMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
opts := append(m.cfg.spanOpts, tracer.ServiceName(m.cfg.serviceName), tracer.ResourceName(m.cfg.resourceNamer(r)))
opts = append(opts, httptrace.HeaderTagsFromRequest(r, m.cfg.headerTags))
opts := append(
m.cfg.spanOpts,
tracer.ServiceName(m.cfg.serviceName),
tracer.ResourceName(m.cfg.resourceNamer(r)),
httptrace.HeaderTagsFromRequest(r, m.cfg.headerTags),
)
if !math.IsNaN(m.cfg.analyticsRate) {
opts = append(opts, tracer.Tag(ext.EventSampleRate, m.cfg.analyticsRate))
}

span, ctx := httptrace.StartRequestSpan(r, opts...)
defer func() {
// check if the responseWriter is of type negroni.ResponseWriter
Expand Down
5 changes: 4 additions & 1 deletion contrib/zenazn/goji.v1/web/goji.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,10 @@ func Middleware(opts ...Option) func(*web.C, http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
resource := r.Method
p := web.GetMatch(*c).RawPattern()
route := ""
if p != nil {
resource += fmt.Sprintf(" %s", p)
route = fmt.Sprintf("%s", p)
resource = resource + " " + route
} else {
warnonce.Do(func() {
log.Warn("contrib/zenazn/goji.v1/web: routes are unavailable. To enable them add the goji Router middleware before the tracer middleware.")
Expand All @@ -64,6 +66,7 @@ func Middleware(opts ...Option) func(*web.C, http.Handler) http.Handler {
Resource: resource,
FinishOpts: cfg.finishOpts,
SpanOpts: cfg.spanOpts,
Route: route,
})
})
}
Expand Down
2 changes: 2 additions & 0 deletions contrib/zenazn/goji.v1/web/goji_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ func TestNoRouter(t *testing.T) {
assert.Equal("http://example.com/user/123", span.Tag(ext.HTTPURL))
assert.Equal("zenazn/goji.v1/web", span.Tag(ext.Component))
assert.Equal(ext.SpanKindServer, span.Tag(ext.SpanKind))
assert.NotContains(span.Tags(), ext.HTTPRoute)
}

func TestTraceWithRouter(t *testing.T) {
Expand Down Expand Up @@ -91,6 +92,7 @@ func TestTraceWithRouter(t *testing.T) {
assert.Equal("http://example.com/user/123", span.Tag(ext.HTTPURL))
assert.Equal("zenazn/goji.v1/web", span.Tag(ext.Component))
assert.Equal(ext.SpanKindServer, span.Tag(ext.SpanKind))
assert.Equal("/user/:id", span.Tag(ext.HTTPRoute))
}

func TestError(t *testing.T) {
Expand Down

0 comments on commit e1a2437

Please sign in to comment.