package trace
import (
"context"
"time"
"go.opentelemetry.io/otel/sdk/instrumentation"
"go.opentelemetry.io/otel/sdk/trace/internal/observ"
"go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/otel/trace/embedded"
)
type tracer struct {
embedded .Tracer
provider *TracerProvider
instrumentationScope instrumentation .Scope
inst observ .Tracer
}
var _ trace .Tracer = &tracer {}
func (tr *tracer ) Start (
ctx context .Context ,
name string ,
options ...trace .SpanStartOption ,
) (context .Context , trace .Span ) {
config := trace .NewSpanStartConfig (options ...)
if ctx == nil {
ctx = context .Background ()
}
if p := trace .SpanFromContext (ctx ); p != nil {
if sdkSpan , ok := p .(*recordingSpan ); ok {
sdkSpan .addChild ()
}
}
s := tr .newSpan (ctx , name , &config )
newCtx := trace .ContextWithSpan (ctx , s )
if tr .inst .Enabled () {
if o , ok := s .(interface { setOrigCtx (context .Context ) }); ok {
o .setOrigCtx (newCtx )
}
psc := trace .SpanContextFromContext (ctx )
tr .inst .SpanStarted (newCtx , psc , s )
}
if rw , ok := s .(ReadWriteSpan ); ok && s .IsRecording () {
sps := tr .provider .getSpanProcessors ()
for _ , sp := range sps {
sp .sp .OnStart (ctx , rw )
}
}
if rtt , ok := s .(runtimeTracer ); ok {
newCtx = rtt .runtimeTrace (newCtx )
}
return newCtx , s
}
type runtimeTracer interface {
runtimeTrace(ctx context .Context ) context .Context
}
func (tr *tracer ) newSpan (ctx context .Context , name string , config *trace .SpanConfig ) trace .Span {
var psc trace .SpanContext
if config .NewRoot () {
ctx = trace .ContextWithSpanContext (ctx , psc )
} else {
psc = trace .SpanContextFromContext (ctx )
}
var tid trace .TraceID
var sid trace .SpanID
if !psc .TraceID ().IsValid () {
tid , sid = tr .provider .idGenerator .NewIDs (ctx )
} else {
tid = psc .TraceID ()
sid = tr .provider .idGenerator .NewSpanID (ctx , tid )
}
samplingResult := tr .provider .sampler .ShouldSample (SamplingParameters {
ParentContext : ctx ,
TraceID : tid ,
Name : name ,
Kind : config .SpanKind (),
Attributes : config .Attributes (),
Links : config .Links (),
})
scc := trace .SpanContextConfig {
TraceID : tid ,
SpanID : sid ,
TraceState : samplingResult .Tracestate ,
}
if isSampled (samplingResult ) {
scc .TraceFlags = psc .TraceFlags () | trace .FlagsSampled
} else {
scc .TraceFlags = psc .TraceFlags () &^ trace .FlagsSampled
}
sc := trace .NewSpanContext (scc )
if !isRecording (samplingResult ) {
return tr .newNonRecordingSpan (sc )
}
return tr .newRecordingSpan (ctx , psc , sc , name , samplingResult , config )
}
func (tr *tracer ) newRecordingSpan (
ctx context .Context ,
psc , sc trace .SpanContext ,
name string ,
sr SamplingResult ,
config *trace .SpanConfig ,
) *recordingSpan {
startTime := config .Timestamp ()
if startTime .IsZero () {
startTime = time .Now ()
}
s := &recordingSpan {
parent : psc ,
spanContext : sc ,
spanKind : trace .ValidateSpanKind (config .SpanKind ()),
name : name ,
startTime : startTime ,
events : newEvictedQueueEvent (tr .provider .spanLimits .EventCountLimit ),
links : newEvictedQueueLink (tr .provider .spanLimits .LinkCountLimit ),
tracer : tr ,
}
for _ , l := range config .Links () {
s .AddLink (l )
}
s .SetAttributes (sr .Attributes ...)
s .SetAttributes (config .Attributes ()...)
if tr .inst .Enabled () {
ctx = trace .ContextWithSpan (ctx , s )
tr .inst .SpanLive (ctx , s )
}
return s
}
func (tr *tracer ) newNonRecordingSpan (sc trace .SpanContext ) nonRecordingSpan {
return nonRecordingSpan {tracer : tr , sc : sc }
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .