@sentry/nextjs
Version:
Official Sentry SDK for Next.js
119 lines (105 loc) • 4.42 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 debugBuild = require('./debug-build.js');
const platformSupportsStreaming = require('./utils/platformSupportsStreaming.js');
const responseEnd = require('./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,
) {
core.addTracingExtensions();
return core.runWithAsyncContext(async () => {
const sendDefaultPii = _optionalChain([core.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) {
debugBuild.DEBUG_BUILD &&
utils.logger.warn(
"Sentry wasn't able to extract the tracing headers for a server action. Will not trace this request.",
);
}
const currentScope = core.getCurrentScope();
const { traceparentData, dynamicSamplingContext, propagationContext } = utils.tracingContextFromHeaders(
sentryTraceHeader,
baggageHeader,
);
currentScope.setPropagationContext(propagationContext);
let res;
try {
res = await core.startSpan(
{
op: 'function.server_action',
name: `serverAction/${serverActionName}`,
status: 'ok',
...traceparentData,
metadata: {
source: 'route',
dynamicSamplingContext: traceparentData && !dynamicSamplingContext ? {} : dynamicSamplingContext,
request: {
headers: fullHeadersObject,
},
},
},
async span => {
const result = await core.handleCallbackErrors(callback, error => {
core.captureException(error, { mechanism: { handled: false } });
});
if (options.recordResponse !== undefined ? options.recordResponse : sendDefaultPii) {
_optionalChain([span, 'optionalAccess', _14 => _14.setAttribute, 'call', _15 => _15('server_action_result', result)]);
}
if (options.formData) {
options.formData.forEach((value, key) => {
_optionalChain([span, 'optionalAccess', _16 => _16.setAttribute, 'call', _17 => _17(
`server_action_form_data.${key}`,
typeof value === 'string' ? value : '[non-string value]',
)]);
});
}
return result;
},
);
} finally {
if (!platformSupportsStreaming.platformSupportsStreaming()) {
// Lambdas require manual flushing to prevent execution freeze before the event is sent
await responseEnd.flushQueue();
}
if (process.env.NEXT_RUNTIME === 'edge') {
// flushQueue should not throw
// eslint-disable-next-line @typescript-eslint/no-floating-promises
responseEnd.flushQueue();
}
}
return res;
});
}
exports.withServerActionInstrumentation = withServerActionInstrumentation;
//# sourceMappingURL=withServerActionInstrumentation.js.map