diff --git a/packages/core/src/hub.ts b/packages/core/src/hub.ts index 6f109dfe1ce4..1a2358b81555 100644 --- a/packages/core/src/hub.ts +++ b/packages/core/src/hub.ts @@ -50,6 +50,14 @@ export const API_VERSION = 4; */ const DEFAULT_BREADCRUMBS = 100; +/** + * Strategy used to track async context. + */ +export interface AsyncContextStrategy { + getCurrentHub: () => Hub | undefined; + runWithAsyncContext(callback: (hub: Hub, ...args: A[]) => T, ...args: A[]): T; +} + /** * A layer in the process stack. * @hidden @@ -66,6 +74,7 @@ export interface Layer { export interface Carrier { __SENTRY__?: { hub?: Hub; + acs?: AsyncContextStrategy; /** * Extra Hub properties injected by various SDKs */ @@ -519,6 +528,14 @@ export function getCurrentHub(): Hub { // Get main carrier (global for every environment) const registry = getMainCarrier(); + if (registry.__SENTRY__ && registry.__SENTRY__.acs) { + const hub = registry.__SENTRY__.acs.getCurrentHub(); + + if (hub) { + return hub; + } + } + // If there's no hub, or its an old API, assign a new one if (!hasHubOnCarrier(registry) || getHubFromCarrier(registry).isOlderThan(API_VERSION)) { setHubOnCarrier(registry, new Hub()); @@ -532,6 +549,34 @@ export function getCurrentHub(): Hub { return getHubFromCarrier(registry); } +/** + * @private Private API with no semver guarantees! + * + * Sets the global async context strategy + */ +export function setAsyncContextStrategy(strategy: AsyncContextStrategy): void { + // Get main carrier (global for every environment) + const registry = getMainCarrier(); + registry.__SENTRY__ = registry.__SENTRY__ || {}; + registry.__SENTRY__.acs = strategy; +} + +/** + * @private Private API with no semver guarantees! + * + * Runs the given callback function with the global async context strategy + */ +export function runWithAsyncContext(callback: (hub: Hub, ...args: A[]) => T, ...args: A[]): T { + const registry = getMainCarrier(); + + if (registry.__SENTRY__ && registry.__SENTRY__.acs) { + return registry.__SENTRY__.acs.runWithAsyncContext(callback, ...args); + } + + // if there was no strategy, fallback to just calling the callback + return callback(getCurrentHub(), ...args); +} + /** * Try to read the hub from an active domain, and fallback to the registry if one doesn't exist * @returns discovered hub diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index e5ee3c623d76..ee8e624709a0 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,5 +1,5 @@ export type { ClientClass } from './sdk'; -export type { Carrier, Layer } from './hub'; +export type { AsyncContextStrategy, Carrier, Layer } from './hub'; export type { OfflineStore, OfflineTransportOptions } from './transports/offline'; export * from './tracing'; @@ -18,7 +18,16 @@ export { setUser, withScope, } from './exports'; -export { getCurrentHub, getHubFromCarrier, Hub, makeMain, getMainCarrier, setHubOnCarrier } from './hub'; +export { + getCurrentHub, + getHubFromCarrier, + Hub, + makeMain, + getMainCarrier, + runWithAsyncContext, + setHubOnCarrier, + setAsyncContextStrategy, +} from './hub'; export { makeSession, closeSession, updateSession } from './session'; export { SessionFlusher } from './sessionflusher'; export { addGlobalEventProcessor, Scope } from './scope';