1package opentracing 2 3import ( 4 "context" 5 "net" 6 "net/http" 7 "strconv" 8 9 opentracing "github.com/opentracing/opentracing-go" 10 "github.com/opentracing/opentracing-go/ext" 11 12 "github.com/go-kit/kit/log" 13 kithttp "github.com/go-kit/kit/transport/http" 14) 15 16// ContextToHTTP returns an http RequestFunc that injects an OpenTracing Span 17// found in `ctx` into the http headers. If no such Span can be found, the 18// RequestFunc is a noop. 19func ContextToHTTP(tracer opentracing.Tracer, logger log.Logger) kithttp.RequestFunc { 20 return func(ctx context.Context, req *http.Request) context.Context { 21 // Try to find a Span in the Context. 22 if span := opentracing.SpanFromContext(ctx); span != nil { 23 // Add standard OpenTracing tags. 24 ext.HTTPMethod.Set(span, req.Method) 25 ext.HTTPUrl.Set(span, req.URL.String()) 26 host, portString, err := net.SplitHostPort(req.URL.Host) 27 if err == nil { 28 ext.PeerHostname.Set(span, host) 29 if port, err := strconv.Atoi(portString); err == nil { 30 ext.PeerPort.Set(span, uint16(port)) 31 } 32 } else { 33 ext.PeerHostname.Set(span, req.URL.Host) 34 } 35 36 // There's nothing we can do with any errors here. 37 if err = tracer.Inject( 38 span.Context(), 39 opentracing.HTTPHeaders, 40 opentracing.HTTPHeadersCarrier(req.Header), 41 ); err != nil { 42 logger.Log("err", err) 43 } 44 } 45 return ctx 46 } 47} 48 49// HTTPToContext returns an http RequestFunc that tries to join with an 50// OpenTracing trace found in `req` and starts a new Span called 51// `operationName` accordingly. If no trace could be found in `req`, the Span 52// will be a trace root. The Span is incorporated in the returned Context and 53// can be retrieved with opentracing.SpanFromContext(ctx). 54func HTTPToContext(tracer opentracing.Tracer, operationName string, logger log.Logger) kithttp.RequestFunc { 55 return func(ctx context.Context, req *http.Request) context.Context { 56 // Try to join to a trace propagated in `req`. 57 var span opentracing.Span 58 wireContext, err := tracer.Extract( 59 opentracing.HTTPHeaders, 60 opentracing.HTTPHeadersCarrier(req.Header), 61 ) 62 if err != nil && err != opentracing.ErrSpanContextNotFound { 63 logger.Log("err", err) 64 } 65 66 span = tracer.StartSpan(operationName, ext.RPCServerOption(wireContext)) 67 ext.HTTPMethod.Set(span, req.Method) 68 ext.HTTPUrl.Set(span, req.URL.String()) 69 return opentracing.ContextWithSpan(ctx, span) 70 } 71} 72