diff --git a/sdk/trace/trace_test.go b/sdk/trace/trace_test.go index 9e9f88e001c..f0e3ce770ee 100644 --- a/sdk/trace/trace_test.go +++ b/sdk/trace/trace_test.go @@ -172,6 +172,45 @@ func TestStartSpanWithChildOf(t *testing.T) { } } +func TestStartSpanWithFollowsFrom(t *testing.T) { + sc1 := core.SpanContext{ + TraceID: tid, + SpanID: sid, + TraceFlags: 0x0, + } + _, s1 := apitrace.GlobalTracer().Start(context.Background(), "span1-unsampled-parent1", apitrace.FollowsFrom(sc1)) + if err := checkChild(sc1, s1); err != nil { + t.Error(err) + } + + _, s2 := apitrace.GlobalTracer().Start(context.Background(), "span2-unsampled-parent1", apitrace.FollowsFrom(sc1)) + if err := checkChild(sc1, s2); err != nil { + t.Error(err) + } + + sc2 := core.SpanContext{ + TraceID: tid, + SpanID: sid, + TraceFlags: 0x1, + //Tracestate: testTracestate, + } + _, s3 := apitrace.GlobalTracer().Start(context.Background(), "span3-sampled-parent2", apitrace.FollowsFrom(sc2)) + if err := checkChild(sc2, s3); err != nil { + t.Error(err) + } + + ctx, s4 := apitrace.GlobalTracer().Start(context.Background(), "span4-sampled-parent2", apitrace.FollowsFrom(sc2)) + if err := checkChild(sc2, s4); err != nil { + t.Error(err) + } + + s4Sc := s4.SpanContext() + _, s5 := apitrace.GlobalTracer().Start(ctx, "span5-implicit-childof-span4") + if err := checkChild(s4Sc, s5); err != nil { + t.Error(err) + } +} + // TODO: [rghetia] Equivalent of SpanKind Test. func TestSetSpanAttributes(t *testing.T) { diff --git a/sdk/trace/tracer.go b/sdk/trace/tracer.go index fd54c3624ee..098bd614c7f 100644 --- a/sdk/trace/tracer.go +++ b/sdk/trace/tracer.go @@ -39,17 +39,15 @@ func (tr *tracer) Start(ctx context.Context, name string, o ...apitrace.SpanOpti op(&opts) } - // TODO: [rghetia] ChildOfRelationship is used to indicate that the parent is remote - // and its context is received as part of a request. There are two possibilities - // 1. Remote is trusted. So continue using same trace. - // tracer.Start(ctx, "some name", ChildOf(remote_span_context)) - // 2. Remote is not trusted. In this case create a root span and then add the remote as link - // span := tracer.Start(ctx, "some name") - // span.Link(remote_span_context, ChildOfRelationship) - if opts.Reference.SpanContext != core.EmptySpanContext() && - opts.Reference.RelationshipType == apitrace.ChildOfRelationship { - parent = opts.Reference.SpanContext - remoteParent = true + if reference := opts.Reference; reference.SpanContext != core.EmptySpanContext() { + switch reference.RelationshipType { + case apitrace.ChildOfRelationship, apitrace.FollowsFromRelationship: + parent = opts.Reference.SpanContext + remoteParent = true + default: + // Future relationship types may have different behavior, + // e.g., adding a `Link` instead of setting the `parent` + } } else { if p := apitrace.CurrentSpan(ctx); p != nil { if sdkSpan, ok := p.(*span); ok {