Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose LookupResult params field #89

Closed
devilleweppenaar opened this issue Oct 17, 2022 · 0 comments · Fixed by #90
Closed

Expose LookupResult params field #89

devilleweppenaar opened this issue Oct 17, 2022 · 0 comments · Fixed by #90

Comments

@devilleweppenaar
Copy link
Contributor

devilleweppenaar commented Oct 17, 2022

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant