@sentry/nextjs
Version:
Official Sentry SDK for Next.js
113 lines (104 loc) • 4.95 kB
JavaScript
var {
_nullishCoalesce,
_optionalChain
} = require('@sentry/utils');
Object.defineProperty(exports, '__esModule', { value: true });
const core = require('@sentry/core');
const utils = require('@sentry/utils');
const nextNavigationErrorUtils = require('./nextNavigationErrorUtils.js');
const commonObjectTracing = require('./utils/commonObjectTracing.js');
/**
* Wraps a generation function (e.g. generateMetadata) with Sentry error and performance instrumentation.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function wrapGenerationFunctionWithSentry(
generationFunction,
context,
) {
core.addTracingExtensions();
const { requestAsyncStorage, componentRoute, componentType, generationFunctionIdentifier } = context;
return new Proxy(generationFunction, {
apply: (originalFunction, thisArg, args) => {
let headers = undefined;
// We try-catch here just in case anything goes wrong with the async storage here goes wrong since it is Next.js internal API
try {
headers = _optionalChain([requestAsyncStorage, 'optionalAccess', _ => _.getStore, 'call', _2 => _2(), 'optionalAccess', _3 => _3.headers]);
} catch (e) {
/** empty */
}
let data = undefined;
if (_optionalChain([core.getClient, 'call', _4 => _4(), 'optionalAccess', _5 => _5.getOptions, 'call', _6 => _6(), 'access', _7 => _7.sendDefaultPii])) {
const props = args[0];
const params = props && typeof props === 'object' && 'params' in props ? props.params : undefined;
const searchParams =
props && typeof props === 'object' && 'searchParams' in props ? props.searchParams : undefined;
data = { params, searchParams };
}
return core.runWithAsyncContext(() => {
const transactionContext = core.continueTrace({
baggage: _optionalChain([headers, 'optionalAccess', _8 => _8.get, 'call', _9 => _9('baggage')]),
sentryTrace: _nullishCoalesce(_optionalChain([headers, 'optionalAccess', _10 => _10.get, 'call', _11 => _11('sentry-trace')]), () => ( undefined)),
});
// If there is no incoming trace, we are setting the transaction context to one that is shared between all other
// transactions for this request. We do this based on the `headers` object, which is the same for all components.
const propagationContext = core.getCurrentScope().getPropagationContext();
if (!transactionContext.traceId && !transactionContext.parentSpanId) {
const { traceId: commonTraceId, spanId: commonSpanId } = commonObjectTracing.commonObjectToPropagationContext(
headers,
propagationContext,
);
transactionContext.traceId = commonTraceId;
transactionContext.parentSpanId = commonSpanId;
}
return core.startSpanManual(
{
op: 'function.nextjs',
name: `${componentType}.${generationFunctionIdentifier} (${componentRoute})`,
origin: 'auto.function.nextjs',
...transactionContext,
data,
attributes: {
[core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',
},
metadata: {
// eslint-disable-next-line deprecation/deprecation
...transactionContext.metadata,
request: {
headers: headers ? utils.winterCGHeadersToDict(headers) : undefined,
},
},
},
span => {
return core.handleCallbackErrors(
() => originalFunction.apply(thisArg, args),
err => {
if (nextNavigationErrorUtils.isNotFoundNavigationError(err)) {
// We don't want to report "not-found"s
_optionalChain([span, 'optionalAccess', _12 => _12.setStatus, 'call', _13 => _13('not_found')]);
} else if (nextNavigationErrorUtils.isRedirectNavigationError(err)) {
// We don't want to report redirects
_optionalChain([span, 'optionalAccess', _14 => _14.setStatus, 'call', _15 => _15('ok')]);
} else {
_optionalChain([span, 'optionalAccess', _16 => _16.setStatus, 'call', _17 => _17('internal_error')]);
core.captureException(err, {
mechanism: {
handled: false,
data: {
function: 'wrapGenerationFunctionWithSentry',
},
},
});
}
},
() => {
_optionalChain([span, 'optionalAccess', _18 => _18.end, 'call', _19 => _19()]);
},
);
},
);
});
},
});
}
exports.wrapGenerationFunctionWithSentry = wrapGenerationFunctionWithSentry;
//# sourceMappingURL=wrapGenerationFunctionWithSentry.js.map