-
Notifications
You must be signed in to change notification settings - Fork 316
introduce and take advantage of SpanContext #82
Conversation
@@ -7,23 +7,17 @@ type contextKey struct{} | |||
var activeSpanKey = contextKey{} | |||
|
|||
// ContextWithSpan returns a new `context.Context` that holds a reference to | |||
// the given `Span`. | |||
// the given `Span`'s `SpanContext`. | |||
func ContextWithSpan(ctx context.Context, span Span) context.Context { |
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.
Since the proposed semantics allow for Span.SpanContext()
to be called after Span.Finish()
, I think it's fine to store the Span
in the context.Context
. If others disagree, we could store the SpanContext
here instead, but that limits the users of the API in certain ways.
Overall, I like the change. However, one of the motivations for re-introducing SpanContext, among many, was that it would provide the datatype we could use to solve opentracing/opentracing.io#28. I don't think the current change does that, because there is no API to deserialize just the SpanContext, without starting a new span. |
I like everything that weakens the |
@yurishkuro re:
This change leaves the door open to some simplifications for the API. The data in a
I.e., there's no more I would like to avoid an explicit |
@bensigelman span context as a carrier format - ingenious! One problem I see with the above is that by losing a distinction between Start and Join we'd be breaking Zipkin's "one span per RPC" model. Unless we say that a combination of FWIW, adding |
Well, maybe we shouldn't use the term "Parent" here. Anyway, a slightly revised mini-proposal along these lines:
If I have time in the next 36 hours I will try to flesh out the above. |
I like this approach better. Looks like it doesn't need Minor nit: when using the functional option pattern, if we define type StartSpanOption interface {
Apply(* StartSpanOptions)
} and implement various options explicitly with structs instead of lambdas (Ex: https://play.golang.org/p/3S0tm_7qEe) , then the call to |
Well, I have jury duty next week (:us: :us: :us: :us:) ... hopefully that means I will just be sitting in a courthouse waiting to be called and hacking a little further on this. In which case I will work out the implications for I'm going to cc some people here since I realized they may not get Gitter notifications: @dkuebric @bg451 @adriancole @michaelsembwever @dawallin @bcronin @jmacd this is an important change and I'd appreciate if you took a look. If it's a problem that this RFC is in Go, I can try and translate to something analogous in Java or Python or whatever. |
I like the spanContext. For me it makes it more explicit in Inject that only the context part is passed on to the carrier. It is also good if Inject and Join/Extract could stay symmetric. I like the introduction of multiple parents, but in the solution above, it looks to me that all parents are needed at the start of the span. Is this always true? Shouldn't it be possible to add parents later or that introduces other problems ? What is the parent-after-finish problem I saw mentioned somewhere? Is it not ok to let a new span be created after the parent is finished? This would be the standard scenario in "fire and forget" eventdriven architecture. What are the SpanReferenceTypes (BlockedParentRef, RPCClientRef, StartedBeforeRef, |
I spent time thinking about this yesterday and I'm a really big fan of this change. It solves a lot of the problems around the semantics surrounding
@dawallin Since the finish semantics means a) this is the last call on the span and b) I won't be using the span anymore, a few opentracing implementations recycle the underlying span objects after |
@yurishkuro @bg451 @dawallin @lookfwd @jmacd Since you've all commented on this, I pushed another change to make symmetric Inject+Extract. I think this is a big improvement. The actual @dawallin asked:
This should be possible, yes. I think we need to decide whether those refs should happen via a new method on |
(and I updated opentracing/basictracer-go#29 to illustrate the ramifications for calling code and implementations) |
} | ||
span := tracer.StartSpan( | ||
operationName, | ||
opts...) |
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'd prefer
var span Span
if parentSpan := := SpanFromContext(ctx); parentSpan != nil {
span = tracer.StartSpan(operationName, Reference(RefBlockedParent, parentSpan.SpanContext()))
} else {
span = tracer.StartSpan(operationName)
}
avoids allocation/append of a slice
Okay, per today's weekly hangout, we are going to move forward with this. I will clean things up and ping the PR when it's ready for a detailed look. |
}) | ||
return parent.Tracer().StartSpan( | ||
operationName, | ||
Reference(RefBlockedParent, parent.SpanContext()), |
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.
The comment for RefBlockedParent implies this is a change of semantics. StartChildSpan says nothing about blocking its parent.
@bensigelman iirc you've always resisted the term "metadata" :-) |
I did some soul-searching... my options, as I perceived them:
Other suggestions?? |
Anyway, this is now cleaned up and ready for a nitpicky review... @yurishkuro @jmacd @bg451 @dawallin @lookfwd |
8ced677
to
a57601e
Compare
// value is copied into every local *and remote* child of this Span, and | ||
// that can add up to a lot of network and cpu overhead. | ||
// | ||
// IMPORTANT NOTE #3: Baggage item keys have a restricted format: |
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.
FYI, I got rid of the baggage key restrictions in this PR.
I've thought a bunch more about the semantics for the references (regardless of what we call them). A few conclusions:
All of this has me thinking we should only support three sorts of references for now... (Per the above, all of them imply
... or, if we express things from the perspective of the Span that's about to start:
I'm going to sleep on this, but those are my thoughts at the moment. |
... well, I did sleep on this and I had a few more thoughts about it.
I'll try to codify this in Go later today. |
There is no guarantee that the tags will be provided at span construction time and not in a separate statement. In the latter case it's too late to assign span ID. |
If the caller is able to provide the reference at span start time, then they could equivalently provide the tag at span start time... and it seems likely to me that there will eventually be a way to add references after span start time, too. Furthermore, we already use span tags to differentiate the RPC vs non-RPC case. I like the idea of the references being strictly about causality and not about how many process boundaries were crossed... seems like a cleaner separation of concerns. |
I like this. The RPCClient was the ref type I had most problem with. |
I pushed some "minimum viable reference types" as well as a helper for the RPC server span case (in |
|
||
func (r rpcServerOption) Apply(o *opentracing.StartSpanOptions) { | ||
opentracing.Parent(r.clientMetadata).Apply(o) | ||
(opentracing.Tags{SpanKind: SpanKindRPCServer}).Apply(o) |
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.
probably need string(SpanKind)
+1
I'm ok with the latest version, modulo minor renaming (meta->context, SpanReferenceType) and a few clarifications in the comments. |
LGTM |
I'm going to leave this unmerged until the analogous change is in for the docs site (which should be the "master copy"). |
... and handle the fallout. See opentracing/opentracing.io#100
14972a4
to
4232cc0
Compare
This has been updated per opentracing/opentracing.io#100 and #85 + #86 |
I will merge this tomorrow if there are no objections. (cc @basvanbeek since I noticed you were kind enough to fix recent breakage in openzipkin-contrib/zipkin-go-opentracing#5 ... Bas, I am happy to help with the downstream changes to support what's here if that's helpful.) |
@bensigelman... that would be great as I'm quite busy at the moment and not sure how quickly I'd be able to look at it myself |
@basvanbeek I'll take a look and try to prepare a PR for you to review before I merge this |
// Create a span referring to the RPC client. | ||
serverSpan = opentracing.StartSpan( | ||
appSpecificOperationName, | ||
opentracing.RPCServerOption(wireContext)) |
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.
s/opentracing/ext/
since RPCServerOption is in the ext package.
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 catch, fixed.
@basvanbeek see openzipkin-contrib/zipkin-go-opentracing#9 I will plan to merge this pr #82 tomorrow unless you have concerns about the zipkin change. |
No description provided.