mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2024-12-04 09:43:23 +02:00
c7ae470a16
* Refactor startSpanInternal into a tracer method The span creation and configuration process is split across the tracer Start method and the startSpanInternal function, each living in different files. This adds confusion when developing. It requires the developer to remember certain parts of the configuration happen in one place or the other. This unifies the creation and configuration of a new span. It makes this unification by creating a newSpan method on the tracer. This method will do all the configuration needed for a new span other than setting the execution task tracker. This remains a part of the Start method to preserve any existing timing and tracing the already exists. * Add a non-recording span to the SDK * Assign returned context from runtime trace task Co-authored-by: Anthony Mirabella <a9@aneurysm9.com>
154 lines
4.8 KiB
Go
154 lines
4.8 KiB
Go
// Copyright The OpenTelemetry Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package trace // import "go.opentelemetry.io/otel/sdk/trace"
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"go.opentelemetry.io/otel/trace"
|
|
|
|
"go.opentelemetry.io/otel/sdk/instrumentation"
|
|
)
|
|
|
|
type tracer struct {
|
|
provider *TracerProvider
|
|
instrumentationLibrary instrumentation.Library
|
|
}
|
|
|
|
var _ trace.Tracer = &tracer{}
|
|
|
|
// Start starts a Span and returns it along with a context containing it.
|
|
//
|
|
// The Span is created with the provided name and as a child of any existing
|
|
// span context found in the passed context. The created Span will be
|
|
// configured appropriately by any SpanOption passed.
|
|
func (tr *tracer) Start(ctx context.Context, name string, options ...trace.SpanStartOption) (context.Context, trace.Span) {
|
|
config := trace.NewSpanStartConfig(options...)
|
|
|
|
// For local spans created by this SDK, track child span count.
|
|
if p := trace.SpanFromContext(ctx); p != nil {
|
|
if sdkSpan, ok := p.(*recordingSpan); ok {
|
|
sdkSpan.addChild()
|
|
}
|
|
}
|
|
|
|
s := tr.newSpan(ctx, name, &config)
|
|
if rw, ok := s.(ReadWriteSpan); ok && s.IsRecording() {
|
|
sps, _ := tr.provider.spanProcessors.Load().(spanProcessorStates)
|
|
for _, sp := range sps {
|
|
sp.sp.OnStart(ctx, rw)
|
|
}
|
|
}
|
|
if rtt, ok := s.(runtimeTracer); ok {
|
|
ctx = rtt.runtimeTrace(ctx)
|
|
}
|
|
|
|
return trace.ContextWithSpan(ctx, s), s
|
|
}
|
|
|
|
type runtimeTracer interface {
|
|
// runtimeTrace starts a "runtime/trace".Task for the span and
|
|
// returns a context containing the task.
|
|
runtimeTrace(ctx context.Context) context.Context
|
|
}
|
|
|
|
// newSpan returns a new configured span.
|
|
func (tr *tracer) newSpan(ctx context.Context, name string, config *trace.SpanConfig) trace.Span {
|
|
// If told explicitly to make this a new root use a zero value SpanContext
|
|
// as a parent which contains an invalid trace ID and is not remote.
|
|
var psc trace.SpanContext
|
|
if config.NewRoot() {
|
|
ctx = trace.ContextWithSpanContext(ctx, psc)
|
|
} else {
|
|
psc = trace.SpanContextFromContext(ctx)
|
|
}
|
|
|
|
// If there is a valid parent trace ID, use it to ensure the continuity of
|
|
// the trace. Always generate a new span ID so other components can rely
|
|
// on a unique span ID, even if the Span is non-recording.
|
|
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(psc, sc, name, samplingResult, config)
|
|
}
|
|
|
|
// newRecordingSpan returns a new configured recordingSpan.
|
|
func (tr *tracer) newRecordingSpan(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,
|
|
attributes: newAttributesMap(tr.provider.spanLimits.AttributeCountLimit),
|
|
events: newEvictedQueue(tr.provider.spanLimits.EventCountLimit),
|
|
links: newEvictedQueue(tr.provider.spanLimits.LinkCountLimit),
|
|
tracer: tr,
|
|
spanLimits: tr.provider.spanLimits,
|
|
resource: tr.provider.resource,
|
|
instrumentationLibrary: tr.instrumentationLibrary,
|
|
}
|
|
|
|
for _, l := range config.Links() {
|
|
s.addLink(l)
|
|
}
|
|
|
|
s.SetAttributes(sr.Attributes...)
|
|
s.SetAttributes(config.Attributes()...)
|
|
|
|
return s
|
|
}
|
|
|
|
// newNonRecordingSpan returns a new configured nonRecordingSpan.
|
|
func (tr *tracer) newNonRecordingSpan(sc trace.SpanContext) nonRecordingSpan {
|
|
return nonRecordingSpan{tracer: tr, sc: sc}
|
|
}
|