-
Notifications
You must be signed in to change notification settings - Fork 656
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 CorrelationContext and stub Context API #379
Conversation
0a48d08
to
bd5afae
Compare
This code will rely on the Context Propagation work to be fully implemented, but breaking the work into separate PRs to make the review process a bit easier. Signed-off-by: Alex Boten <[email protected]>
bd5afae
to
69f6671
Compare
# pylint: disable=no-self-use | ||
return context.set_value(CORRELATION_CONTEXT_KEY, {}) | ||
|
||
def _copy(self) -> typing.Dict[str, typing.Any]: |
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 this will be called quite often I think we should keep performance in mind and try to use the stdlib contextvars on Python versions where this is possible (is it possible to nest contexts, i.e store a context in a context slot?). If this is not possible, we might be able to reuse ideas from https://www.python.org/dev/peps/pep-0567/#implementation (which refers to https://www.python.org/dev/peps/pep-0550/#context-variables) to achieve a constant time copy function. Alternatively, maybe this is the point where we should really use the contextvars backport (see #101). (OK, contextvars backport is only for 3.6) The cool thing about contextvars is that it has an immutable context API, just like the OTEP's design.
@@ -150,3 +152,20 @@ def __repr__(self): | |||
from .thread_local_context import ThreadLocalRuntimeContext | |||
|
|||
Context = ThreadLocalRuntimeContext() | |||
|
|||
|
|||
class ContextAPI: |
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 https://github.com/open-telemetry/opentelemetry-python/pull/379/files#r371754360. We might want to stay closer to contextvars.
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, that's right. This change only implements the stub context API as a way to break apart #325 to make it easier to review. The next change in this branch will be the Context API changes, followed by the Propagation API.
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.
One consideration that might affect the design here: do we need the context API to support arbitrary "concerns", or is it safe to assume adding a new concern will require a code change here? If the former, we probably want a single dict-valued ContextVar
with a (probably also dict-valued) key for each concern. If the latter, we could have one cv for trace context and another for correlation 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.
I think I need to understand the motivation behind multiple contexts to understand the design of the correlation context API here. I'll review again after taking another pass at the spec.
|
||
def get_correlations(self) -> typing.Dict: | ||
""" | ||
Returns the entries in this CorrelationContext. The order of entries is not significant. Based |
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 see the docs are copied from the spec, can you add a TODO to make these specific to python once the spec is finalized?
|
||
def get_correlation( | ||
self, context: ContextAPI, name: str | ||
) -> typing.Optional[typing.Any]: |
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.
Nit: this is the same type without the Optional
(unless Any
is a placeholder in this PR for some real type in the future).
@@ -150,3 +152,20 @@ def __repr__(self): | |||
from .thread_local_context import ThreadLocalRuntimeContext | |||
|
|||
Context = ThreadLocalRuntimeContext() | |||
|
|||
|
|||
class ContextAPI: |
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.
One consideration that might affect the design here: do we need the context API to support arbitrary "concerns", or is it safe to assume adding a new concern will require a code change here? If the former, we probably want a single dict-valued ContextVar
with a (probably also dict-valued) key for each concern. If the latter, we could have one cv for trace context and another for correlation context.
new_correlation_context = self._copy() | ||
new_correlation_context[name] = value | ||
return context.set_value( | ||
CORRELATION_CONTEXT_KEY, new_correlation_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.
If I understand this, a CorrelationContextManager
is a snapshot of the correlation context data of a ContextAPI
, with manager-style helper methods for setting that data.
But since this isn't associated with a context instance, this makes for a pretty weird API! It's surprising that set_correlation
and remove_correlation
don't just set/remove values from the context or this snapshot, they replace the entire context with values from the time the CorrelationContextManager
was created.
The value of the entry matching the name | ||
""" | ||
# pylint: disable=no-self-use | ||
correlation_context = context.get_value(CORRELATION_CONTEXT_KEY) |
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.
Another surprising consequence of the snapshot/context disconnect is that get_correlations
and get_correlation
do such different things, e.g. that ccm.get_correlations()[key]
and ccm.get_correlation(key, context)
only get the same value if context
's values match the ones used to create ccm
.
Closing this PR. Will be opening a PR for the Context API changes only shortly. |
* feat(plugin-https): patch https requests closes open-telemetry#375 add tests Signed-off-by: Olivier Albertini <[email protected]> * docs(plugin-https): add jaeger image Signed-off-by: Olivier Albertini <[email protected]> * fix: add mayurkale22 recommendations Signed-off-by: Olivier Albertini <[email protected]> * fix: add markwolff recommendations Signed-off-by: Olivier Albertini <[email protected]> * fix: file name utils * fix: add danielkhan and bg451 recommendations Signed-off-by: Olivier Albertini <[email protected]>
This code will rely on the Context Propagation work to be fully implemented, but breaking the work into separate PRs to make the review process a bit easier. This implements part of otep #66, this is tracked in the spec here: open-telemetry/opentelemetry-specification#420
To note in this PR:
Signed-off-by: Alex Boten [email protected]