Skip to content

[v8] Browser & active spans #10944

Closed
@mydea

Description

@mydea

In Node & edge environments, we use async local storage to ensure we have actual isolation for active spans. So the following code:

startSpan({ name: 'outer 1' }, async () => {
  await waitForSeconds(2);
  console.log(getActiveSpan());
});

startSpan({ name: 'outer 2' }, async () => {
  await waitForSeconds(3);
  console.log(getActiveSpan());
});

Will actually work and log outer 1 and outer 2 correctly.
However, in browser (and theoretically any other environment where we don't have a custom Async Context Strategy (ACS)), this will not necessarily work as expected, because we cannot isolate the execution contexts, thus they may leak out into other parts of the code - so the above code may print out different spans, depending on what is globally active at the time.

This was always the case - also with the old performance APIs - but with the new APIs it is much easier to accidentally do this.

Previously, if you just did getActiveTransaction().startChild() or similar, stuff would work just fine - you had to actually go and do getCurrentScope().setSpan(span) to get potentially inconsistent behavior.

Since now startSpan (and startSpanManual) are the "default" APIs proposed for these things, I feel like maybe this will become a bigger problem in v8, and we should address this somehow.

Some options I see:

  1. We do nothing - this will basically work when passing a sync callback, and it may or may not work when passing async callbacks.
  2. In browser environment, we make startSpan and startSpanManual not actually update the active span. This would mean that the only active spans would ever be ones that we create (? or we provide a separate API/option for that...?), so pageload/navigation spans... we'd need some story for manual page load etc. instrumentation though as well 🤔
  3. Or we could do 2 only if an async callback is provided, not if a sync callback is provided. But I guess this would only make things even more confusing...

Basically, I think it would be safer to say that in browser we don't have a nested span structure, but we only have a single active span (pageload, navigation, ...) and all other spans are children of that. That of course also has downsides, but to me less severe ones. But 🤷 there is no ideal solution here 😬

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions