gtsocial-umbx

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

tracer.go (5098B)


      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 trace // import "go.opentelemetry.io/otel/sdk/trace"
     16 
     17 import (
     18 	"context"
     19 	"time"
     20 
     21 	"go.opentelemetry.io/otel/sdk/instrumentation"
     22 	"go.opentelemetry.io/otel/trace"
     23 )
     24 
     25 type tracer struct {
     26 	provider             *TracerProvider
     27 	instrumentationScope instrumentation.Scope
     28 }
     29 
     30 var _ trace.Tracer = &tracer{}
     31 
     32 // Start starts a Span and returns it along with a context containing it.
     33 //
     34 // The Span is created with the provided name and as a child of any existing
     35 // span context found in the passed context. The created Span will be
     36 // configured appropriately by any SpanOption passed.
     37 func (tr *tracer) Start(ctx context.Context, name string, options ...trace.SpanStartOption) (context.Context, trace.Span) {
     38 	config := trace.NewSpanStartConfig(options...)
     39 
     40 	if ctx == nil {
     41 		// Prevent trace.ContextWithSpan from panicking.
     42 		ctx = context.Background()
     43 	}
     44 
     45 	// For local spans created by this SDK, track child span count.
     46 	if p := trace.SpanFromContext(ctx); p != nil {
     47 		if sdkSpan, ok := p.(*recordingSpan); ok {
     48 			sdkSpan.addChild()
     49 		}
     50 	}
     51 
     52 	s := tr.newSpan(ctx, name, &config)
     53 	if rw, ok := s.(ReadWriteSpan); ok && s.IsRecording() {
     54 		sps := tr.provider.getSpanProcessors()
     55 		for _, sp := range sps {
     56 			sp.sp.OnStart(ctx, rw)
     57 		}
     58 	}
     59 	if rtt, ok := s.(runtimeTracer); ok {
     60 		ctx = rtt.runtimeTrace(ctx)
     61 	}
     62 
     63 	return trace.ContextWithSpan(ctx, s), s
     64 }
     65 
     66 type runtimeTracer interface {
     67 	// runtimeTrace starts a "runtime/trace".Task for the span and
     68 	// returns a context containing the task.
     69 	runtimeTrace(ctx context.Context) context.Context
     70 }
     71 
     72 // newSpan returns a new configured span.
     73 func (tr *tracer) newSpan(ctx context.Context, name string, config *trace.SpanConfig) trace.Span {
     74 	// If told explicitly to make this a new root use a zero value SpanContext
     75 	// as a parent which contains an invalid trace ID and is not remote.
     76 	var psc trace.SpanContext
     77 	if config.NewRoot() {
     78 		ctx = trace.ContextWithSpanContext(ctx, psc)
     79 	} else {
     80 		psc = trace.SpanContextFromContext(ctx)
     81 	}
     82 
     83 	// If there is a valid parent trace ID, use it to ensure the continuity of
     84 	// the trace. Always generate a new span ID so other components can rely
     85 	// on a unique span ID, even if the Span is non-recording.
     86 	var tid trace.TraceID
     87 	var sid trace.SpanID
     88 	if !psc.TraceID().IsValid() {
     89 		tid, sid = tr.provider.idGenerator.NewIDs(ctx)
     90 	} else {
     91 		tid = psc.TraceID()
     92 		sid = tr.provider.idGenerator.NewSpanID(ctx, tid)
     93 	}
     94 
     95 	samplingResult := tr.provider.sampler.ShouldSample(SamplingParameters{
     96 		ParentContext: ctx,
     97 		TraceID:       tid,
     98 		Name:          name,
     99 		Kind:          config.SpanKind(),
    100 		Attributes:    config.Attributes(),
    101 		Links:         config.Links(),
    102 	})
    103 
    104 	scc := trace.SpanContextConfig{
    105 		TraceID:    tid,
    106 		SpanID:     sid,
    107 		TraceState: samplingResult.Tracestate,
    108 	}
    109 	if isSampled(samplingResult) {
    110 		scc.TraceFlags = psc.TraceFlags() | trace.FlagsSampled
    111 	} else {
    112 		scc.TraceFlags = psc.TraceFlags() &^ trace.FlagsSampled
    113 	}
    114 	sc := trace.NewSpanContext(scc)
    115 
    116 	if !isRecording(samplingResult) {
    117 		return tr.newNonRecordingSpan(sc)
    118 	}
    119 	return tr.newRecordingSpan(psc, sc, name, samplingResult, config)
    120 }
    121 
    122 // newRecordingSpan returns a new configured recordingSpan.
    123 func (tr *tracer) newRecordingSpan(psc, sc trace.SpanContext, name string, sr SamplingResult, config *trace.SpanConfig) *recordingSpan {
    124 	startTime := config.Timestamp()
    125 	if startTime.IsZero() {
    126 		startTime = time.Now()
    127 	}
    128 
    129 	s := &recordingSpan{
    130 		// Do not pre-allocate the attributes slice here! Doing so will
    131 		// allocate memory that is likely never going to be used, or if used,
    132 		// will be over-sized. The default Go compiler has been tested to
    133 		// dynamically allocate needed space very well. Benchmarking has shown
    134 		// it to be more performant than what we can predetermine here,
    135 		// especially for the common use case of few to no added
    136 		// attributes.
    137 
    138 		parent:      psc,
    139 		spanContext: sc,
    140 		spanKind:    trace.ValidateSpanKind(config.SpanKind()),
    141 		name:        name,
    142 		startTime:   startTime,
    143 		events:      newEvictedQueue(tr.provider.spanLimits.EventCountLimit),
    144 		links:       newEvictedQueue(tr.provider.spanLimits.LinkCountLimit),
    145 		tracer:      tr,
    146 	}
    147 
    148 	for _, l := range config.Links() {
    149 		s.addLink(l)
    150 	}
    151 
    152 	s.SetAttributes(sr.Attributes...)
    153 	s.SetAttributes(config.Attributes()...)
    154 
    155 	return s
    156 }
    157 
    158 // newNonRecordingSpan returns a new configured nonRecordingSpan.
    159 func (tr *tracer) newNonRecordingSpan(sc trace.SpanContext) nonRecordingSpan {
    160 	return nonRecordingSpan{tracer: tr, sc: sc}
    161 }