Skip to content

Commit

Permalink
Add flag to determine whether SpanContext is remote (#1701)
Browse files Browse the repository at this point in the history
* Add remote property to SpanContext

* Set SpanContext.remote when extracting context in TraceContext propagator

* Ensure remote flag is set when inserting remote SpanContext into context

* Ensure tests are expecting remote flag in SpanContext where appropriate

* Update CHANGELOG.md

* Apply PR feedback

Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>

Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>
  • Loading branch information
Aneurysm9 and MrAlias committed Mar 18, 2021
1 parent 0fe65e6 commit 860d5d8
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -14,6 +14,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- A `ForceFlush` method to the `"go.opentelemetry.io/otel/sdk/trace".TracerProvider` to flush all registered `SpanProcessor`s. (#1608)
- Added `WithDefaultSampler` and `WithSpanLimits` to tracer provider. (#1633)
- Jaeger exporter falls back to `resource.Default`'s `service.name` if the exported Span does not have one. (#1673)
- `"go.opentelemetry.io/otel/trace".SpanContext` now has a `remote` property, and `IsRemote()` predicate, that is true when the `SpanContext` has been extracted from remote context data. (#1701)
- A `Valid` method to the `"go.opentelemetry.io/otel/attribute".KeyValue` type. (#1703)

### Changed
Expand Down
2 changes: 1 addition & 1 deletion exporters/stdout/trace_test.go
Expand Up @@ -83,7 +83,7 @@ func TestExporter_ExportSpan(t *testing.T) {
`{` +
`"Key":"key",` +
`"Value":{"Type":"STRING","Value":"val"}` +
`}]},` +
`}],"Remote":false},` +
`"ParentSpanID":"0000000000000000",` +
`"SpanKind":1,` +
`"Name":"/foo",` +
Expand Down
2 changes: 2 additions & 0 deletions oteltest/tracer_test.go
Expand Up @@ -184,6 +184,8 @@ func TestTracer(t *testing.T) {
parentSpanContext := parentSpan.SpanContext()
remoteParentSpanContext := remoteParentSpan.SpanContext()
parentCtx = trace.ContextWithRemoteSpanContext(parentCtx, remoteParentSpanContext)
// remote SpanContexts will be marked as remote
remoteParentSpanContext = remoteParentSpanContext.WithRemote(true)

_, span := subject.Start(parentCtx, "child", trace.WithNewRoot())

Expand Down
1 change: 1 addition & 0 deletions propagation/trace_context.go
Expand Up @@ -133,6 +133,7 @@ func (tc TraceContext) extract(carrier TextMapCarrier) trace.SpanContext {
scc.TraceFlags = opts[0] & trace.FlagsSampled

scc.TraceState = parseTraceState(carrier.Get(tracestateHeader))
scc.Remote = true

sc := trace.NewSpanContext(scc)
if !sc.IsValid() {
Expand Down
11 changes: 11 additions & 0 deletions propagation/trace_context_test.go
Expand Up @@ -40,6 +40,7 @@ func TestExtractValidTraceContextFromHTTPReq(t *testing.T) {
wantSc: trace.NewSpanContext(trace.SpanContextConfig{
TraceID: traceID,
SpanID: spanID,
Remote: true,
}),
},
{
Expand All @@ -49,6 +50,7 @@ func TestExtractValidTraceContextFromHTTPReq(t *testing.T) {
TraceID: traceID,
SpanID: spanID,
TraceFlags: trace.FlagsSampled,
Remote: true,
}),
},
{
Expand All @@ -58,6 +60,7 @@ func TestExtractValidTraceContextFromHTTPReq(t *testing.T) {
TraceID: traceID,
SpanID: spanID,
TraceFlags: trace.FlagsSampled,
Remote: true,
}),
},
{
Expand All @@ -67,6 +70,7 @@ func TestExtractValidTraceContextFromHTTPReq(t *testing.T) {
TraceID: traceID,
SpanID: spanID,
TraceFlags: trace.FlagsSampled,
Remote: true,
}),
},
{
Expand All @@ -75,6 +79,7 @@ func TestExtractValidTraceContextFromHTTPReq(t *testing.T) {
wantSc: trace.NewSpanContext(trace.SpanContextConfig{
TraceID: traceID,
SpanID: spanID,
Remote: true,
}),
},
{
Expand All @@ -84,6 +89,7 @@ func TestExtractValidTraceContextFromHTTPReq(t *testing.T) {
TraceID: traceID,
SpanID: spanID,
TraceFlags: trace.FlagsSampled,
Remote: true,
}),
},
{
Expand All @@ -93,6 +99,7 @@ func TestExtractValidTraceContextFromHTTPReq(t *testing.T) {
TraceID: traceID,
SpanID: spanID,
TraceFlags: trace.FlagsSampled,
Remote: true,
}),
},
{
Expand All @@ -102,6 +109,7 @@ func TestExtractValidTraceContextFromHTTPReq(t *testing.T) {
TraceID: traceID,
SpanID: spanID,
TraceFlags: trace.FlagsSampled,
Remote: true,
}),
},
}
Expand Down Expand Up @@ -302,6 +310,7 @@ func TestTraceStatePropagation(t *testing.T) {
TraceID: traceID,
SpanID: spanID,
TraceState: state,
Remote: true,
}),
},
{
Expand All @@ -314,6 +323,7 @@ func TestTraceStatePropagation(t *testing.T) {
wantSc: trace.NewSpanContext(trace.SpanContextConfig{
TraceID: traceID,
SpanID: spanID,
Remote: true,
}),
},
{
Expand All @@ -326,6 +336,7 @@ func TestTraceStatePropagation(t *testing.T) {
wantSc: trace.NewSpanContext(trace.SpanContextConfig{
TraceID: traceID,
SpanID: spanID,
Remote: true,
}),
},
}
Expand Down
1 change: 1 addition & 0 deletions sdk/trace/trace_test.go
Expand Up @@ -1385,6 +1385,7 @@ func TestReadOnlySpan(t *testing.T) {
TraceID: tID,
SpanID: sID,
TraceFlags: 0x1,
Remote: true,
})
ctx := trace.ContextWithRemoteSpanContext(context.Background(), parent)

Expand Down
29 changes: 27 additions & 2 deletions trace/trace.go
Expand Up @@ -326,6 +326,7 @@ type SpanContextConfig struct {
SpanID SpanID
TraceFlags byte
TraceState TraceState
Remote bool
}

// NewSpanContext constructs a SpanContext using values from the provided
Expand All @@ -336,6 +337,7 @@ func NewSpanContext(config SpanContextConfig) SpanContext {
spanID: config.SpanID,
traceFlags: config.TraceFlags,
traceState: config.TraceState,
remote: config.Remote,
}
}

Expand All @@ -345,6 +347,7 @@ type SpanContext struct {
spanID SpanID
traceFlags byte
traceState TraceState
remote bool
}

// IsValid returns if the SpanContext is valid. A valid span context has a
Expand All @@ -353,6 +356,22 @@ func (sc SpanContext) IsValid() bool {
return sc.HasTraceID() && sc.HasSpanID()
}

// IsRemote indicates whether the SpanContext represents a remotely-created Span.
func (sc SpanContext) IsRemote() bool {
return sc.remote
}

// WithRemote returns a copy of sc with the Remote property set to remote.
func (sc SpanContext) WithRemote(remote bool) SpanContext {
return SpanContext{
traceID: sc.traceID,
spanID: sc.spanID,
traceFlags: sc.traceFlags,
traceState: sc.traceState,
remote: remote,
}
}

// TraceID returns the TraceID from the SpanContext.
func (sc SpanContext) TraceID() TraceID {
return sc.traceID
Expand All @@ -370,6 +389,7 @@ func (sc SpanContext) WithTraceID(traceID TraceID) SpanContext {
spanID: sc.spanID,
traceFlags: sc.traceFlags,
traceState: sc.traceState,
remote: sc.remote,
}
}

Expand All @@ -390,6 +410,7 @@ func (sc SpanContext) WithSpanID(spanID SpanID) SpanContext {
spanID: spanID,
traceFlags: sc.traceFlags,
traceState: sc.traceState,
remote: sc.remote,
}
}

Expand All @@ -405,6 +426,7 @@ func (sc SpanContext) WithTraceFlags(flags byte) SpanContext {
spanID: sc.spanID,
traceFlags: flags,
traceState: sc.traceState,
remote: sc.remote,
}
}

Expand Down Expand Up @@ -435,6 +457,7 @@ func (sc SpanContext) WithTraceState(state TraceState) SpanContext {
spanID: sc.spanID,
traceFlags: sc.traceFlags,
traceState: state,
remote: sc.remote,
}
}

Expand All @@ -443,7 +466,8 @@ func (sc SpanContext) Equal(other SpanContext) bool {
return sc.traceID == other.traceID &&
sc.spanID == other.spanID &&
sc.traceFlags == other.traceFlags &&
sc.traceState.String() == other.traceState.String()
sc.traceState.String() == other.traceState.String() &&
sc.remote == other.remote
}

// MarshalJSON implements a custom marshal function to encode a SpanContext.
Expand All @@ -453,6 +477,7 @@ func (sc SpanContext) MarshalJSON() ([]byte, error) {
SpanID: sc.spanID,
TraceFlags: sc.traceFlags,
TraceState: sc.traceState,
Remote: sc.remote,
})
}

Expand Down Expand Up @@ -487,7 +512,7 @@ func SpanContextFromContext(ctx context.Context) SpanContext {
// ContextWithRemoteSpanContext returns a copy of parent with a remote set as
// the remote span context.
func ContextWithRemoteSpanContext(parent context.Context, remote SpanContext) context.Context {
return context.WithValue(parent, remoteContextKey, remote)
return context.WithValue(parent, remoteContextKey, remote.WithRemote(true))
}

// RemoteSpanContextFromContext returns the remote span context from ctx.
Expand Down
5 changes: 5 additions & 0 deletions trace/trace_test.go
Expand Up @@ -80,6 +80,8 @@ func TestContextRemoteSpanContext(t *testing.T) {

want := SpanContext{traceID: [16]byte{1}, spanID: [8]byte{42}}
ctx = ContextWithRemoteSpanContext(ctx, want)
want = want.WithRemote(true)

if got, ok := ctx.Value(remoteContextKey).(SpanContext); !ok {
t.Errorf("failed to set SpanContext with %#v", want)
} else if !assertSpanContextEqual(got, want) {
Expand All @@ -92,6 +94,8 @@ func TestContextRemoteSpanContext(t *testing.T) {

want = SpanContext{traceID: [16]byte{1}, spanID: [8]byte{43}}
ctx = ContextWithRemoteSpanContext(ctx, want)
want = want.WithRemote(true)

if got, ok := ctx.Value(remoteContextKey).(SpanContext); !ok {
t.Errorf("failed to set SpanContext with %#v", want)
} else if !assertSpanContextEqual(got, want) {
Expand Down Expand Up @@ -982,6 +986,7 @@ func assertSpanContextEqual(got SpanContext, want SpanContext) bool {
return got.spanID == want.spanID &&
got.traceID == want.traceID &&
got.traceFlags == want.traceFlags &&
got.remote == want.remote &&
assertTraceStateEqual(got.traceState, want.traceState)
}

Expand Down

0 comments on commit 860d5d8

Please sign in to comment.