diff --git a/packages/core/src/hub.ts b/packages/core/src/hub.ts index 18527e342d12..ea4f955ec681 100644 --- a/packages/core/src/hub.ts +++ b/packages/core/src/hub.ts @@ -60,7 +60,7 @@ export interface AsyncContextStrategy { /** * Runs the supplied callback in its own async context. */ - runWithAsyncContext(callback: (hub: Hub) => T, options: RunWithAsyncContextOptions): T; + runWithAsyncContext(callback: () => T, options: RunWithAsyncContextOptions): T; } /** @@ -593,7 +593,7 @@ export function setAsyncContextStrategy(strategy: AsyncContextStrategy | undefin * @param options Options to pass to the async context strategy * @returns The result of the callback */ -export function runWithAsyncContext(callback: (hub: Hub) => T, options: RunWithAsyncContextOptions = {}): T { +export function runWithAsyncContext(callback: () => T, options: RunWithAsyncContextOptions = {}): T { const registry = getMainCarrier(); if (registry.__SENTRY__ && registry.__SENTRY__.acs) { @@ -601,7 +601,7 @@ export function runWithAsyncContext(callback: (hub: Hub) => T, options: RunWi } // if there was no strategy, fallback to just calling the callback - return callback(getCurrentHub()); + return callback(); } /** diff --git a/packages/nextjs/src/server/utils/wrapperUtils.ts b/packages/nextjs/src/server/utils/wrapperUtils.ts index 2448cfb7b8b6..44b193038011 100644 --- a/packages/nextjs/src/server/utils/wrapperUtils.ts +++ b/packages/nextjs/src/server/utils/wrapperUtils.ts @@ -1,4 +1,10 @@ -import { captureException, getActiveTransaction, runWithAsyncContext, startTransaction } from '@sentry/core'; +import { + captureException, + getActiveTransaction, + getCurrentHub, + runWithAsyncContext, + startTransaction, +} from '@sentry/core'; import type { Transaction } from '@sentry/types'; import { baggageHeaderToDynamicSamplingContext, extractTraceparentData } from '@sentry/utils'; import type { IncomingMessage, ServerResponse } from 'http'; @@ -74,7 +80,8 @@ export function withTracedServerSideDataFetcher Pr }, ): (...params: Parameters) => Promise> { return async function (this: unknown, ...args: Parameters): Promise> { - return runWithAsyncContext(async hub => { + return runWithAsyncContext(async () => { + const hub = getCurrentHub(); let requestTransaction: Transaction | undefined = getTransactionFromRequest(req); let dataFetcherSpan; diff --git a/packages/nextjs/src/server/wrapApiHandlerWithSentry.ts b/packages/nextjs/src/server/wrapApiHandlerWithSentry.ts index 3799ff94905a..3ebf97d4b614 100644 --- a/packages/nextjs/src/server/wrapApiHandlerWithSentry.ts +++ b/packages/nextjs/src/server/wrapApiHandlerWithSentry.ts @@ -1,4 +1,4 @@ -import { hasTracingEnabled, runWithAsyncContext } from '@sentry/core'; +import { getCurrentHub, hasTracingEnabled, runWithAsyncContext } from '@sentry/core'; import { captureException, startTransaction } from '@sentry/node'; import type { Transaction } from '@sentry/types'; import { @@ -63,7 +63,8 @@ export function withSentry(apiHandler: NextApiHandler, parameterizedRoute?: stri // eslint-disable-next-line complexity, @typescript-eslint/no-explicit-any const boundHandler = runWithAsyncContext( // eslint-disable-next-line complexity - async hub => { + async () => { + const hub = getCurrentHub(); let transaction: Transaction | undefined; const currentScope = hub.getScope(); const options = hub.getClient()?.getOptions(); diff --git a/packages/nextjs/src/server/wrapServerComponentWithSentry.ts b/packages/nextjs/src/server/wrapServerComponentWithSentry.ts index 73e331424c5c..8b0f1d8f2d79 100644 --- a/packages/nextjs/src/server/wrapServerComponentWithSentry.ts +++ b/packages/nextjs/src/server/wrapServerComponentWithSentry.ts @@ -1,4 +1,10 @@ -import { addTracingExtensions, captureException, runWithAsyncContext, startTransaction } from '@sentry/core'; +import { + addTracingExtensions, + captureException, + getCurrentHub, + runWithAsyncContext, + startTransaction, +} from '@sentry/core'; import { baggageHeaderToDynamicSamplingContext, extractTraceparentData } from '@sentry/utils'; import { isNotFoundNavigationError, isRedirectNavigationError } from '../common/nextNavigationErrorUtils'; @@ -20,7 +26,9 @@ export function wrapServerComponentWithSentry any> // hook. 🤯 return new Proxy(appDirComponent, { apply: (originalFunction, thisArg, args) => { - return runWithAsyncContext(hub => { + return runWithAsyncContext(() => { + const hub = getCurrentHub(); + let maybePromiseResult; const traceparentData = context.sentryTraceHeader diff --git a/packages/nextjs/test/serverSdk.test.ts b/packages/nextjs/test/serverSdk.test.ts index 4367c9ec1abc..5867132075fd 100644 --- a/packages/nextjs/test/serverSdk.test.ts +++ b/packages/nextjs/test/serverSdk.test.ts @@ -117,7 +117,8 @@ describe('Server init()', () => { it("initializes both global hub and domain hub when there's an active domain", () => { const globalHub = getCurrentHub(); - runWithAsyncContext(globalHub2 => { + runWithAsyncContext(() => { + const globalHub2 = getCurrentHub(); // If we call runWithAsyncContext before init, it executes the callback in the same context as there is no // strategy yet expect(globalHub2).toBe(globalHub); @@ -126,7 +127,8 @@ describe('Server init()', () => { init({}); - runWithAsyncContext(domainHub => { + runWithAsyncContext(() => { + const domainHub = getCurrentHub(); // this tag should end up only in the domain hub domainHub.setTag('dogs', 'areGreat'); diff --git a/packages/node/src/async/domain.ts b/packages/node/src/async/domain.ts index c53f7a7e22fc..628d2428e8ed 100644 --- a/packages/node/src/async/domain.ts +++ b/packages/node/src/async/domain.ts @@ -26,12 +26,12 @@ function createNewHub(parent: Hub | undefined): Hub { return getHubFromCarrier(carrier); } -function runWithAsyncContext(callback: (hub: Hub) => T, options: RunWithAsyncContextOptions): T { +function runWithAsyncContext(callback: () => T, options: RunWithAsyncContextOptions): T { const activeDomain = getActiveDomain(); if (activeDomain && options?.reuseExisting) { // We're already in a domain, so we don't need to create a new one, just call the callback with the current hub - return callback(getHubFromCarrier(activeDomain)); + return callback(); } const local = domain.create() as domain.Domain & Carrier; @@ -41,7 +41,7 @@ function runWithAsyncContext(callback: (hub: Hub) => T, options: RunWithAsync setHubOnCarrier(local, newHub); return local.bind(() => { - return callback(newHub); + return callback(); })(); } diff --git a/packages/node/src/async/hooks.ts b/packages/node/src/async/hooks.ts index 840236d5b2c1..c7e59de997ef 100644 --- a/packages/node/src/async/hooks.ts +++ b/packages/node/src/async/hooks.ts @@ -28,19 +28,19 @@ export function setHooksAsyncContextStrategy(): void { return getHubFromCarrier(carrier); } - function runWithAsyncContext(callback: (hub: Hub) => T, options: RunWithAsyncContextOptions): T { + function runWithAsyncContext(callback: () => T, options: RunWithAsyncContextOptions): T { const existingHub = getCurrentHub(); if (existingHub && options?.reuseExisting) { // We're already in an async context, so we don't need to create a new one // just call the callback with the current hub - return callback(existingHub); + return callback(); } const newHub = createNewHub(existingHub); return asyncStorage.run(newHub, () => { - return callback(newHub); + return callback(); }); } diff --git a/packages/node/src/handlers.ts b/packages/node/src/handlers.ts index 0a0ddee02a75..14b2abf9a662 100644 --- a/packages/node/src/handlers.ts +++ b/packages/node/src/handlers.ts @@ -187,7 +187,8 @@ export function requestHandler( }); }; } - runWithAsyncContext(currentHub => { + runWithAsyncContext(() => { + const currentHub = getCurrentHub(); currentHub.configureScope(scope => { scope.setSDKProcessingMetadata({ request: req, diff --git a/packages/node/test/async/domain.test.ts b/packages/node/test/async/domain.test.ts index 8b608c778fa0..84c3362b9882 100644 --- a/packages/node/test/async/domain.test.ts +++ b/packages/node/test/async/domain.test.ts @@ -22,13 +22,15 @@ describe('domains', () => { const globalHub = getCurrentHub(); globalHub.setExtra('a', 'b'); - runWithAsyncContext(hub1 => { + runWithAsyncContext(() => { + const hub1 = getCurrentHub(); expect(hub1).toEqual(globalHub); hub1.setExtra('c', 'd'); expect(hub1).not.toEqual(globalHub); - runWithAsyncContext(hub2 => { + runWithAsyncContext(() => { + const hub2 = getCurrentHub(); expect(hub2).toEqual(hub1); expect(hub2).not.toEqual(globalHub); @@ -53,13 +55,15 @@ describe('domains', () => { const globalHub = getCurrentHub(); await addRandomExtra(globalHub, 'a'); - await runWithAsyncContext(async hub1 => { + await runWithAsyncContext(async () => { + const hub1 = getCurrentHub(); expect(hub1).toEqual(globalHub); await addRandomExtra(hub1, 'b'); expect(hub1).not.toEqual(globalHub); - await runWithAsyncContext(async hub2 => { + await runWithAsyncContext(async () => { + const hub2 = getCurrentHub(); expect(hub2).toEqual(hub1); expect(hub2).not.toEqual(globalHub); @@ -72,7 +76,8 @@ describe('domains', () => { test('hub single instance', () => { setDomainAsyncContextStrategy(); - runWithAsyncContext(hub => { + runWithAsyncContext(() => { + const hub = getCurrentHub(); expect(hub).toBe(getCurrentHub()); }); }); @@ -80,8 +85,10 @@ describe('domains', () => { test('within a domain not reused', () => { setDomainAsyncContextStrategy(); - runWithAsyncContext(hub1 => { - runWithAsyncContext(hub2 => { + runWithAsyncContext(() => { + const hub1 = getCurrentHub(); + runWithAsyncContext(() => { + const hub2 = getCurrentHub(); expect(hub1).not.toBe(hub2); }); }); @@ -90,9 +97,11 @@ describe('domains', () => { test('within a domain reused when requested', () => { setDomainAsyncContextStrategy(); - runWithAsyncContext(hub1 => { + runWithAsyncContext(() => { + const hub1 = getCurrentHub(); runWithAsyncContext( - hub2 => { + () => { + const hub2 = getCurrentHub(); expect(hub1).toBe(hub2); }, { reuseExisting: true }, @@ -106,7 +115,8 @@ describe('domains', () => { let d1done = false; let d2done = false; - runWithAsyncContext(hub => { + runWithAsyncContext(() => { + const hub = getCurrentHub(); hub.getStack().push({ client: 'process' } as any); expect(hub.getStack()[1]).toEqual({ client: 'process' }); // Just in case so we don't have to worry which one finishes first @@ -119,7 +129,8 @@ describe('domains', () => { }); }); - runWithAsyncContext(hub => { + runWithAsyncContext(() => { + const hub = getCurrentHub(); hub.getStack().push({ client: 'local' } as any); expect(hub.getStack()[1]).toEqual({ client: 'local' }); setTimeout(() => { diff --git a/packages/node/test/async/hooks.test.ts b/packages/node/test/async/hooks.test.ts index da741d7684f5..8c4c5decab76 100644 --- a/packages/node/test/async/hooks.test.ts +++ b/packages/node/test/async/hooks.test.ts @@ -15,8 +15,10 @@ conditionalTest({ min: 12 })('async_hooks', () => { }); test('without strategy hubs should be equal', () => { - runWithAsyncContext(hub1 => { - runWithAsyncContext(hub2 => { + runWithAsyncContext(() => { + const hub1 = getCurrentHub(); + runWithAsyncContext(() => { + const hub2 = getCurrentHub(); expect(hub1).toBe(hub2); }); }); @@ -28,13 +30,15 @@ conditionalTest({ min: 12 })('async_hooks', () => { const globalHub = getCurrentHub(); globalHub.setExtra('a', 'b'); - runWithAsyncContext(hub1 => { + runWithAsyncContext(() => { + const hub1 = getCurrentHub(); expect(hub1).toEqual(globalHub); hub1.setExtra('c', 'd'); expect(hub1).not.toEqual(globalHub); - runWithAsyncContext(hub2 => { + runWithAsyncContext(() => { + const hub2 = getCurrentHub(); expect(hub2).toEqual(hub1); expect(hub2).not.toEqual(globalHub); @@ -59,13 +63,15 @@ conditionalTest({ min: 12 })('async_hooks', () => { const globalHub = getCurrentHub(); await addRandomExtra(globalHub, 'a'); - await runWithAsyncContext(async hub1 => { + await runWithAsyncContext(async () => { + const hub1 = getCurrentHub(); expect(hub1).toEqual(globalHub); await addRandomExtra(hub1, 'b'); expect(hub1).not.toEqual(globalHub); - await runWithAsyncContext(async hub2 => { + await runWithAsyncContext(async () => { + const hub2 = getCurrentHub(); expect(hub2).toEqual(hub1); expect(hub2).not.toEqual(globalHub); @@ -78,16 +84,19 @@ conditionalTest({ min: 12 })('async_hooks', () => { test('context single instance', () => { setHooksAsyncContextStrategy(); - runWithAsyncContext(hub => { - expect(hub).toBe(getCurrentHub()); + const globalHub = getCurrentHub(); + runWithAsyncContext(() => { + expect(globalHub).not.toBe(getCurrentHub()); }); }); test('context within a context not reused', () => { setHooksAsyncContextStrategy(); - runWithAsyncContext(hub1 => { - runWithAsyncContext(hub2 => { + runWithAsyncContext(() => { + const hub1 = getCurrentHub(); + runWithAsyncContext(() => { + const hub2 = getCurrentHub(); expect(hub1).not.toBe(hub2); }); }); @@ -96,9 +105,11 @@ conditionalTest({ min: 12 })('async_hooks', () => { test('context within a context reused when requested', () => { setHooksAsyncContextStrategy(); - runWithAsyncContext(hub1 => { + runWithAsyncContext(() => { + const hub1 = getCurrentHub(); runWithAsyncContext( - hub2 => { + () => { + const hub2 = getCurrentHub(); expect(hub1).toBe(hub2); }, { reuseExisting: true }, @@ -112,7 +123,8 @@ conditionalTest({ min: 12 })('async_hooks', () => { let d1done = false; let d2done = false; - runWithAsyncContext(hub => { + runWithAsyncContext(() => { + const hub = getCurrentHub(); hub.getStack().push({ client: 'process' } as any); expect(hub.getStack()[1]).toEqual({ client: 'process' }); // Just in case so we don't have to worry which one finishes first @@ -125,7 +137,8 @@ conditionalTest({ min: 12 })('async_hooks', () => { }); }); - runWithAsyncContext(hub => { + runWithAsyncContext(() => { + const hub = getCurrentHub(); hub.getStack().push({ client: 'local' } as any); expect(hub.getStack()[1]).toEqual({ client: 'local' }); setTimeout(() => { diff --git a/packages/node/test/index.test.ts b/packages/node/test/index.test.ts index e72ab8ecf3ae..8b035dff7b03 100644 --- a/packages/node/test/index.test.ts +++ b/packages/node/test/index.test.ts @@ -291,7 +291,8 @@ describe('SentryNode', () => { setNodeAsyncContextStrategy(); const client = new NodeClient(options); - runWithAsyncContext(hub => { + runWithAsyncContext(() => { + const hub = getCurrentHub(); hub.bindClient(client); expect(getCurrentHub().getClient()).toBe(client); hub.captureEvent({ message: 'test domain' });