From c7de9c33c6cbef3f0976ce0503fa1d2e190f7ef5 Mon Sep 17 00:00:00 2001 From: Charly Gomez Date: Fri, 18 Oct 2024 15:15:52 +0200 Subject: [PATCH 1/2] await flush in api handlers --- .../src/common/wrapApiHandlerWithSentry.ts | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/packages/nextjs/src/common/wrapApiHandlerWithSentry.ts b/packages/nextjs/src/common/wrapApiHandlerWithSentry.ts index cef85c320ae0..7e1927dc6850 100644 --- a/packages/nextjs/src/common/wrapApiHandlerWithSentry.ts +++ b/packages/nextjs/src/common/wrapApiHandlerWithSentry.ts @@ -7,7 +7,7 @@ import { withIsolationScope, } from '@sentry/core'; import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core'; -import { isString, logger, objectify, vercelWaitUntil } from '@sentry/utils'; +import { isString, logger, objectify } from '@sentry/utils'; import type { NextApiRequest } from 'next'; import type { AugmentedNextApiResponse, NextApiHandler } from './types'; import { flushSafelyWithTimeout } from './utils/responseEnd'; @@ -77,16 +77,6 @@ export function wrapApiHandlerWithSentry(apiHandler: NextApiHandler, parameteriz }, }, async span => { - // eslint-disable-next-line @typescript-eslint/unbound-method - res.end = new Proxy(res.end, { - apply(target, thisArg, argArray) { - setHttpStatus(span, res.statusCode); - span.end(); - vercelWaitUntil(flushSafelyWithTimeout()); - return target.apply(thisArg, argArray); - }, - }); - try { return await wrappingTarget.apply(thisArg, args); } catch (e) { @@ -110,7 +100,9 @@ export function wrapApiHandlerWithSentry(apiHandler: NextApiHandler, parameteriz setHttpStatus(span, 500); span.end(); - vercelWaitUntil(flushSafelyWithTimeout()); + // we need to await the flush here to ensure that the error is captured + // as the runtime freezes as soon as the error is thrown below + await flushSafelyWithTimeout(); // We rethrow here so that nextjs can do with the error whatever it would normally do. (Sometimes "whatever it // would normally do" is to allow the error to bubble up to the global handlers - another reason we need to mark From f9df1b4ab80f8e79b9f35874494d0fe6ccf8b4d6 Mon Sep 17 00:00:00 2001 From: Charly Gomez Date: Fri, 18 Oct 2024 15:38:21 +0200 Subject: [PATCH 2/2] patch res.end for all transactions --- .../nextjs/src/common/wrapApiHandlerWithSentry.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/nextjs/src/common/wrapApiHandlerWithSentry.ts b/packages/nextjs/src/common/wrapApiHandlerWithSentry.ts index 7e1927dc6850..a6463b0a7791 100644 --- a/packages/nextjs/src/common/wrapApiHandlerWithSentry.ts +++ b/packages/nextjs/src/common/wrapApiHandlerWithSentry.ts @@ -7,7 +7,7 @@ import { withIsolationScope, } from '@sentry/core'; import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core'; -import { isString, logger, objectify } from '@sentry/utils'; +import { isString, logger, objectify, vercelWaitUntil } from '@sentry/utils'; import type { NextApiRequest } from 'next'; import type { AugmentedNextApiResponse, NextApiHandler } from './types'; import { flushSafelyWithTimeout } from './utils/responseEnd'; @@ -77,6 +77,15 @@ export function wrapApiHandlerWithSentry(apiHandler: NextApiHandler, parameteriz }, }, async span => { + // eslint-disable-next-line @typescript-eslint/unbound-method + res.end = new Proxy(res.end, { + apply(target, thisArg, argArray) { + setHttpStatus(span, res.statusCode); + span.end(); + vercelWaitUntil(flushSafelyWithTimeout()); + return target.apply(thisArg, argArray); + }, + }); try { return await wrappingTarget.apply(thisArg, args); } catch (e) {