func WithTraceContext(base http.Handler, tracer ot.Tracer) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ctx := r.Context()
		carrier := ot.HTTPHeadersCarrier(r.Header)
		ctx = context.WithValue(ctx, tracingInfoKey{}, carrier)
		r = r.WithContext(ctx)
		base.ServeHTTP(w, r)
	})
}
WithTraceContext wraps the handler and extracts the span context from request
headers to attach to the context for connecting client and server calls.
package ottwirp
import (
	"context"
	"net/http"
	"strconv"
	ot "github.com/opentracing/opentracing-go"
	"github.com/opentracing/opentracing-go/ext"
	otlog "github.com/opentracing/opentracing-go/log"
	"github.com/twitchtv/twirp"
)
const (
	RequestReceivedEvent = "request.received"
)
type tracingInfoKey struct{}
type TraceServerHooks struct {
	Tracer ot.Tracer
	opts   *TraceOptions
}
type TraceOptions struct {
	includeClientErrors bool
	tags                []TraceTag
	ctxTagFn            func(ctx context.Context) []TraceTag
}
type TraceTag struct {
	Key string
	Value interface{}
}
type TraceOption func(opts *TraceOptions)
func IncludeClientErrors(includeClientErrors bool) TraceOption {
	return func(opts *TraceOptions) {
		opts.includeClientErrors = includeClientErrors
	}
}
func WithTags(tags ...TraceTag) TraceOption {
	return func(opts *TraceOptions) {
		opts.tags = tags
	}
}
func WithContextTags(fn func(ctx context.Context) []TraceTag) TraceOption {
	return func(opts *TraceOptions) {
		opts.ctxTagFn = fn
	}
}
func NewOpenTracingHooks(tracer ot.Tracer, opts ...TraceOption) *twirp.ServerHooks {
	serverOpts := &TraceOptions{
		includeClientErrors: true,
	}
	for _, opt := range opts {
		opt(serverOpts)
	}
	traceHooks := &TraceServerHooks{
		Tracer: tracer,
		opts:   serverOpts,
	}
	return traceHooks.TwirpHooks()
}
func (t *TraceServerHooks) TwirpHooks() *twirp.ServerHooks {
	return &twirp.ServerHooks{
		RequestReceived: t.startTraceSpan,
		RequestRouted:   t.handleRequestRouted,
		ResponseSent:    t.finishTrace,
		Error:           t.handleError,
	}
}
func (t *TraceServerHooks) startTraceSpan(ctx context.Context) (context.Context, error) {
	spanContext, err := extractSpanCtx(ctx, t.Tracer)
	if err != nil && err != ot.ErrSpanContextNotFound {  
	}
	span, ctx := ot.StartSpanFromContext(ctx, RequestReceivedEvent, ext.RPCServerOption(spanContext), ext.SpanKindRPCServer)
	if span != nil {
		span.SetTag("component", "twirp")
		if packageName, ok := twirp.PackageName(ctx); ok {
			span.SetTag("package", packageName)
		}
		if serviceName, ok := twirp.ServiceName(ctx); ok {
			span.SetTag("service", serviceName)
		}
		if len(t.opts.tags) != 0 {
			for _, tag := range t.opts.tags {
				span.SetTag(tag.Key, tag.Value)
			}
		}
		if t.opts.ctxTagFn != nil {
			for _, tag := range t.opts.ctxTagFn(ctx) {
				span.SetTag(tag.Key, tag.Value)
			}
		}
	}
	return ctx, nil
}
func (t *TraceServerHooks) handleRequestRouted(ctx context.Context) (context.Context, error) {
	span := ot.SpanFromContext(ctx)
	if span != nil {
		if method, ok := twirp.MethodName(ctx); ok {
			span.SetOperationName(method)
		}
	}
	return ctx, nil
}
func (t *TraceServerHooks) finishTrace(ctx context.Context) {
	span := ot.SpanFromContext(ctx)
	if span != nil {
		status, haveStatus := twirp.StatusCode(ctx)
		code, err := strconv.ParseInt(status, 10, 64)
		if haveStatus && err == nil {
			span.SetTag("http.status_code", code)
		}
		span.Finish()
	}
}
func (t *TraceServerHooks) handleError(ctx context.Context, err twirp.Error) context.Context {
	span := ot.SpanFromContext(ctx)
	statusCode := twirp.ServerHTTPStatusFromErrorCode(err.Code())
	if span != nil {
		if t.opts.includeClientErrors || statusCode >= 500 {
			span.SetTag("error", true)
		}
		span.LogFields(otlog.String("event", "error"), otlog.String("message", err.Msg()))
	}
	return ctx
}