github.com/gorilla/mux
Package gorilla/mux implements a request router and dispatcher for matching incoming requests to their respective handler.
Add fields to Router
Definition of
mux.Router
Introduce new declarations:
// Using the following synthetic imports:
import (
ddtrace "gopkg.in/DataDog/dd-trace-go.v1/ddtrace"
http "net/http"
internal "gopkg.in/DataDog/dd-trace-go.v1/internal"
telemetry "gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry"
tracer "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)
type ddRouterConfig struct {
ignoreRequest func(*http.Request) bool
headerTags *internal.LockMap
resourceNamer func(*Router, *http.Request) string
serviceName string
spanOpts []ddtrace.StartSpanOption
}
func ddDefaultResourceNamer(router *Router, req *http.Request) string {
var (
match RouteMatch
route = "unknown"
)
if router.Match(req, &match) && match.Route != nil {
if r, err := match.Route.GetPathTemplate(); err == nil {
route = r
}
}
return fmt.Sprintf("%s %s", req.Method, route)
}
func init() {
telemetry.LoadIntegration("gorilla/mux")
tracer.MarkIntegrationImported("github.com/gorilla/mux")
}
Setup in NewRouter
All of
- Import path
github.com/
gorilla/ mux - Function body
- Function declaration
- Function name
NewRouter
Prepend statements produced by the following template:
// Using the following synthetic imports:
import (
ddtrace "gopkg.in/DataDog/dd-trace-go.v1/ddtrace"
ext "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext"
globalconfig "gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig"
http "net/http"
internal "gopkg.in/DataDog/dd-trace-go.v1/internal"
math "math"
namingschema "gopkg.in/DataDog/dd-trace-go.v1/internal/namingschema"
tracer "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)
{{- $res := .Function.Result 0 -}}
defer func() {
var analyticsRate float64
if internal.BoolEnv("DD_TRACE_MUX_ANALYTICS_ENABLED", false) {
analyticsRate = 1.0
} else {
analyticsRate = globalconfig.AnalyticsRate()
}
{{ $res }}.__dd_config.headerTags = globalconfig.HeaderTagMap()
{{ $res }}.__dd_config.ignoreRequest = func(*http.Request) bool { return false }
{{ $res }}.__dd_config.resourceNamer = ddDefaultResourceNamer
{{ $res }}.__dd_config.serviceName = namingschema.ServiceName("mux.router")
{{ $res }}.__dd_config.spanOpts = []ddtrace.StartSpanOption{
tracer.Tag(ext.Component, "gorilla/mux"),
tracer.Tag(ext.SpanKind, ext.SpanKindServer),
}
if !math.IsNaN(analyticsRate) {
{{ $res }}.__dd_config.spanOpts = append(
{{ $res }}.__dd_config.spanOpts,
tracer.Tag(ext.EventSampleRate, analyticsRate),
)
}
}()
Instrument Router.ServeHTTP
Function body
- Function declaration
- Is method of
*mux.Router
- Function name
ServeHTTP
Prepend statements produced by the following template:
// Using the following synthetic imports:
import (
http "net/http"
httptrace "gopkg.in/DataDog/dd-trace-go.v1/contrib/net/http"
httptraceinternal "gopkg.in/DataDog/dd-trace-go.v1/contrib/internal/httptrace"
options "gopkg.in/DataDog/dd-trace-go.v1/contrib/internal/options"
tracer "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)
{{- $r := .Function.Receiver -}}
{{- $w := .Function.Argument 0 -}}
{{- $req := .Function.Argument 1 -}}
if !{{ $r }}.__dd_config.ignoreRequest({{ $req }}) {
var (
match RouteMatch
route string
spanOpts = options.Copy({{ $r }}.__dd_config.spanOpts...)
)
if {{ $r }}.Match({{ $req }}, &match) && match.Route != nil {
if h, err := match.Route.GetHostTemplate(); err == nil {
spanOpts = append(spanOpts, tracer.Tag("mux.host", h))
}
route, _ = match.Route.GetPathTemplate()
}
spanOpts = append(spanOpts, httptraceinternal.HeaderTagsFromRequest({{ $req }}, {{ $r }}.__dd_config.headerTags))
resource := {{ $r }}.__dd_config.resourceNamer({{ $r }}, {{ $req }})
// This is a temporary workaround/hack to prevent endless recursion via httptrace.TraceAndServe, which
// basically implies passing a shallow copy of this router that ignores all requests down to
// httptrace.TraceAndServe.
var rCopy Router
rCopy = *{{ $r }}
rCopy.__dd_config.ignoreRequest = func(*http.Request) bool { return true }
httptrace.TraceAndServe(&rCopy, {{ $w }}, {{ $req }}, &httptrace.ServeConfig{
Service: {{ $r }}.__dd_config.serviceName,
Resource: resource,
SpanOpts: spanOpts,
RouteParams: match.Vars,
Route: route,
})
return
}