Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
231 lines
11 KiB
Plaintext
231 lines
11 KiB
Plaintext
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
|
const api = require('@opentelemetry/api');
|
|
const core = require('@sentry/core');
|
|
const opentelemetry = require('@sentry/opentelemetry');
|
|
const vercelEdge = require('@sentry/vercel-edge');
|
|
const debugBuild = require('../common/debug-build.js');
|
|
const nextSpanAttributes = require('../common/nextSpanAttributes.js');
|
|
const spanAttributesWithLogicAttached = require('../common/span-attributes-with-logic-attached.js');
|
|
const addHeadersAsAttributes = require('../common/utils/addHeadersAsAttributes.js');
|
|
const dropMiddlewareTunnelRequests = require('../common/utils/dropMiddlewareTunnelRequests.js');
|
|
const isBuild = require('../common/utils/isBuild.js');
|
|
const responseEnd = require('../common/utils/responseEnd.js');
|
|
const setUrlProcessingMetadata = require('../common/utils/setUrlProcessingMetadata.js');
|
|
const distDirRewriteFramesIntegration = require('./distDirRewriteFramesIntegration.js');
|
|
const wrapGetStaticPropsWithSentry = require('../common/pages-router-instrumentation/wrapGetStaticPropsWithSentry.js');
|
|
const wrapGetInitialPropsWithSentry = require('../common/pages-router-instrumentation/wrapGetInitialPropsWithSentry.js');
|
|
const wrapAppGetInitialPropsWithSentry = require('../common/pages-router-instrumentation/wrapAppGetInitialPropsWithSentry.js');
|
|
const wrapDocumentGetInitialPropsWithSentry = require('../common/pages-router-instrumentation/wrapDocumentGetInitialPropsWithSentry.js');
|
|
const wrapErrorGetInitialPropsWithSentry = require('../common/pages-router-instrumentation/wrapErrorGetInitialPropsWithSentry.js');
|
|
const wrapGetServerSidePropsWithSentry = require('../common/pages-router-instrumentation/wrapGetServerSidePropsWithSentry.js');
|
|
const wrapServerComponentWithSentry = require('../common/wrapServerComponentWithSentry.js');
|
|
const wrapRouteHandlerWithSentry = require('../common/wrapRouteHandlerWithSentry.js');
|
|
const wrapApiHandlerWithSentryVercelCrons = require('../common/pages-router-instrumentation/wrapApiHandlerWithSentryVercelCrons.js');
|
|
const wrapMiddlewareWithSentry = require('../common/wrapMiddlewareWithSentry.js');
|
|
const wrapPageComponentWithSentry = require('../common/pages-router-instrumentation/wrapPageComponentWithSentry.js');
|
|
const wrapGenerationFunctionWithSentry = require('../common/wrapGenerationFunctionWithSentry.js');
|
|
const withServerActionInstrumentation = require('../common/withServerActionInstrumentation.js');
|
|
const captureRequestError = require('../common/captureRequestError.js');
|
|
const _error = require('../common/pages-router-instrumentation/_error.js');
|
|
const nextSpan = require('../common/utils/nextSpan.js');
|
|
const wrapApiHandlerWithSentry = require('./wrapApiHandlerWithSentry.js');
|
|
|
|
// import/export got a false positive, and affects most of our index barrel files
|
|
// can be removed once following issue is fixed: https://github.com/import-js/eslint-plugin-import/issues/703
|
|
/* eslint-disable import/export */
|
|
|
|
const globalWithInjectedValues = core.GLOBAL_OBJ
|
|
|
|
;
|
|
|
|
/** Inits the Sentry NextJS SDK on the Edge Runtime. */
|
|
function init(options = {}) {
|
|
core.registerSpanErrorInstrumentation();
|
|
|
|
if (isBuild.isBuild()) {
|
|
return;
|
|
}
|
|
|
|
if (!debugBuild.DEBUG_BUILD && options.debug) {
|
|
// eslint-disable-next-line no-console
|
|
console.warn(
|
|
'[@sentry/nextjs] You have enabled `debug: true`, but Sentry debug logging was removed from your bundle (likely via `withSentryConfig({ disableLogger: true })` / `webpack.treeshake.removeDebugLogging: true`). Set that option to `false` to see Sentry debug output.',
|
|
);
|
|
}
|
|
|
|
const customDefaultIntegrations = vercelEdge.getDefaultIntegrations(options);
|
|
|
|
// This value is injected at build time, based on the output directory specified in the build config. Though a default
|
|
// is set there, we set it here as well, just in case something has gone wrong with the injection.
|
|
const distDirName = process.env._sentryRewriteFramesDistDir || globalWithInjectedValues._sentryRewriteFramesDistDir;
|
|
|
|
if (distDirName) {
|
|
customDefaultIntegrations.push(distDirRewriteFramesIntegration.distDirRewriteFramesIntegration({ distDirName }));
|
|
}
|
|
|
|
// Detect if running on OpenNext/Cloudflare
|
|
const isRunningOnCloudflare = responseEnd.isCloudflareWaitUntilAvailable();
|
|
|
|
const opts = {
|
|
defaultIntegrations: customDefaultIntegrations,
|
|
release: process.env._sentryRelease || globalWithInjectedValues._sentryRelease,
|
|
...options,
|
|
// Override runtime to 'cloudflare' when running on OpenNext/Cloudflare
|
|
...(isRunningOnCloudflare && { runtime: { name: 'cloudflare' } }),
|
|
};
|
|
|
|
// Use appropriate SDK metadata based on the runtime environment
|
|
if (isRunningOnCloudflare) {
|
|
core.applySdkMetadata(opts, 'nextjs', ['nextjs', 'cloudflare']);
|
|
} else {
|
|
core.applySdkMetadata(opts, 'nextjs', ['nextjs', 'vercel-edge']);
|
|
}
|
|
|
|
const client = vercelEdge.init(opts);
|
|
|
|
client?.on('spanStart', span => {
|
|
const spanAttributes = core.spanToJSON(span).data;
|
|
const rootSpan = core.getRootSpan(span);
|
|
const isRootSpan = span === rootSpan;
|
|
|
|
dropMiddlewareTunnelRequests.dropMiddlewareTunnelRequests(span, spanAttributes);
|
|
|
|
// Mark all spans generated by Next.js as 'auto'
|
|
if (spanAttributes?.['next.span_type'] !== undefined) {
|
|
span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto');
|
|
}
|
|
|
|
// Make sure middleware spans get the right op
|
|
if (spanAttributes?.['next.span_type'] === 'Middleware.execute') {
|
|
span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, 'http.server.middleware');
|
|
span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, 'url');
|
|
}
|
|
|
|
// We want to fork the isolation scope for incoming requests
|
|
if (spanAttributes?.[nextSpanAttributes.ATTR_NEXT_SPAN_TYPE] === 'BaseServer.handleRequest' && isRootSpan) {
|
|
const scopes = core.getCapturedScopesOnSpan(span);
|
|
|
|
const isolationScope = (scopes.isolationScope || core.getIsolationScope()).clone();
|
|
const scope = scopes.scope || core.getCurrentScope();
|
|
|
|
const currentScopesPointer = opentelemetry.getScopesFromContext(api.context.active());
|
|
if (currentScopesPointer) {
|
|
currentScopesPointer.isolationScope = isolationScope;
|
|
}
|
|
|
|
core.setCapturedScopesOnSpan(span, scope, isolationScope);
|
|
}
|
|
|
|
if (isRootSpan) {
|
|
// todo: check if we can set request headers for edge on sdkProcessingMetadata
|
|
const headers = core.getIsolationScope().getScopeData().sdkProcessingMetadata?.normalizedRequest?.headers;
|
|
addHeadersAsAttributes.addHeadersAsAttributes(headers, rootSpan);
|
|
}
|
|
});
|
|
|
|
// Use the preprocessEvent hook instead of an event processor, so that the users event processors receive the most
|
|
// up-to-date value, but also so that the logic that detects changes to the transaction names to set the source to
|
|
// "custom", doesn't trigger.
|
|
client?.on('preprocessEvent', event => {
|
|
// The otel auto inference will clobber the transaction name because the span has an http.target
|
|
if (
|
|
event.type === 'transaction' &&
|
|
event.contexts?.trace?.data?.['next.span_type'] === 'Middleware.execute' &&
|
|
event.contexts?.trace?.data?.['next.span_name']
|
|
) {
|
|
if (event.transaction) {
|
|
// Older nextjs versions pass the full url appended to the middleware name, which results in high cardinality transaction names.
|
|
// We want to remove the url from the name here.
|
|
const spanName = event.contexts.trace.data['next.span_name'];
|
|
|
|
if (typeof spanName === 'string') {
|
|
const match = spanName.match(/^middleware (GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)/);
|
|
if (match) {
|
|
const normalizedName = `middleware ${match[1]}`;
|
|
event.transaction = normalizedName;
|
|
} else {
|
|
event.transaction = core.stripUrlQueryAndFragment(event.contexts.trace.data['next.span_name']);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
setUrlProcessingMetadata.setUrlProcessingMetadata(event);
|
|
});
|
|
|
|
client?.on('spanEnd', span => {
|
|
if (span === core.getRootSpan(span)) {
|
|
responseEnd.waitUntil(responseEnd.flushSafelyWithTimeout());
|
|
}
|
|
});
|
|
|
|
core.getGlobalScope().addEventProcessor(
|
|
Object.assign(
|
|
(event => {
|
|
// Filter transactions that we explicitly want to drop.
|
|
if (event.type === 'transaction') {
|
|
if (event.contexts?.trace?.data?.[spanAttributesWithLogicAttached.TRANSACTION_ATTR_SHOULD_DROP_TRANSACTION]) {
|
|
return null;
|
|
}
|
|
|
|
return event;
|
|
} else {
|
|
return event;
|
|
}
|
|
}) ,
|
|
{ id: 'NextLowQualityTransactionsFilter' },
|
|
),
|
|
);
|
|
|
|
try {
|
|
// @ts-expect-error `process.turbopack` is a magic string that will be replaced by Next.js
|
|
if (process.turbopack) {
|
|
core.getGlobalScope().setTag('turbopack', true);
|
|
}
|
|
} catch {
|
|
// Noop
|
|
// The statement above can throw because process is not defined on the client
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Just a passthrough in case this is imported from the client.
|
|
*/
|
|
function withSentryConfig(exportedUserNextConfig) {
|
|
return exportedUserNextConfig;
|
|
}
|
|
|
|
exports.wrapGetStaticPropsWithSentry = wrapGetStaticPropsWithSentry.wrapGetStaticPropsWithSentry;
|
|
exports.wrapGetInitialPropsWithSentry = wrapGetInitialPropsWithSentry.wrapGetInitialPropsWithSentry;
|
|
exports.wrapAppGetInitialPropsWithSentry = wrapAppGetInitialPropsWithSentry.wrapAppGetInitialPropsWithSentry;
|
|
exports.wrapDocumentGetInitialPropsWithSentry = wrapDocumentGetInitialPropsWithSentry.wrapDocumentGetInitialPropsWithSentry;
|
|
exports.wrapErrorGetInitialPropsWithSentry = wrapErrorGetInitialPropsWithSentry.wrapErrorGetInitialPropsWithSentry;
|
|
exports.wrapGetServerSidePropsWithSentry = wrapGetServerSidePropsWithSentry.wrapGetServerSidePropsWithSentry;
|
|
exports.wrapServerComponentWithSentry = wrapServerComponentWithSentry.wrapServerComponentWithSentry;
|
|
exports.wrapRouteHandlerWithSentry = wrapRouteHandlerWithSentry.wrapRouteHandlerWithSentry;
|
|
exports.wrapApiHandlerWithSentryVercelCrons = wrapApiHandlerWithSentryVercelCrons.wrapApiHandlerWithSentryVercelCrons;
|
|
exports.wrapMiddlewareWithSentry = wrapMiddlewareWithSentry.wrapMiddlewareWithSentry;
|
|
exports.wrapPageComponentWithSentry = wrapPageComponentWithSentry.wrapPageComponentWithSentry;
|
|
exports.wrapGenerationFunctionWithSentry = wrapGenerationFunctionWithSentry.wrapGenerationFunctionWithSentry;
|
|
exports.withServerActionInstrumentation = withServerActionInstrumentation.withServerActionInstrumentation;
|
|
exports.captureRequestError = captureRequestError.captureRequestError;
|
|
exports.captureUnderscoreErrorException = _error.captureUnderscoreErrorException;
|
|
exports.startInactiveSpan = nextSpan.startInactiveSpan;
|
|
exports.startSpan = nextSpan.startSpan;
|
|
exports.startSpanManual = nextSpan.startSpanManual;
|
|
exports.wrapApiHandlerWithSentry = wrapApiHandlerWithSentry.wrapApiHandlerWithSentry;
|
|
exports.init = init;
|
|
exports.withSentryConfig = withSentryConfig;
|
|
Object.prototype.hasOwnProperty.call(vercelEdge, '__proto__') &&
|
|
!Object.prototype.hasOwnProperty.call(exports, '__proto__') &&
|
|
Object.defineProperty(exports, '__proto__', {
|
|
enumerable: true,
|
|
value: vercelEdge['__proto__']
|
|
});
|
|
|
|
Object.keys(vercelEdge).forEach(k => {
|
|
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) exports[k] = vercelEdge[k];
|
|
});
|
|
//# sourceMappingURL=index.js.map
|