123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- var {
- _optionalChain
- } = require('@sentry/utils');
- Object.defineProperty(exports, '__esModule', { value: true });
- const core = require('@sentry/core');
- const utils = require('@sentry/utils');
- const platformSupportsStreaming = require('./platformSupportsStreaming.js');
- const responseEnd = require('./responseEnd.js');
- /**
- * Grabs a span off a Next.js datafetcher request object, if it was previously put there via
- * `setSpanOnRequest`.
- *
- * @param req The Next.js datafetcher request object
- * @returns the span on the request object if there is one, or `undefined` if the request object didn't have one.
- */
- function getSpanFromRequest(req) {
- return req._sentrySpan;
- }
- function setSpanOnRequest(transaction, req) {
- req._sentrySpan = transaction;
- }
- /**
- * Wraps a function that potentially throws. If it does, the error is passed to `captureException` and rethrown.
- *
- * Note: This function turns the wrapped function into an asynchronous one.
- */
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- function withErrorInstrumentation(
- origFunction,
- ) {
- return async function ( ...origFunctionArguments) {
- try {
- return await origFunction.apply(this, origFunctionArguments);
- } catch (e) {
- // TODO: Extract error logic from `withSentry` in here or create a new wrapper with said logic or something like that.
- core.captureException(e, { mechanism: { handled: false } });
- throw e;
- }
- };
- }
- /**
- * Calls a server-side data fetching function (that takes a `req` and `res` object in its context) with tracing
- * instrumentation. A transaction will be created for the incoming request (if it doesn't already exist) in addition to
- * a span for the wrapped data fetching function.
- *
- * All of the above happens in an isolated domain, meaning all thrown errors will be associated with the correct span.
- *
- * @param origDataFetcher The data fetching method to call.
- * @param origFunctionArguments The arguments to call the data fetching method with.
- * @param req The data fetching function's request object.
- * @param res The data fetching function's response object.
- * @param options Options providing details for the created transaction and span.
- * @returns what the data fetching method call returned.
- */
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- function withTracedServerSideDataFetcher(
- origDataFetcher,
- req,
- res,
- options
- ,
- ) {
- return async function ( ...args) {
- return core.withIsolationScope(async isolationScope => {
- isolationScope.setSDKProcessingMetadata({
- request: req,
- });
- const sentryTrace =
- req.headers && utils.isString(req.headers['sentry-trace']) ? req.headers['sentry-trace'] : undefined;
- const baggage = _optionalChain([req, 'access', _ => _.headers, 'optionalAccess', _2 => _2.baggage]);
- return core.continueTrace({ sentryTrace, baggage }, () => {
- let requestSpan = getSpanFromRequest(req);
- if (!requestSpan) {
- // TODO(v8): Simplify these checks when startInactiveSpan always returns a span
- requestSpan = core.startInactiveSpan({
- name: options.requestedRouteName,
- op: 'http.server',
- attributes: {
- [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.nextjs',
- [core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',
- },
- });
- if (requestSpan) {
- requestSpan.setStatus('ok');
- setSpanOnRequest(requestSpan, req);
- responseEnd.autoEndSpanOnResponseEnd(requestSpan, res);
- }
- }
- const withActiveSpanCallback = () => {
- return core.startSpanManual(
- {
- op: 'function.nextjs',
- name: `${options.dataFetchingMethodName} (${options.dataFetcherRouteName})`,
- attributes: {
- [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.nextjs',
- [core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',
- },
- },
- async dataFetcherSpan => {
- _optionalChain([dataFetcherSpan, 'optionalAccess', _3 => _3.setStatus, 'call', _4 => _4('ok')]);
- try {
- return await origDataFetcher.apply(this, args);
- } catch (e) {
- _optionalChain([dataFetcherSpan, 'optionalAccess', _5 => _5.setStatus, 'call', _6 => _6('internal_error')]);
- _optionalChain([requestSpan, 'optionalAccess', _7 => _7.setStatus, 'call', _8 => _8('internal_error')]);
- throw e;
- } finally {
- _optionalChain([dataFetcherSpan, 'optionalAccess', _9 => _9.end, 'call', _10 => _10()]);
- if (!platformSupportsStreaming.platformSupportsStreaming()) {
- await responseEnd.flushQueue();
- }
- }
- },
- );
- };
- if (requestSpan) {
- return core.withActiveSpan(requestSpan, withActiveSpanCallback);
- } else {
- return withActiveSpanCallback();
- }
- });
- });
- };
- }
- /**
- * Call a data fetcher and trace it. Only traces the function if there is an active transaction on the scope.
- *
- * We only do the following until we move transaction creation into this function: When called, the wrapped function
- * will also update the name of the active transaction with a parameterized route provided via the `options` argument.
- */
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- async function callDataFetcherTraced(
- origFunction,
- origFunctionArgs,
- options
- ,
- ) {
- const { parameterizedRoute, dataFetchingMethodName } = options;
- return core.startSpan(
- {
- op: 'function.nextjs',
- name: `${dataFetchingMethodName} (${parameterizedRoute})`,
- attributes: {
- [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.nextjs',
- [core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',
- },
- },
- async dataFetcherSpan => {
- _optionalChain([dataFetcherSpan, 'optionalAccess', _11 => _11.setStatus, 'call', _12 => _12('ok')]);
- try {
- return await origFunction(...origFunctionArgs);
- } catch (e) {
- _optionalChain([dataFetcherSpan, 'optionalAccess', _13 => _13.setStatus, 'call', _14 => _14('internal_error')]);
- core.captureException(e, { mechanism: { handled: false } });
- throw e;
- } finally {
- _optionalChain([dataFetcherSpan, 'optionalAccess', _15 => _15.end, 'call', _16 => _16()]);
- if (!platformSupportsStreaming.platformSupportsStreaming()) {
- await responseEnd.flushQueue();
- }
- }
- },
- );
- }
- exports.callDataFetcherTraced = callDataFetcherTraced;
- exports.getSpanFromRequest = getSpanFromRequest;
- exports.withErrorInstrumentation = withErrorInstrumentation;
- exports.withTracedServerSideDataFetcher = withTracedServerSideDataFetcher;
- //# sourceMappingURL=wrapperUtils.js.map
|