Skip to content

Commit

Permalink
Remove links on NewRoot spans (#1726)
Browse files Browse the repository at this point in the history
* Remove links on NewRoot spans

To ensure forwards compatibility, remove the unspecified links currently
set on `NewRoot` spans.

Resolves #461

* Remove links from oteltest tracer to match
  • Loading branch information
MrAlias authored Mar 25, 2021
1 parent a9b2f85 commit 6defcfd
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 98 deletions.
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

0 comments on commit 6defcfd

Please sign in to comment.