trace.go (5701B)
1 // Copyright The 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 15 package global // import "go.opentelemetry.io/otel/internal/global" 16 17 /* 18 This file contains the forwarding implementation of the TracerProvider used as 19 the default global instance. Prior to initialization of an SDK, Tracers 20 returned by the global TracerProvider will provide no-op functionality. This 21 means that all Span created prior to initialization are no-op Spans. 22 23 Once an SDK has been initialized, all provided no-op Tracers are swapped for 24 Tracers provided by the SDK defined TracerProvider. However, any Span started 25 prior to this initialization does not change its behavior. Meaning, the Span 26 remains a no-op Span. 27 28 The implementation to track and swap Tracers locks all new Tracer creation 29 until the swap is complete. This assumes that this operation is not 30 performance-critical. If that assumption is incorrect, be sure to configure an 31 SDK prior to any Tracer creation. 32 */ 33 34 import ( 35 "context" 36 "sync" 37 "sync/atomic" 38 39 "go.opentelemetry.io/otel/attribute" 40 "go.opentelemetry.io/otel/codes" 41 "go.opentelemetry.io/otel/trace" 42 ) 43 44 // tracerProvider is a placeholder for a configured SDK TracerProvider. 45 // 46 // All TracerProvider functionality is forwarded to a delegate once 47 // configured. 48 type tracerProvider struct { 49 mtx sync.Mutex 50 tracers map[il]*tracer 51 delegate trace.TracerProvider 52 } 53 54 // Compile-time guarantee that tracerProvider implements the TracerProvider 55 // interface. 56 var _ trace.TracerProvider = &tracerProvider{} 57 58 // setDelegate configures p to delegate all TracerProvider functionality to 59 // provider. 60 // 61 // All Tracers provided prior to this function call are switched out to be 62 // Tracers provided by provider. 63 // 64 // It is guaranteed by the caller that this happens only once. 65 func (p *tracerProvider) setDelegate(provider trace.TracerProvider) { 66 p.mtx.Lock() 67 defer p.mtx.Unlock() 68 69 p.delegate = provider 70 71 if len(p.tracers) == 0 { 72 return 73 } 74 75 for _, t := range p.tracers { 76 t.setDelegate(provider) 77 } 78 79 p.tracers = nil 80 } 81 82 // Tracer implements TracerProvider. 83 func (p *tracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer { 84 p.mtx.Lock() 85 defer p.mtx.Unlock() 86 87 if p.delegate != nil { 88 return p.delegate.Tracer(name, opts...) 89 } 90 91 // At this moment it is guaranteed that no sdk is installed, save the tracer in the tracers map. 92 93 c := trace.NewTracerConfig(opts...) 94 key := il{ 95 name: name, 96 version: c.InstrumentationVersion(), 97 } 98 99 if p.tracers == nil { 100 p.tracers = make(map[il]*tracer) 101 } 102 103 if val, ok := p.tracers[key]; ok { 104 return val 105 } 106 107 t := &tracer{name: name, opts: opts, provider: p} 108 p.tracers[key] = t 109 return t 110 } 111 112 type il struct { 113 name string 114 version string 115 } 116 117 // tracer is a placeholder for a trace.Tracer. 118 // 119 // All Tracer functionality is forwarded to a delegate once configured. 120 // Otherwise, all functionality is forwarded to a NoopTracer. 121 type tracer struct { 122 name string 123 opts []trace.TracerOption 124 provider *tracerProvider 125 126 delegate atomic.Value 127 } 128 129 // Compile-time guarantee that tracer implements the trace.Tracer interface. 130 var _ trace.Tracer = &tracer{} 131 132 // setDelegate configures t to delegate all Tracer functionality to Tracers 133 // created by provider. 134 // 135 // All subsequent calls to the Tracer methods will be passed to the delegate. 136 // 137 // It is guaranteed by the caller that this happens only once. 138 func (t *tracer) setDelegate(provider trace.TracerProvider) { 139 t.delegate.Store(provider.Tracer(t.name, t.opts...)) 140 } 141 142 // Start implements trace.Tracer by forwarding the call to t.delegate if 143 // set, otherwise it forwards the call to a NoopTracer. 144 func (t *tracer) Start(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { 145 delegate := t.delegate.Load() 146 if delegate != nil { 147 return delegate.(trace.Tracer).Start(ctx, name, opts...) 148 } 149 150 s := nonRecordingSpan{sc: trace.SpanContextFromContext(ctx), tracer: t} 151 ctx = trace.ContextWithSpan(ctx, s) 152 return ctx, s 153 } 154 155 // nonRecordingSpan is a minimal implementation of a Span that wraps a 156 // SpanContext. It performs no operations other than to return the wrapped 157 // SpanContext. 158 type nonRecordingSpan struct { 159 sc trace.SpanContext 160 tracer *tracer 161 } 162 163 var _ trace.Span = nonRecordingSpan{} 164 165 // SpanContext returns the wrapped SpanContext. 166 func (s nonRecordingSpan) SpanContext() trace.SpanContext { return s.sc } 167 168 // IsRecording always returns false. 169 func (nonRecordingSpan) IsRecording() bool { return false } 170 171 // SetStatus does nothing. 172 func (nonRecordingSpan) SetStatus(codes.Code, string) {} 173 174 // SetError does nothing. 175 func (nonRecordingSpan) SetError(bool) {} 176 177 // SetAttributes does nothing. 178 func (nonRecordingSpan) SetAttributes(...attribute.KeyValue) {} 179 180 // End does nothing. 181 func (nonRecordingSpan) End(...trace.SpanEndOption) {} 182 183 // RecordError does nothing. 184 func (nonRecordingSpan) RecordError(error, ...trace.EventOption) {} 185 186 // AddEvent does nothing. 187 func (nonRecordingSpan) AddEvent(string, ...trace.EventOption) {} 188 189 // SetName does nothing. 190 func (nonRecordingSpan) SetName(string) {} 191 192 func (s nonRecordingSpan) TracerProvider() trace.TracerProvider { return s.tracer.provider }