123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- import { _nullishCoalesce, _optionalChain } from '@sentry/utils';
- import { addTracingExtensions, withIsolationScope, continueTrace, startSpan, handleCallbackErrors, captureException, getIsolationScope, getClient } from '@sentry/core';
- import { logger } from '@sentry/utils';
- import { DEBUG_BUILD } from './debug-build.js';
- import { isNotFoundNavigationError, isRedirectNavigationError } from './nextNavigationErrorUtils.js';
- import { platformSupportsStreaming } from './utils/platformSupportsStreaming.js';
- import { flushQueue } from './utils/responseEnd.js';
- /**
- * Wraps a Next.js Server Action implementation with Sentry Error and Performance instrumentation.
- */
- function withServerActionInstrumentation(
- ...args
- ) {
- if (typeof args[1] === 'function') {
- const [serverActionName, callback] = args;
- return withServerActionInstrumentationImplementation(serverActionName, {}, callback);
- } else {
- const [serverActionName, options, callback] = args;
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- return withServerActionInstrumentationImplementation(serverActionName, options, callback);
- }
- }
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- async function withServerActionInstrumentationImplementation(
- serverActionName,
- options,
- callback,
- ) {
- addTracingExtensions();
- return withIsolationScope(isolationScope => {
- const sendDefaultPii = _optionalChain([getClient, 'call', _ => _(), 'optionalAccess', _2 => _2.getOptions, 'call', _3 => _3(), 'access', _4 => _4.sendDefaultPii]);
- let sentryTraceHeader;
- let baggageHeader;
- const fullHeadersObject = {};
- try {
- sentryTraceHeader = _nullishCoalesce(_optionalChain([options, 'access', _5 => _5.headers, 'optionalAccess', _6 => _6.get, 'call', _7 => _7('sentry-trace')]), () => ( undefined));
- baggageHeader = _optionalChain([options, 'access', _8 => _8.headers, 'optionalAccess', _9 => _9.get, 'call', _10 => _10('baggage')]);
- _optionalChain([options, 'access', _11 => _11.headers, 'optionalAccess', _12 => _12.forEach, 'call', _13 => _13((value, key) => {
- fullHeadersObject[key] = value;
- })]);
- } catch (e) {
- DEBUG_BUILD &&
- logger.warn(
- "Sentry wasn't able to extract the tracing headers for a server action. Will not trace this request.",
- );
- }
- isolationScope.setSDKProcessingMetadata({
- request: {
- headers: fullHeadersObject,
- },
- });
- return continueTrace(
- {
- sentryTrace: sentryTraceHeader,
- baggage: baggageHeader,
- },
- async () => {
- try {
- return await startSpan(
- {
- op: 'function.server_action',
- name: `serverAction/${serverActionName}`,
- metadata: {
- source: 'route',
- },
- },
- async span => {
- const result = await handleCallbackErrors(callback, error => {
- if (isNotFoundNavigationError(error)) {
- // We don't want to report "not-found"s
- _optionalChain([span, 'optionalAccess', _14 => _14.setStatus, 'call', _15 => _15('not_found')]);
- } else if (isRedirectNavigationError(error)) {
- // Don't do anything for redirects
- } else {
- _optionalChain([span, 'optionalAccess', _16 => _16.setStatus, 'call', _17 => _17('internal_error')]);
- captureException(error, {
- mechanism: {
- handled: false,
- },
- });
- }
- });
- if (options.recordResponse !== undefined ? options.recordResponse : sendDefaultPii) {
- getIsolationScope().setExtra('server_action_result', result);
- }
- if (options.formData) {
- options.formData.forEach((value, key) => {
- getIsolationScope().setExtra(
- `server_action_form_data.${key}`,
- typeof value === 'string' ? value : '[non-string value]',
- );
- });
- }
- return result;
- },
- );
- } finally {
- if (!platformSupportsStreaming()) {
- // Lambdas require manual flushing to prevent execution freeze before the event is sent
- await flushQueue();
- }
- if (process.env.NEXT_RUNTIME === 'edge') {
- // flushQueue should not throw
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- flushQueue();
- }
- }
- },
- );
- });
- }
- export { withServerActionInstrumentation };
- //# sourceMappingURL=withServerActionInstrumentation.js.map
|