1// Copyright 2019, OpenTelemetry Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package opentracing 16 17import ( 18 "context" 19 20 oteltrace "go.opentelemetry.io/otel/api/trace" 21 22 "go.opentelemetry.io/otel/bridge/opentracing/migration" 23) 24 25type WrapperProvider struct { 26 wTracer *WrapperTracer 27} 28 29var _ oteltrace.Provider = (*WrapperProvider)(nil) 30 31// Tracer returns the WrapperTracer associated with the WrapperProvider. 32func (p *WrapperProvider) Tracer(name string) oteltrace.Tracer { 33 return p.wTracer 34} 35 36// NewWrappedProvider creates a new trace provider that creates a single 37// instance of WrapperTracer that wraps OpenTelemetry tracer. 38func NewWrappedProvider(bridge *BridgeTracer, tracer oteltrace.Tracer) *WrapperProvider { 39 return &WrapperProvider{ 40 wTracer: NewWrapperTracer(bridge, tracer), 41 } 42} 43 44// WrapperTracer is a wrapper around an OpenTelemetry tracer. It 45// mostly forwards the calls to the wrapped tracer, but also does some 46// extra steps like setting up a context with the active OpenTracing 47// span. 48// 49// It does not need to be used when the OpenTelemetry tracer is also 50// aware how to operate in environment where OpenTracing API is also 51// used. 52type WrapperTracer struct { 53 bridge *BridgeTracer 54 tracer oteltrace.Tracer 55} 56 57var _ oteltrace.Tracer = &WrapperTracer{} 58var _ migration.DeferredContextSetupTracerExtension = &WrapperTracer{} 59 60// NewWrapperTracer wraps the passed tracer and also talks to the 61// passed bridge tracer when setting up the context with the new 62// active OpenTracing span. 63func NewWrapperTracer(bridge *BridgeTracer, tracer oteltrace.Tracer) *WrapperTracer { 64 return &WrapperTracer{ 65 bridge: bridge, 66 tracer: tracer, 67 } 68} 69 70func (t *WrapperTracer) otelTracer() oteltrace.Tracer { 71 return t.tracer 72} 73 74// WithSpan forwards the call to the wrapped tracer with a modified 75// body callback, which sets the active OpenTracing span before 76// calling the original callback. 77func (t *WrapperTracer) WithSpan(ctx context.Context, name string, body func(context.Context) error) error { 78 return t.otelTracer().WithSpan(ctx, name, func(ctx context.Context) error { 79 span := oteltrace.SpanFromContext(ctx) 80 if spanWithExtension, ok := span.(migration.OverrideTracerSpanExtension); ok { 81 spanWithExtension.OverrideTracer(t) 82 } 83 ctx = t.bridge.ContextWithBridgeSpan(ctx, span) 84 return body(ctx) 85 }) 86} 87 88// Start forwards the call to the wrapped tracer. It also tries to 89// override the tracer of the returned span if the span implements the 90// OverrideTracerSpanExtension interface. 91func (t *WrapperTracer) Start(ctx context.Context, name string, opts ...oteltrace.StartOption) (context.Context, oteltrace.Span) { 92 ctx, span := t.otelTracer().Start(ctx, name, opts...) 93 if spanWithExtension, ok := span.(migration.OverrideTracerSpanExtension); ok { 94 spanWithExtension.OverrideTracer(t) 95 } 96 if !migration.SkipContextSetup(ctx) { 97 ctx = t.bridge.ContextWithBridgeSpan(ctx, span) 98 } 99 return ctx, span 100} 101 102// DeferredContextSetupHook is a part of the implementation of the 103// DeferredContextSetupTracerExtension interface. It will try to 104// forward the call to the wrapped tracer if it implements the 105// interface. 106func (t *WrapperTracer) DeferredContextSetupHook(ctx context.Context, span oteltrace.Span) context.Context { 107 if tracerWithExtension, ok := t.otelTracer().(migration.DeferredContextSetupTracerExtension); ok { 108 ctx = tracerWithExtension.DeferredContextSetupHook(ctx, span) 109 } 110 ctx = oteltrace.ContextWithSpan(ctx, span) 111 return ctx 112} 113