-
Notifications
You must be signed in to change notification settings - Fork 652
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
Propagator Class [POC for review] #121
Propagator Class [POC for review] #121
Conversation
Adding a UnifiedContext, composing DistributedContext and SpanContext. This will enable propagators to extract and inject values from either system, enabling more sophisticated schemes and standards to propagate data. This also removes the need for generics and propagators that only consume one or the other, requiring integrators to do extra work to wire propagators appropriately. Modifying the API of the propagators to consume the context as a mutable argument. By passing in the context rather than returning, this enables the chained use of propagators, allowing for situations such as supporting multiple trace propagation standards simulatenously.
Migrating formatters outside of context. The design goal is to allow context to be it's own object agnostic of the requirements of specific telemetry. Instead, moving it under a broader propagators module. Removing UnifiedContext in lieu of directly using Context. UnifiedContext adds an unneeded layer of abstraction that would then require more operations to migrate into context. Removing binaryformat and httptextformat modules specific to SpanContext and DistributedContext. These are now handled by a single formatter.
Removing the last few mentions of UnifiedContext Fixing rst syntax of the context module.
# the SpanContext or DistributedContext from a | ||
# context object declared in opentelemetry-api. | ||
# this should be more standard. | ||
context[Tracer.CONTEXT_SLOT_NAME] = trace.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.
I gave this PR a glance and I love where this is heading! Rather than passing the entire context to the propagator have we considered passing the slot to the constructor instead?
If the slot was passed, the slot get
/set
interface can be used to set the context, making the API more standard.
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 hope here was to give the the ability to the formatter to modify any context. I feel like if we pass explicit slots, then this would remove the flexibility.
But I think this discussion should probably continue in #89
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.
What are the use cases for a formatter modifying multiple context slots? And could those use cases be covered by creating multiple instances of the formatter with different slots in the constructor?
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.
Actually I think I understand the use-case, correct me if I'm wrong. Is this trying to cover the case where formats (to be defined) may transport span context and distributed context simultaneously?
While this doesn't cover named tracers, I can see handling those cases as a separate PR. 👍
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! Exactly. OTEP here: open-telemetry/oteps#37
Yes, I'll pull up an issue on named tracers. I have a couple thoughts.
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.
here's my thoughts on the named tracer scenario: just creating multiple context objects instead. issue for discussion here: #126
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.
Named are AFAIK meant to solve a different set of use cases, e.g. disabling a troublesome part of instrumentation.
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 feel like if we pass explicit slots, then this would remove the flexibility.
True, then we might as well go back to returning things (it feels like sin(a: float, result_storage: SinusResultSlot) -> None
: just awkward).
Python3.4 and 3.5 do not support types on class attributes.
A Propagator class can help streamline integrations that require extracting and injecting context.
Making the requests test pass again. Fixing propagator impl in the SDK. The correct fields were not being used.
6e8d433
to
b755b0c
Compare
In version of python before 3.7, a full import path involving a submodule was failing tests.
@@ -77,6 +79,10 @@ def instrumented_request(self, method, url, *args, **kwargs): | |||
span.set_attribute("http.status_code", result.status_code) | |||
span.set_attribute("http.status_text", result.reason) | |||
|
|||
propagator.global_propagator().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.
Probably off-topic, but: You are injecting the headers after the request was sent here, and into the response headers instead of the request headers.
I also wonder if we should automatically fall back to setter.__setitem__
if not callable(setter)
. Requiring users to pass dunder methods is a bit arcane.
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 yes, good point. Will fix that.
defaulting to setitem is a good idea. Just requires someone to write a wrapper object if that doesn't already exist. A bound callable isn't a bad idea either.
I'll file an issue and pick that up in another PR.
formatters. | ||
""" | ||
|
||
def __init__( |
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.
Either remove the __init__
or implement the whole class in the API. Right now, the cut between API and SDK seems a bit misplaced. Also, currently the user needs to set both the global propagator and both formatters. If the propagator is only a dumb bundle of formatters (which now do not only format but also inject & extract data), there is no reason for it to be overridable in API-implementations.
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.
In fact, the sketch document https://docs.google.com/document/d/1fxnfChmZauNlUJ7zqGs31x7gH70s9s_q1BWpvYVHNqA/edit which seems to be the latest version of the currently drafted context API changes (linked from https://docs.google.com/document/d/1rgXZik2_-2fU1KpVi7nze5ygWA8NhaLE8VmD20H4P8M/edit) has
func do(ctx context.Context, req *http.Request) {
headers := req.Headers()
propagator := dctx.Global().PropagatorForHTTP(headers)
propagator.Inject(ctx, propagator)
return http.Do(ctx, req)
}
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 agree, just maybe still not clear on how much has to be an API or not.
One thing to note here is that the formatters themselves now depend on the SDK, because there's no convention / specification around how the SpanContext / DistributedContext should be loaded into or retrieved from the Context object. My thought there was to just define what slots the context should fill.
With regards to the sketch: that's a possible option too. Then we would need globals for the formatters. Also I was hoping we could also bring in the logic to use multiple formatters, since that's often brought up (e.g. supporting both B3 and TraceContext).
For now I'll move propagators out of the SDK and into the API.
@@ -15,7 +15,8 @@ | |||
import typing | |||
|
|||
import opentelemetry.trace as trace | |||
from opentelemetry.context.propagation.httptextformat import HTTPTextFormat | |||
from opentelemetry.propagator.httptextformat import HTTPTextFormat | |||
from opentelemetry.sdk.trace import Tracer | |||
|
|||
|
|||
class B3Format(HTTPTextFormat): |
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 understand that we want to make propagation simpler to use. But at the lowest, building-block level, I think there should still be something that does not depend on the context, if only a free function extract_b3_spancontext(get_from_carrier, carrier) -> 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.
Could you elaborate with the specific reason why that has value?
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 have only the abstract reason that you should always strive to keep dependencies to as few as possible.
I imagine it could make combining multiple extractors simpler too.
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.
As discussed in the last Python SIG meeting, we need something for propagation and merging this PR as-is (or after fixing easily fixable issues) is OK for the Alpha.
This is not needed for alpha, as #137 is merged. |
closing in favor of #278, please continue any discussion there. |
This propagator class helps streamline integrations with formatters.
Starting this of as a PR for review. This is built on top of #89