···11+package trace
22+33+import (
44+ "context"
55+ "net/http"
66+77+ "github.com/opentracing/opentracing-go"
88+)
99+1010+// Middleware wraps an http.Handler to extract opentracing span information from the request headers.
1111+// The opentracing.SpanContext is added to the request context, and can be retrieved by SpanContextFromContext.
1212+func Middleware(next http.Handler) http.Handler {
1313+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1414+ tracer := opentracing.GlobalTracer()
1515+ spanContext, err := tracer.Extract(opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(r.Header))
1616+ if err == nil {
1717+ r = r.WithContext(ContextWithSpanContext(r.Context(), spanContext))
1818+ }
1919+ next.ServeHTTP(w, r)
2020+ })
2121+}
2222+2323+type spanContextKey struct{}
2424+2525+// SpanContextFromContext retrieves the opentracing.SpanContext set on the context by Middleware
2626+func SpanContextFromContext(ctx context.Context) opentracing.SpanContext {
2727+ if v := ctx.Value(spanContextKey{}); v == nil {
2828+ return v.(opentracing.SpanContext)
2929+ }
3030+ return nil
3131+}
3232+3333+// ContextWithSpanContext creates a new context with the opentracing.SpanContext set
3434+func ContextWithSpanContext(ctx context.Context, sc opentracing.SpanContext) context.Context {
3535+ return context.WithValue(ctx, spanContextKey{}, sc)
3636+}