-
Notifications
You must be signed in to change notification settings - Fork 251
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
fix: update context to match spec #807
Conversation
3b76df2
to
154103d
Compare
154103d
to
3c440ed
Compare
api/lib/opentelemetry/context.rb
Outdated
# Returns the previous context so that it can be restored | ||
# | ||
# @param [Context] context The new context | ||
# @return [Context] prev The previous 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.
The spec refers to this as a "Token" rather than necessarily being the previous Context. Is there value in giving ourselves that flexibility or do we not need it?
# @return [Context] prev The previous context | |
# @return [Context] The previous 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'll admit I find the returning of a Token a bit unclear in the context of the detach documentation.
This operation is intended to help making sure the correct Context is associated with the caller's current execution unit. Users can rely on it to identify a wrong call order, i.e. trying to detach a Context that is not the current instance. In this case the operation can emit a signal to warn users of the wrong call order, such as logging an error or returning an error value.
The API MUST accept the following parameters:
A Token that was returned by a previous call to attach a Context.
What purpose does this token serve if we want to keep attaching and detaching balanced. Is there a situation where you want to detach and provide a token that doesn't match the current 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.
Is there a situation where you want to detach and provide a token that doesn't match the current context?
It helps double-check that attach
and detach
are balanced. These functions are meant to be low-level building blocks for higher level block-structured mechanisms. Passing an opaque Token around provides implementation flexibility while also being able to check for correct use of the functions, and report meaningful errors (oh yeah, we should do that 😄 ).
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.
So, why a Token instead of the Context? If we were to use an array as the Context stack instead of chaining contexts together internally, we'd likely use the array index as the Token instead of the Context itself.
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 so that makes it a lot clearer, I was under the impression that the token was to be used to actually retrieve a specific context instead of a means to assert that the attach/detach calls were lined up.
I think with the fact that should allow for attaching the same context multiple times it makes sense to use an array to keep track of the context stack, and to provide the array index as token to check against.
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.
Changes based on discussion here 0c57bd6
api/lib/opentelemetry/context.rb
Outdated
def detach(token = nil) | ||
OpenTelemetry.logger.warn 'Calls to detach should match corresponding calls to attach' if token && token != stack.size |
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.
def detach(token = nil) | |
OpenTelemetry.logger.warn 'Calls to detach should match corresponding calls to attach' if token && token != stack.size | |
def detach(token) | |
calls_matched = (token == stack.size) | |
OpenTelemetry.logger.warn 'Calls to detach should match corresponding calls to attach' unless calls_matched |
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.
Also, do you think there's value in logging the stack at this point, or at least the caller?
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 was actually thinking that it might be useful to define an exception for this situation and then have the error handler manage it. That way an application owner/instrumentation author can adjust the handling of the error based on their current needs.
api/lib/opentelemetry/context.rb
Outdated
def detach(token = nil) | ||
OpenTelemetry.logger.warn 'Calls to detach should match corresponding calls to attach' if token && token != stack.size | ||
|
||
previous_context = stack.pop || ROOT |
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 the || ROOT
implies the calls were mismatched - we should probably incorporate that into the calls_matched
check (if the stack is empty, the calls must not have been matched).
Co-authored-by: Francis Bogsanyi <[email protected]>
Co-authored-by: Francis Bogsanyi <[email protected]>
Co-authored-by: Francis Bogsanyi <[email protected]>
Co-authored-by: Francis Bogsanyi <[email protected]>
d36e4a2
to
94cd8a8
Compare
In particular open-telemetry/opentelemetry-ruby#807 changed some of the APIs we were using to get the current span for a thread. To test both 0.17.0 and this new version I moved opentelemetry to appraisals.
I've been working on integrating Datadog's continuous profiler with opentelemetry traces (see DataDog/dd-trace-rb#1568). The profiler runs on a background thread, and needs to be able to access the current context for a thread, to be able to get the current span's trace id and span ids (if any active). To do so, I was originally using ```ruby thread = ... ::OpenTelemetry::Trace.current_span(thread[::OpenTelemetry::Context::KEY]) ``` Unfortunately, after open-telemetry#807, this interface was changed, and more importantly, `Context::KEY` was removed and replaced with `Context::STACK_KEY`. `STACK_KEY` was marked as `private_constant`. With 1.0.0.rc2, the only way of getting this information is by relying on private implementation details, which isn't great. Thus, I would like to ask if it'd be reasonable to add an optional `thread` parameter to `Context.current`. This would make it easy to access the needed information, and it would even be more future-proof as the outside code doesn't need to care anymore where and how the context is stored.
I've been working on integrating Datadog's continuous profiler with opentelemetry traces (see DataDog/dd-trace-rb#1568). The profiler runs on a background thread, and needs to be able to access the current context for a thread, to be able to get the current span's trace id and span ids (if any active). To do so, I was originally using ```ruby thread = ... ::OpenTelemetry::Trace.current_span(thread[::OpenTelemetry::Context::KEY]) ``` Unfortunately, after open-telemetry#807, this interface was changed, and more importantly, `Context::KEY` was removed and replaced with `Context::STACK_KEY`. `STACK_KEY` was marked as `private_constant`. With 1.0.0.rc2, the only way of getting this information is by relying on private implementation details, which isn't great. Thus, I would like to ask if it'd be reasonable to add an optional `thread` parameter to `Context.current`. This would make it easy to access the needed information, and it would even be more future-proof as the outside code doesn't need to care anymore where and how the context is stored.
In particular open-telemetry/opentelemetry-ruby#807 changed some of the APIs we were using to get the current span for a thread. To test both 0.17.0 and this new version I moved opentelemetry to appraisals.
Moves the
attach
anddetach
methods from private instance methods to public global methodshttps://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/context.md
Related: https://github.com/open-telemetry/opentelemetry-ruby/pull/796/files#r647055849