Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
1 line
8.7 KiB
Plaintext
1 line
8.7 KiB
Plaintext
{"version":3,"file":"wrapApiHandlerWithSentry.js","sources":["../../../../src/common/pages-router-instrumentation/wrapApiHandlerWithSentry.ts"],"sourcesContent":["import {\n captureException,\n continueTrace,\n debug,\n getActiveSpan,\n httpRequestToRequestData,\n isString,\n objectify,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n setHttpStatus,\n startSpanManual,\n withIsolationScope,\n} from '@sentry/core';\nimport type { NextApiRequest } from 'next';\nimport type { AugmentedNextApiResponse, NextApiHandler } from '../types';\nimport { flushSafelyWithTimeout, waitUntil } from '../utils/responseEnd';\nimport { dropNextjsRootContext, escapeNextjsTracing } from '../utils/tracingUtils';\n\nexport type AugmentedNextApiRequest = NextApiRequest & {\n __withSentry_applied__?: boolean;\n};\n\n/**\n * Wrap the given API route handler with error nad performance monitoring.\n *\n * @param apiHandler The handler exported from the user's API page route file, which may or may not already be\n * wrapped with `withSentry`\n * @param parameterizedRoute The page's parameterized route.\n * @returns The wrapped handler which will always return a Promise.\n */\nexport function wrapApiHandlerWithSentry(apiHandler: NextApiHandler, parameterizedRoute: string): NextApiHandler {\n return new Proxy(apiHandler, {\n apply: (\n wrappingTarget,\n thisArg,\n args: [AugmentedNextApiRequest | undefined, AugmentedNextApiResponse | undefined],\n ) => {\n dropNextjsRootContext();\n return escapeNextjsTracing(() => {\n const [req, res] = args;\n\n if (!req) {\n debug.log(\n `Wrapped API handler on route \"${parameterizedRoute}\" was not passed a request object. Will not instrument.`,\n );\n return wrappingTarget.apply(thisArg, args);\n } else if (!res) {\n debug.log(\n `Wrapped API handler on route \"${parameterizedRoute}\" was not passed a response object. Will not instrument.`,\n );\n return wrappingTarget.apply(thisArg, args);\n }\n\n // Prevent double wrapping of the same request.\n if (req.__withSentry_applied__) {\n return wrappingTarget.apply(thisArg, args);\n }\n req.__withSentry_applied__ = true;\n\n return withIsolationScope(isolationScope => {\n // Normally, there is an active span here (from Next.js OTEL) and we just use that as parent\n // Else, we manually continueTrace from the incoming headers\n const continueTraceIfNoActiveSpan = getActiveSpan()\n ? <T>(_opts: unknown, callback: () => T) => callback()\n : continueTrace;\n\n return continueTraceIfNoActiveSpan(\n {\n sentryTrace:\n req.headers && isString(req.headers['sentry-trace']) ? req.headers['sentry-trace'] : undefined,\n baggage: req.headers?.baggage,\n },\n () => {\n const reqMethod = `${(req.method || 'GET').toUpperCase()} `;\n const normalizedRequest = httpRequestToRequestData(req);\n\n isolationScope.setSDKProcessingMetadata({ normalizedRequest });\n isolationScope.setTransactionName(`${reqMethod}${parameterizedRoute}`);\n\n return startSpanManual(\n {\n name: `${reqMethod}${parameterizedRoute}`,\n op: 'http.server',\n forceTransaction: true,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.nextjs',\n },\n },\n async span => {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n res.end = new Proxy(res.end, {\n apply(target, thisArg, argArray) {\n setHttpStatus(span, res.statusCode);\n span.end();\n waitUntil(flushSafelyWithTimeout());\n return target.apply(thisArg, argArray);\n },\n });\n try {\n return await wrappingTarget.apply(thisArg, args);\n } catch (e) {\n // In case we have a primitive, wrap it in the equivalent wrapper class (string -> String, etc.) so that we can\n // store a seen flag on it. (Because of the one-way-on-Vercel-one-way-off-of-Vercel approach we've been forced\n // to take, it can happen that the same thrown object gets caught in two different ways, and flagging it is a\n // way to prevent it from actually being reported twice.)\n const objectifiedErr = objectify(e);\n\n captureException(objectifiedErr, {\n mechanism: {\n type: 'auto.http.nextjs.api_handler',\n handled: false,\n data: {\n wrapped_handler: wrappingTarget.name,\n function: 'withSentry',\n },\n },\n });\n\n setHttpStatus(span, 500);\n span.end();\n\n // we need to await the flush here to ensure that the error is captured\n // as the runtime freezes as soon as the error is thrown below\n await flushSafelyWithTimeout();\n\n // We rethrow here so that nextjs can do with the error whatever it would normally do. (Sometimes \"whatever it\n // would normally do\" is to allow the error to bubble up to the global handlers - another reason we need to mark\n // the error as already having been captured.)\n throw objectifiedErr;\n }\n },\n );\n },\n );\n });\n });\n },\n });\n}\n"],"names":[],"mappings":"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"} |