tracing.go
func ExtractInboundSpan(ctx context.Context, call *InboundCall, headers map[string]string, tracer opentracing.Tracer) context.Context {
	var span = call.Response().span
	if span != nil {
		if headers != nil {
			// extract SpanContext from headers, but do not start another span with it,
			// just get the baggage and copy to the already created span
			carrier := tracingHeadersCarrier(headers)
			if sc, err := tracer.Extract(opentracing.TextMap, carrier); err == nil {
				sc.ForeachBaggageItem(func(k, v string) bool {
					span.SetBaggageItem(k, v)
					return true
				})
			}
			carrier.RemoveTracingKeys()
		}
	} else {
		var parent opentracing.SpanContext
		if headers != nil {
			carrier := tracingHeadersCarrier(headers)
			if p, err := tracer.Extract(opentracing.TextMap, carrier); err == nil {
				parent = p
			}
			carrier.RemoveTracingKeys()
		}
		span = tracer.StartSpan(call.MethodString(), ext.RPCServerOption(parent))
		ext.PeerService.Set(span, call.CallerName())
		span.SetTag("as", string(call.Format()))
		call.conn.setPeerHostPort(span)
		call.Response().span = span
	}
	return opentracing.ContextWithSpan(ctx, span)
}
func ExtractInboundSpan(ctx context.Context, call *InboundCall, headers map[string]string, tracer opentracing.Tracer) context.Context {
	var span = call.Response().span
	if span != nil {
		if headers != nil {
			// extract SpanContext from headers, but do not start another span with it,
			// just get the baggage and copy to the already created span
			carrier := tracingHeadersCarrier(headers)
			if sc, err := tracer.Extract(opentracing.TextMap, carrier); err == nil {
				sc.ForeachBaggageItem(func(k, v string) bool {
					span.SetBaggageItem(k, v)
					return true
				})
			}
			carrier.RemoveTracingKeys()
		}
	} else {
		var parent opentracing.SpanContext
		if headers != nil {
			carrier := tracingHeadersCarrier(headers)
			if p, err := tracer.Extract(opentracing.TextMap, carrier); err == nil {
				parent = p
			}
			carrier.RemoveTracingKeys()
		}
		span = tracer.StartSpan(call.MethodString(), ext.RPCServerOption(parent))
		ext.PeerService.Set(span, call.CallerName())
		span.SetTag("as", string(call.Format()))
		call.conn.setPeerHostPort(span)
		call.Response().span = span
	}
	return opentracing.ContextWithSpan(ctx, span)
}
// ExtractInboundSpan is a higher level version of extractInboundSpan().
// If the lower-level attempt to create a span from incoming request was
// successful (e.g. when then Tracer supports Zipkin-style trace IDs),
// then the application headers are only used to read the Baggage and add
// it to the existing span. Otherwise, the standard OpenTracing API supported
// by all tracers is used to deserialize the tracing context from the
// application headers and start a new server-side span.
// Once the span is started, it is wrapped in a new Context, which is returned.