feat: prototype context attach/detach#6387
feat: prototype context attach/detach#6387pichlermarc wants to merge 4 commits intoopen-telemetry:mainfrom
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #6387 +/- ##
==========================================
- Coverage 95.50% 95.47% -0.03%
==========================================
Files 365 365
Lines 11606 11627 +21
Branches 2676 2683 +7
==========================================
+ Hits 11084 11101 +17
- Misses 522 526 +4
🚀 New features to boost your workflow:
|
dyladan
left a comment
There was a problem hiding this comment.
this looks really good to me. I think it's well past time we implemented something like this
| * @returns A Token that can be used to restore the previous Context | ||
| * @since 1.10.0 | ||
| */ | ||
| attach?(context: Context): Token { |
There was a problem hiding this comment.
Does attach/detach need to be optional here? I think it only needs to be optional in the type the SDK implements and we can do the null check before calling the SDK impl
| * This is an optional global operation that allows context to be set | ||
| * imperatively rather than using with(). | ||
| * | ||
| * @param context The Context to attach |
| * This is an optional global operation that allows context to be set | ||
| * imperatively rather than using with(). | ||
| * | ||
| * @param context The Context to attach |
| * @returns A Token that can be used to restore the previous Context | ||
| * @since 1.10.0 | ||
| */ | ||
| attach?(context: Context): Token; |
There was a problem hiding this comment.
Maybe attach should return a disposable so that it can be used with the using directive https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/using
There was a problem hiding this comment.
Can't comment on files not in the diff so i'm leaving this here in order to make it a thread:
Did you choose not to implement in ZoneContextManager because it was impossible or just to make the PR easier and save time? I think we would do well to include a browser-compatible version of this if possible when the feature is released.
There was a problem hiding this comment.
symbol doesn't work because it can't key a WeakMap. I ended up using Context return here https://github.com/dynatrace-oss-contrib/opentelemetry-js/blob/zone-attach-detach/packages/opentelemetry-context-zone-peer-dep/src/ZoneContextManager.ts
| attach(context: Context): Token { | ||
| const previousContext = this.active(); | ||
| this._asyncLocalStorage.enterWith(context); | ||
| return previousContext as unknown as Token; | ||
| } |
There was a problem hiding this comment.
Any reason you chose to return the real context here rather than an opaque symbol as a token? It looks like you're going out of your way to make it opaque with types.
| * contextManager.detach(token); // Restore previous context | ||
| * ``` | ||
| */ | ||
| attach(context: Context): Token { |
There was a problem hiding this comment.
Another way to impl may be to return a detach function which encapsulates the token. Keeps the implementation opaque and reduces the API to a single method addition, avoiding bugs caused by potentially calling detach with invalid input.
Important
While this PR is intended to show possible use of attach/detach functionality for
tracingChannelinstrumentation, as an alternative to proposal #6088, It does not feature a production ready implementation of itIt's intended as a means to demonstrate how I expect this could be used to accomplish that use case.
Which problem is this PR solving?
Proposal #6088 is to allow accessing the internal
AsyncLocalStoragefrom the outside, for the purpose of binding it to aTracingChannel, so that context propagation works properly. While this is works in practice it has a few downsides:AsyncLocalStorageis internal to avoid tampering, misuse can lead to catastrophic effects and can be hard to debugContextManageris aAsyncLocalStorageContextManager, so many do not have anAsyncLocalStorage. As such, we also cannot add it to the@opentelemetry/apipackage. FurtherAsyncLocalStorageis a Node.js type, and the@opentelemetry/apiand its types must remain compatible with the BrowserMy counter-proposal is implementing the spec-defined
attach()anddetach()operations to achieve a similar effect. This works by manually attaching context when theTracingChannelemits its events, storing the state on the message, and detaching the context once the end message is received.This implementation:
ContextManager)The downsides:
AsyncLocalStorage, context attach/detach can have potentially catastrophic effects (however, I think it's easier to document that than with exposingAsyncLocalStorageand other language SIGs have been managing fine with this operation available)You can find an example how tracing channel instrumentation would work at
examples/tracing-channels.Previous work on context attach/detach