Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Migrate from using internally built and maintained version of the OTLP to the one hosted at `go.opentelemetry.io/proto/otlp`. (#1713)
- Migrate from using `github.com/gogo/protobuf` to `google.golang.org/protobuf` to match `go.opentelemetry.io/proto/otlp`. (#1713)

### Removed

- No longer set the links for a `Span` in `go.opentelemetry.io/otel/sdk/trace` that is configured to be a new root.
This is unspecified behavior that the OpenTelemetry community plans to standardize in the future.
To prevent backwards incompatible changes when it is specified, these links are removed. (#1726)

## [0.19.0] - 2021-03-18

### Added
Expand Down
3 changes: 1 addition & 2 deletions bridge/opentracing/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -655,10 +655,9 @@ func (t *BridgeTracer) Extract(format interface{}, carrier interface{}) (ot.Span
header := http.Header(hhcarrier)
ctx := t.getPropagator().Extract(context.Background(), propagation.HeaderCarrier(header))
baggage := baggage.MapFromContext(ctx)
otelSC, _, _ := otelparent.GetSpanContextAndLinks(ctx, false)
bridgeSC := &bridgeSpanContext{
baggageItems: baggage,
otelSpanContext: otelSC,
otelSpanContext: otelparent.SpanContext(ctx),
}
if !bridgeSC.otelSpanContext.IsValid() {
return nil, ot.ErrSpanContextNotFound
Expand Down
6 changes: 4 additions & 2 deletions bridge/opentracing/internal/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,10 @@ func (t *MockTracer) getParentSpanID(ctx context.Context, config *trace.SpanConf
}

func (t *MockTracer) getParentSpanContext(ctx context.Context, config *trace.SpanConfig) trace.SpanContext {
spanCtx, _, _ := otelparent.GetSpanContextAndLinks(ctx, config.NewRoot)
return spanCtx
if !config.NewRoot {
return otelparent.SpanContext(ctx)
}
return trace.SpanContext{}
}

func (t *MockTracer) getSpanID() trace.SpanID {
Expand Down
33 changes: 4 additions & 29 deletions internal/trace/parent/parent.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,37 +17,12 @@ package parent
import (
"context"

"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
)

func GetSpanContextAndLinks(ctx context.Context, ignoreContext bool) (trace.SpanContext, bool, []trace.Link) {
lsctx := trace.SpanContextFromContext(ctx)
rsctx := trace.RemoteSpanContextFromContext(ctx)

if ignoreContext {
links := addLinkIfValid(nil, lsctx, "current")
links = addLinkIfValid(links, rsctx, "remote")

return trace.SpanContext{}, false, links
}
if lsctx.IsValid() {
return lsctx, false, nil
}
if rsctx.IsValid() {
return rsctx, true, nil
}
return trace.SpanContext{}, false, nil
}

func addLinkIfValid(links []trace.Link, sc trace.SpanContext, kind string) []trace.Link {
if !sc.IsValid() {
return links
func SpanContext(ctx context.Context) trace.SpanContext {
if p := trace.SpanContextFromContext(ctx); p.IsValid() {
return p
}
return append(links, trace.Link{
SpanContext: sc,
Attributes: []attribute.KeyValue{
attribute.String("ignored-on-demand", kind),
},
})
return trace.RemoteSpanContextFromContext(ctx)
}
14 changes: 0 additions & 14 deletions oteltest/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,6 @@ func (t *Tracer) Start(ctx context.Context, name string, opts ...trace.SpanOptio

if c.NewRoot {
span.spanContext = trace.SpanContext{}

iodKey := attribute.Key("ignored-on-demand")
if lsc := trace.SpanContextFromContext(ctx); lsc.IsValid() {
span.links = append(span.links, trace.Link{
SpanContext: lsc,
Attributes: []attribute.KeyValue{iodKey.String("current")},
})
}
if rsc := trace.RemoteSpanContextFromContext(ctx); rsc.IsValid() {
span.links = append(span.links, trace.Link{
SpanContext: rsc,
Attributes: []attribute.KeyValue{iodKey.String("remote")},
})
}
} else {
span.spanContext = t.config.SpanContextFunc(ctx)
if lsc := trace.SpanContextFromContext(ctx); lsc.IsValid() {
Expand Down
17 changes: 0 additions & 17 deletions oteltest/tracer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,23 +198,6 @@ func TestTracer(t *testing.T) {
e.Expect(childSpanContext.SpanID()).NotToEqual(parentSpanContext.SpanID())
e.Expect(childSpanContext.SpanID()).NotToEqual(remoteParentSpanContext.SpanID())
e.Expect(testSpan.ParentSpanID().IsValid()).ToBeFalse()

expectedLinks := []trace.Link{
{
SpanContext: parentSpanContext,
Attributes: []attribute.KeyValue{
attribute.String("ignored-on-demand", "current"),
},
},
{
SpanContext: remoteParentSpanContext,
Attributes: []attribute.KeyValue{
attribute.String("ignored-on-demand", "remote"),
},
},
}
gotLinks := testSpan.Links()
e.Expect(gotLinks).ToMatchInAnyOrder(expectedLinks)
})

t.Run("uses the links provided through WithLinks", func(t *testing.T) {
Expand Down
55 changes: 28 additions & 27 deletions sdk/trace/span.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/internal/trace/parent"
"go.opentelemetry.io/otel/trace"

export "go.opentelemetry.io/otel/sdk/export/trace"
Expand Down Expand Up @@ -77,8 +78,6 @@ type ReadWriteSpan interface {
ReadOnlySpan
}

var emptySpanContext = trace.SpanContext{}

// span is an implementation of the OpenTelemetry Span API representing the
// individual component of a trace.
type span struct {
Expand Down Expand Up @@ -518,51 +517,57 @@ func (s *span) addDroppedAttributeCount(delta int) {

func (*span) private() {}

func startSpanInternal(ctx context.Context, tr *tracer, name string, parent trace.SpanContext, remoteParent bool, o *trace.SpanConfig) *span {
func startSpanInternal(ctx context.Context, tr *tracer, name string, o *trace.SpanConfig) *span {
span := &span{}

provider := tr.provider

// 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 !o.NewRoot {
psc = parent.SpanContext(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 hasEmptySpanContext(parent) {
// Generate both TraceID and SpanID
if !psc.TraceID().IsValid() {
tid, sid = provider.idGenerator.NewIDs(ctx)
} else {
// TraceID already exists, just generate a SpanID
tid = parent.TraceID()
tid = psc.TraceID()
sid = provider.idGenerator.NewSpanID(ctx, tid)
}

span.spanContext = trace.NewSpanContext(trace.SpanContextConfig{
TraceID: tid,
SpanID: sid,
TraceFlags: parent.TraceFlags(),
TraceState: parent.TraceState(),
})

spanLimits := provider.spanLimits
span.attributes = newAttributesMap(spanLimits.AttributeCountLimit)
span.messageEvents = newEvictedQueue(spanLimits.EventCountLimit)
span.links = newEvictedQueue(spanLimits.LinkCountLimit)
span.spanLimits = spanLimits

samplingResult := provider.sampler.ShouldSample(SamplingParameters{
ParentContext: parent,
TraceID: span.spanContext.TraceID(),
ParentContext: psc,
TraceID: tid,
Name: name,
HasRemoteParent: remoteParent,
HasRemoteParent: psc.IsRemote(),
Kind: o.SpanKind,
Attributes: o.Attributes,
Links: o.Links,
})

scc := trace.SpanContextConfig{
TraceID: tid,
SpanID: sid,
TraceState: samplingResult.Tracestate,
}
if isSampled(samplingResult) {
span.spanContext = span.spanContext.WithTraceFlags(span.spanContext.TraceFlags() | trace.FlagsSampled)
scc.TraceFlags = psc.TraceFlags() | trace.FlagsSampled
} else {
span.spanContext = span.spanContext.WithTraceFlags(span.spanContext.TraceFlags() &^ trace.FlagsSampled)
scc.TraceFlags = psc.TraceFlags() &^ trace.FlagsSampled
}
span.spanContext = span.spanContext.WithTraceState(samplingResult.Tracestate)
span.spanContext = trace.NewSpanContext(scc)

if !isRecording(samplingResult) {
return span
Expand All @@ -576,21 +581,17 @@ func startSpanInternal(ctx context.Context, tr *tracer, name string, parent trac

span.spanKind = trace.ValidateSpanKind(o.SpanKind)
span.name = name
span.hasRemoteParent = remoteParent
span.hasRemoteParent = psc.IsRemote()
span.resource = provider.resource
span.instrumentationLibrary = tr.instrumentationLibrary

span.SetAttributes(samplingResult.Attributes...)

span.parent = parent
span.parent = psc

return span
}

func hasEmptySpanContext(parent trace.SpanContext) bool {
return parent.Equal(emptySpanContext)
}

func isRecording(s SamplingResult) bool {
return s.Decision == RecordOnly || s.Decision == RecordAndSample
}
Expand Down
9 changes: 2 additions & 7 deletions sdk/trace/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"context"
rt "runtime/trace"

"go.opentelemetry.io/otel/internal/trace/parent"
"go.opentelemetry.io/otel/trace"

"go.opentelemetry.io/otel/sdk/instrumentation"
Expand All @@ -40,18 +39,14 @@ var _ trace.Tracer = &tracer{}
func (tr *tracer) Start(ctx context.Context, name string, options ...trace.SpanOption) (context.Context, trace.Span) {
config := trace.NewSpanConfig(options...)

parentSpanContext, remoteParent, links := parent.GetSpanContextAndLinks(ctx, config.NewRoot)

// For local spans created by this SDK, track child span count.
if p := trace.SpanFromContext(ctx); p != nil {
if sdkSpan, ok := p.(*span); ok {
sdkSpan.addChild()
}
}

span := startSpanInternal(ctx, tr, name, parentSpanContext, remoteParent, config)
for _, l := range links {
span.addLink(l)
}
span := startSpanInternal(ctx, tr, name, config)
for _, l := range config.Links {
span.addLink(l)
}
Expand Down