gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }