69 lines
1.7 KiB
Go
69 lines
1.7 KiB
Go
package http
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"strconv"
|
|
|
|
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext"
|
|
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
|
|
)
|
|
|
|
const defaultResourceName = "http.request"
|
|
|
|
type roundTripper struct {
|
|
base http.RoundTripper
|
|
cfg *roundTripperConfig
|
|
}
|
|
|
|
func (rt *roundTripper) RoundTrip(req *http.Request) (res *http.Response, err error) {
|
|
span, _ := tracer.StartSpanFromContext(req.Context(), "http.request",
|
|
tracer.SpanType(ext.SpanTypeHTTP),
|
|
tracer.ResourceName(defaultResourceName),
|
|
tracer.Tag(ext.HTTPMethod, req.Method),
|
|
tracer.Tag(ext.HTTPURL, req.URL.Path),
|
|
)
|
|
defer func() {
|
|
if rt.cfg.after != nil {
|
|
rt.cfg.after(res, span)
|
|
}
|
|
span.Finish(tracer.WithError(err))
|
|
}()
|
|
if rt.cfg.before != nil {
|
|
rt.cfg.before(req, span)
|
|
}
|
|
// inject the span context into the http request
|
|
err = tracer.Inject(span.Context(), tracer.HTTPHeadersCarrier(req.Header))
|
|
if err != nil {
|
|
// this should never happen
|
|
fmt.Fprintf(os.Stderr, "failed to inject http headers for round tripper: %v\n", err)
|
|
}
|
|
res, err = rt.base.RoundTrip(req)
|
|
if err != nil {
|
|
span.SetTag("http.errors", err.Error())
|
|
} else {
|
|
span.SetTag(ext.HTTPCode, strconv.Itoa(res.StatusCode))
|
|
// treat 5XX as errors
|
|
if res.StatusCode/100 == 5 {
|
|
span.SetTag("http.errors", res.Status)
|
|
err = errors.New(res.Status)
|
|
}
|
|
}
|
|
return res, err
|
|
}
|
|
|
|
// WrapRoundTripper returns a new RoundTripper which traces all requests sent
|
|
// over the transport.
|
|
func WrapRoundTripper(rt http.RoundTripper, opts ...RoundTripperOption) http.RoundTripper {
|
|
cfg := new(roundTripperConfig)
|
|
for _, opt := range opts {
|
|
opt(cfg)
|
|
}
|
|
return &roundTripper{
|
|
base: rt,
|
|
cfg: cfg,
|
|
}
|
|
}
|