-
Notifications
You must be signed in to change notification settings - Fork 650
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
Add support for B3 parentspanid #286
Conversation
Hello I think the CI failure is related to lint, specifically E1137. It kinda looks like a false positive, it has been reported before for circumstances similar to this one:
Here is the offending line. Does this looks like a false positive to you too? |
I signed it |
This is arguably a true positive, since the trace state is supposed to be immutable. Of course it is implemented with a EDIT2: Probably pylint-dev/pylint#2420 We might be able to workaround this by adding |
Ok! I'll try that, @Oberon00 👍 |
When I introduced this change:
So, I updated this commit to simply ignore |
Codecov Report
@@ Coverage Diff @@
## master #286 +/- ##
==========================================
+ Coverage 84.82% 84.92% +0.09%
==========================================
Files 38 38
Lines 1839 1844 +5
Branches 217 218 +1
==========================================
+ Hits 1560 1566 +6
+ Misses 214 213 -1
Partials 65 65
Continue to review full report at Codecov.
|
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.
Sorry for the wild goosechase here. From the discussion in #236, the only new behavior we should handle is extracting the parent span id as ParentSpanId. To do so, this would require passing in spans vs span context to the injector interface, which should be fine.
2bfe070
to
09f6c35
Compare
Ok, implemented the fix, please let me know if this is the right approach. It fails How should this be handled? That interface should also receive a |
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 start! I think the API interface change not being propagated through is the major blocker here. Otherwise there's a stylistic choice to spawn a child span to exercise propagation. I generally prefer simple so just use the existing Span, but creating a new one is ok.
set_in_carrier( | ||
carrier, | ||
cls.PARENT_SPAN_ID_KEY, | ||
format_span_id(span.parent.context.span_id), |
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 parent can be empty, so there should be a conditional here to check that first.
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.
Ok, added the check 👍
@@ -35,22 +35,35 @@ def setUpClass(cls): | |||
cls.serialized_span_id = b3_format.format_span_id( | |||
trace.generate_span_id() | |||
) | |||
cls.serialized_parent_span_id = b3_format.format_span_id( | |||
trace.generate_span_id() | |||
) | |||
|
|||
def test_extract_multi_header(self): |
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.
it feels to me that this test was sufficient by itself (since it exercises the base case of serialization / de-serialization), and have a separate test that verifies the parent_id propagation.
This test as is would also have been a good test for an empty 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.
Sorry, I don't understand this comment, can you explain further, please?
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.
Yep definitely. What I was trying to say was: this test already should just work, and actually exercises a valuable case where the span has no parent.
So I was arguing to not modify this test case at all, and instead add another one that verifies that a parent_id field is set if a span has a 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.
Sure, since you already approved these changes, @toumorokoshi, do you prefer if I open separate issues for your pending requests like this one or is if ok for you if I commit them directly in this PR again?
@@ -100,13 +101,22 @@ def extract(cls, get_from_carrier, carrier): | |||
) | |||
|
|||
@classmethod | |||
def inject(cls, context, set_in_carrier, carrier): | |||
sampled = (trace.TraceOptions.SAMPLED & context.trace_options) != 0 | |||
def inject( |
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 interface change will also need to be propagated up to the API layer as well. There are multiple propagators (tracecontext) that implement the previous API, and those will need to be changed as part of this.
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.
fixed too 👍
parent_span = trace.Span( | ||
"parent", FORMAT.extract(get_as_list, carrier) | ||
) | ||
child_span = trace.Tracer().start_span("child", parent=parent_span) |
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 believe you could just instantiate a raw Span object yourself from the SDK, rather than use a whole trace to do so.
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.
Yes, fixed!
parent_span = trace.Span( | ||
"parent", FORMAT.extract(get_as_list, carrier) | ||
) | ||
child_span = trace.Tracer().start_span("child", parent=parent_span) |
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.
there's a lot of boilerplate in these tests now. Could they be refactored into a few test helper methods?
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.
Yes, refactored 👍
b5e405b
to
db91e97
Compare
7f54d56
to
352de67
Compare
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 really good!
I think before merging we should be adding a test case for b3 propagator if a parent does not exist. But everything else looks great. Thanks!
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 looks like a sensible change, but it might be in violation of the spec depending on how you interpret "the value to be injected can be SpanContext
or DistributedContext
". It might be worth it to check that we're only violating the letter of the law here, and not the spirit.
The discussion in open-telemetry/opentelemetry-specification#359 didn't cover the details of the implementation, I'm interested to see how other languages decide to handle this.
My only blocking comment is that we shouldn't require the SDK in the opentracing shim.
sampled = (trace.TraceOptions.SAMPLED & context.trace_options) != 0 | ||
def inject( | ||
cls, span, set_in_carrier, carrier | ||
): # pylint: disable=arguments-differ |
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 think you can lose this.
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.
Fixed!
opentelemetry-api/src/opentelemetry/context/propagation/httptextformat.py
Outdated
Show resolved
Hide resolved
propagator.inject( | ||
span_context.unwrap(), type(carrier).__setitem__, carrier | ||
Span("", span_context.unwrap()), type(carrier).__setitem__, carrier |
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.
It seems like a problem to require the opentelemetry SDK in code that only previously required the opentracing API. You could use DefaultSpan
here, but it's not a beautiful solution.
It's also pretty surprising to see bare span creation here when we usually create them via the tracer, but I guess that's an unavoidable consequence of the API change.
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 changed Span
for DefaultSpan
. I'm just curious, why is that you don't find this to be beautiful?
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.
Reviewing again, the reason I think this is a kludge is that we're only using the DefaultSpan
to smuggle the span context to the propagator. We're taking advantage of the fact that DefaultSpan
s aren't exported here, but everywhere else they're used interchangeably with regular Span
s, with the expectation that the export behavior is left up to the user.
If the signature hadn't changed to require this to be a span, we wouldn't normally create a span here. That looks to me like evidence that we shouldn't change the API in this way.
…xtformat.py Co-Authored-By: Chris Kleinknecht <libc@google.com>
This is done in order to avoid using the SDK in opentracing_shim
@c24t yes, I think this is a violation of the spec since inject will receive now a |
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.
No more complaints from me, but note that we'll have to change the inject
signature again for #325.
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.
re-approving
Supporting B3's technical definition of a parentspanid, by sourcing the span id of the parent span during injection from the propagator.
* chore: remove all references to SpanData * yarn fix
Fixes #236