Skip to content

Better scope management for async code #3751

Closed
@rhcarvalho

Description

@rhcarvalho

Currently, the @sentry/browser SDK has no mechanism to automatically clone the Hub (and, consequently, Scope), unlike @sentry/node that automatically clones a new hub per Node Domain -- and we use that to isolate state for Node server handling concurrent requests.

This means that, in particular for @sentry/browser, any kind of async code may end up accidentally mixing up state unless hubs are manually cloned and used per unit of concurrency.

This issue tracks improving automatic hub/scope management/propagation in @sentry/browser. As a possible solution we may use (an optional support for) Zone.js.

For example:

setTag('a', 'tag');
withScope((scope) => {
  setTimeout(() => {
    captureMessage('test'); // no tags
  }, 0);
});
getCurrentHub().getScope().clear();
hub.withScope(async scope => {
  console.log('scope1', scope);
  scope.setTag('me', 'you');
  hub.withScope(async scope => {
    // will have tag me: you
    console.log('scope2', scope);
    await asyncOperation();
    hub.withScope(async scope => {
      // won't have tag me: you
      console.log('scope3', scope);
      await asyncOperation();
    });
  });
});

The problem is apparent when some code needs to get something from the current scope, for example here is our fetch instrumentation:

const activeTransaction = getActiveTransaction();
if (activeTransaction) {
const span = activeTransaction.startChild({
data: {
...handlerData.fetchData,
type: 'fetch',
},
description: `${handlerData.fetchData.method} ${handlerData.fetchData.url}`,
op: 'http',
});

export function getActiveTransaction<T extends Transaction>(hub: Hub = getCurrentHub()): T | undefined {
return hub?.getScope()?.getTransaction() as T | undefined;
}

Because fetch is async, the "current scope" is not necessarily in the state that one would expect. In the example above, when we call getActiveTransaction(), the current hub/scope may have changed and lost reference to the current transaction.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    No status

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions