Browser async context gets lost after second await
What happened?
In the browser we're losing spans on the second, same level, await.
But not for nested awaits. This is with the ZoneContextManager
Steps to Reproduce
https://stackblitz.com/edit/tanstack-form-looses-otel-context-k89k2seu?file=src%2FApp.vue,src%2Fmain.ts,src%2Frepro.ts
Expected Result
Console:
repro SpanImpl {_spanContext: {…}, kind: 0, parentSpanContext: undefined, attributes: {…}, links: Array(0), …}
general SpanImpl {_spanContext: {…}, kind: 0, parentSpanContext: undefined, attributes: {…}, links: Array(0), …}
test1 SpanImpl {_spanContext: {…}, kind: 0, parentSpanContext: undefined, attributes: {…}, links: Array(0), …}
test2 SpanImpl {_spanContext: {…}, kind: 0, parentSpanContext: undefined, attributes: {…}, links: Array(0), …}
general.end SpanImpl {_spanContext: {…}, kind: 0, parentSpanContext: undefined, attributes: {…}, links: Array(0), …}
Actual Result
repro SpanImpl {_spanContext: {…}, kind: 0, parentSpanContext: undefined, attributes: {…}, links: Array(0), …}
general SpanImpl {_spanContext: {…}, kind: 0, parentSpanContext: undefined, attributes: {…}, links: Array(0), …}
test1 SpanImpl {_spanContext: {…}, kind: 0, parentSpanContext: undefined, attributes: {…}, links: Array(0), …}
test2 undefined
general.end undefined
Additional Details
It started out with trying to find out why with @tanstack/vue-form, the handleSubmit span was no longer available at the onSubmit callback. But as the repro shows, it happens just with plain javascript too.
See the repro for all the details.
Tip
React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.
Here is a related issue: #5140.
It looks like the ZoneContextManager fails to maintain context across async/await syntax.
Here is a related issue: #5140. It looks like the
ZoneContextManagerfails to maintain context acrossasync/awaitsyntax.
thanks, that's unfortunate. native browser support would be great.
We're kind of blocked on JavaScript language features to make this happen. @legendecas has been working on this for a while with the TC39 async context proposal.
@patroza i've been dying for the TC39 async context proposal myself -- in the meantime, you can wrap each async request in a new sub-span of the parent trace and that should maintain the context. not optimal from a DX perspective, but works nonetheless
@patroza i've been dying for the TC39 async context proposal myself -- in the meantime, you can wrap each async request in a new sub-span of the parent trace and that should maintain the context. not optimal from a DX perspective, but works nonetheless
Yea kmn :) we'll instead maximize Effect-ts use where it flows naturally
Assigned this to myself as I think we'd want to at least document some of the limitations that we're facing have with OTel in that regard (https://github.com/open-telemetry/opentelemetry-js/issues/5104). People are running into this frequently so it's definitely worth calling this out.
Side note: Semantic Conventions for Client instrumentation are mostly moving toward a OTel event (logs-like) based approach, where everything is tied together with a Session ID instead. This circumvents this problem by choosing a compeltely different approach that's more like existing RUM solutions. That's a more robust approach as without async context we'll likely never be able to provide proper (=no config needed ootb) for a Trace SDK in the browser.