@sentry/nextjs
Version:
Official Sentry SDK for Next.js
90 lines (87 loc) • 3.84 kB
JavaScript
import { withIsolationScope, getCurrentScope, winterCGRequestToRequestData, parseStringToURLObject, isURLObjectRelative, getActiveSpan, getRootSpan, spanToJSON, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, SEMANTIC_ATTRIBUTE_SENTRY_OP, setCapturedScopesOnSpan, startSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, handleCallbackErrors, captureException } from '@sentry/core';
import { addHeadersAsAttributes } from '../common/utils/addHeadersAsAttributes.js';
import { waitUntil, flushSafelyWithTimeout } from '../common/utils/responseEnd.js';
import { URL_PATH, URL_FULL, HTTP_ROUTE } from '@sentry/conventions/attributes';
function wrapApiHandlerWithSentry(handler, parameterizedRoute) {
return new Proxy(handler, {
apply: async (wrappingTarget, thisArg, args) => {
return withIsolationScope((isolationScope) => {
const req = args[0];
const currentScope = getCurrentScope();
let headerAttributes = {};
if (req instanceof Request) {
isolationScope.setSDKProcessingMetadata({
normalizedRequest: winterCGRequestToRequestData(req)
});
currentScope.setTransactionName(`${req.method} ${parameterizedRoute}`);
headerAttributes = addHeadersAsAttributes(req.headers);
} else {
currentScope.setTransactionName(`handler (${parameterizedRoute})`);
}
let spanName;
let op = "http.server";
const urlObject = req instanceof Request ? parseStringToURLObject(req.url) : void 0;
const urlAttributes = {
[URL_FULL]: urlObject && !isURLObjectRelative(urlObject) ? urlObject.href : void 0,
[URL_PATH]: urlObject?.pathname
};
const activeSpan = getActiveSpan();
if (activeSpan) {
spanName = `handler (${parameterizedRoute})`;
op = void 0;
const rootSpan = getRootSpan(activeSpan);
if (rootSpan) {
const rootSpanAttributes = spanToJSON(rootSpan).data;
rootSpan.updateName(
req instanceof Request ? `${req.method} ${parameterizedRoute}` : `handler ${parameterizedRoute}`
);
rootSpan.setAttributes({
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: "http.server",
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "route",
[URL_FULL]: rootSpanAttributes[URL_FULL] ?? urlAttributes[URL_FULL],
[URL_PATH]: rootSpanAttributes[URL_PATH] ?? urlAttributes[URL_PATH],
[HTTP_ROUTE]: parameterizedRoute,
...headerAttributes
});
setCapturedScopesOnSpan(rootSpan, currentScope, isolationScope);
}
} else if (req instanceof Request) {
spanName = `${req.method} ${parameterizedRoute}`;
} else {
spanName = `handler ${parameterizedRoute}`;
}
return startSpan(
{
name: spanName,
op,
attributes: {
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "route",
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.nextjs.wrap_api_handler",
[HTTP_ROUTE]: parameterizedRoute,
...urlAttributes,
...headerAttributes
}
},
() => {
return handleCallbackErrors(
() => wrappingTarget.apply(thisArg, args),
(error) => {
captureException(error, {
mechanism: {
type: "auto.function.nextjs.wrap_api_handler",
handled: false
}
});
},
() => {
waitUntil(flushSafelyWithTimeout());
}
);
}
);
});
}
});
}
export { wrapApiHandlerWithSentry };
//# sourceMappingURL=wrapApiHandlerWithSentry.js.map