opentracing / specification

A place to document (and discuss) the OpenTracing specification. 🛑 This project is DEPRECATED! https://github.com/opentracing/specification/issues/163
http://opentracing.io/spec
Apache License 2.0
1.17k stars 182 forks source link

Question Regarding FollowFromRef #112

Closed shreyas-srinivas closed 6 years ago

shreyas-srinivas commented 6 years ago

I've a kafka consumer and I use a FollowsFrom ref to start the span. I was expecting the spans to siblings and share the same parent spanID. But the implementations I see are setting the spanID passed as the parentSpan id which makes it a child of that.

Is this the expected behavior? If so, is there a way to achieve what I'm expecting?

Thanks

yurishkuro commented 6 years ago

can you provide code example and sample IDs? I am not following what you're describing.

shreyas-srinivas commented 6 years ago

I have the following code

log.Debugf("ParentSpanid: %v, SpanID: %v, TraceID: %v", *sctx.(zipkin.SpanContext).ParentSpanID, sctx.(zipkin.SpanContext).SpanID, sctx.(zipkin.SpanContext).TraceID)
span = GetTracer().StartSpan("index", opentracing.FollowsFrom(sctx))
log.Debugf("ParentSpanid: %v, SpanID: %v, TraceID: %v", *sctx.(zipkin.SpanContext).ParentSpanID, sctx.(zipkin.SpanContext).SpanID, sctx.(zipkin.SpanContext).TraceID)

which gives me the following output

ParentSpanid: 0, SpanID: 6022890710582762606, TraceID: {0 5839924638333383621}
ParentSpanid: 6022890710582762606, SpanID: 4036444509682506768, TraceID: {0 5839924638333383621}    

Since it was a Follows From reference I was expecting them to share the same parent id and be displayed as siblings in the UI. But it puts it as child of the span which its following from. Is that the expected behaviour? If so what exactly is the difference between child of and follows from?

And is there anyway to achieve what I'm trying ?

yurishkuro commented 6 years ago

Both B followsFrom A and B childOf A merely imply causality A ==> B. The difference is explained in the References between Spans section of the OpenTracing spec. The notion of a "parent id" is not a part of the spec, it's an artifact of the implementation. E.g. Jaeger also uses parentId field, but only as a shortcut / compression technique, logically the span just records the full reference to the ancestor span.

Also worth noting that Zipkin internal model does not support span references, so it simply cannot represent the difference between child-of and follows-from without recording additional data somewhere (which afaik none of the zipkin OT implementations do).

shreyas-srinivas commented 6 years ago

So if I understand correctly, what you are saying is zipkin does not understand the difference between childof reference and follows from reference and my expectations are not wrong, correct?

yurishkuro commented 6 years ago

I don't want to speak for Zipkin, you can dive into the specific client's code to see if it takes the reference type into account.

But also your expectation may be incorrect, because B followsFrom A and C followsFrom B does not mean both B and C will have parentID == A.spanID, since all you're telling the tracer is that B caused C, so B is "the parent" of C (whatever parent means).

shreyas-srinivas commented 6 years ago

my expection would be that A, B and C are all at the same level and there is some way of representing that B caused A. Zipkin has code which handles them differently but the only difference between them is that the child span ref supports the clientServerSameSpan option. https://github.com/openzipkin/zipkin-go-opentracing/blob/master/tracer.go#L306

is there any implementation that you know of that handles them differently? I think that would help me understand the difference better.

yurishkuro commented 6 years ago

What do you mean by "all at the same level"? You're still constructing a tree, so every new "follows-from" span will be added deeper in the tree.

is there any implementation that you know of that handles them differently?

Jaeger will properly record & preserve the reference type, but beyond that it wouldn't handle it differently, e.g. we don't have any special rendering in the UI for follows-from spans (nobody came up with any requirements yet for how they'd want to see those spans differently).

shreyas-srinivas commented 6 years ago

Jaegar tracing also the same implementation as Zipkin. Thinking about it now I feel the only difference between childOf and FollowsFrom would be that in case of ChildOf reference we would expect the child span to finish before the parent span finishes, and in case of FollowsFrom we don't have such an expectancy.

yurishkuro commented 6 years ago

It's not the same as zipkin. Jaeger natively supports span references and will fully capture then without losing the type. It even supports multi-parent spans.

Expecting childof span to finish before the parent is not a requirement. The spec only days parent depends on the outcome of the child. In most cases it means the child will finish, but in case of an RPC call the caller/parent might time out earlier. "depends on the outcome" is the key difference with follows-from relationship.

shreyas-srinivas commented 6 years ago

But looking at https://github.com/jaegertracing/jaeger-client-go/blob/d7f08d5091e1f6a16d4467c2b7c4c3080e874195/tracer.go#L198 both zipkin and jaegars logic seems to be the same.

yurishkuro commented 6 years ago

the difference is Jaeger captures the reference (here), while Zipkin tries to translate it to parentId and then discard the actual reference (lossy conversion).

shreyas-srinivas commented 6 years ago

Got it. Thanks