-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace span relationship with a potentially remote parent context #451
Replace span relationship with a potentially remote parent context #451
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good overall. Only comment is on adding a guard against a nil pointer dereference.
|
||
// RemoteContext gets the current core.SpanContext from a Context. | ||
func RemoteContext(ctx context.Context) core.SpanContext { | ||
if sc, ok := ctx.Value(remoteContextKey).(core.SpanContext); ok { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will panic if ctx.Value(remoteContextKey)
returns a nil
interface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My assertion this will cause a panic is incorrect. Forget I made this suggestion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was incorrect about needing the guard.
Everything looks good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM except for one comment regarding possible missing test-case.
api/trace/api.go
Outdated
// a. If a current span is set with the same trace_id, use the span's | ||
// SpanContext as parent. | ||
// b. If the current span belongs to a different trace_id, use the remote | ||
// context as parent. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is condition 1.b tested?
I looked at the tests but didn't find one. Maybe it is there and I just missed it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had also proposed that the current trace_id be used to decide whether to take the current span or the remote context, and in that discussion was convinced (by @mwear) that we should do the simpler thing. Always use the span as parent if there is one, then fall back to the remote. It means that, in some cases, we'll have to clear the current span in order to use the remote context, which I think is acceptable. See here: open-telemetry/opentelemetry-specification#423
The longer I look at this PR, the more convinced I become that func doStuff(ctx context.Context, …) {
someStuff := getSomeStuff()
ctx = context.WithValue(ctx, myStuffKey, someStuff)
ctx, span := getTracer().Start(ctx, WithParent(WithRemoteParent(context.Background(), conjureSomeSpanContext())))
…
// much, much later, somewhere deeper in the call stack
// panic, ctx is a background one with some span context
someStuff := ctx.Value(myStuffKey).(stuffType)
…
} So far, we avoided that pitfall in examples and tests, because we usually passed the same context as a first parameter to ctx, span := tracer.Start(ctx, WithParent(WithRemoteParent(ctx, someSC)))
ctx2, span2 := tracer.Start(context.Background(), WithParent(WithRemoteParent(ctx, someSC))) This is just lame, IMO. I'd propose the following:
I'll try to implement that and also see how opentracing bridge can cope with it. |
The clearing of remote span context can be implicit with option WithNewRoot. ctx, span := getTracer().Start(ctx, WithNewRoot()) This option would create a new span and add link to remote context and existing span context. |
Although I wrote the |
5821f91
to
2806145
Compare
Updated. No more |
return append(links, trace.Link{ | ||
SpanContext: sc, | ||
Attributes: []core.KeyValue{ | ||
key.String("ignored-on-demand", kind), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure about ignored-on-demand
. kind (key/value) should be defined in sdk-spec.
How about 'link-type'?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, wasn't sure about the name, but I clearly wanted to preserve some information that we are not making some span context a parent of a span that's about to be created because of the WithNewRoot()
option. So I wanted some information that tells that this remote/local span context could be a parent, but isn't, because the code creating the span decided so. Not sure if link-type
conveys that. possible-remote-parent
or possible-local-parent
? There are quite a mouthful already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now just open an issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, will do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #461.
This PR removes the non-compliant ChildOf and FollowsFrom interfaces and the Relation type, which were inherited from OpenTracing via the initial prototype. Instead allow adding a span context to the go context as a remote span context and use a simple algorithm for figuring out an actual parent of the new span, which was proposed for the OpenTelemetry specification. Also add a way to ignore current span and remote span context in go context, so we can force the tracer to create a new root span - a span with a new trace ID. That required some moderate changes in the opentracing bridge - first reference with ChildOfRef reference type becomes a local parent, the rest become links. This also fixes links handling in the meantime. The downside of the approach proposed here is that we can only set the remote parent when creating a span through the opentracing API.
2806145
to
24f6505
Compare
Rebased. |
This PR removes the non-compliant ChildOf and FollowsFrom interfaces
and the Relation type, which were inherited from OpenTracing via the
initial prototype. The logic I propose is here, which says to use the
remote span context if its TraceID differs from the current Span.
The opentracing bridge will likely need to see more work, but I'd like to punt it to the separate PR later.
This PR was a part of #381.