Object.defineProperty(exports, '__esModule', { value: true }); const react = require('@sentry/react'); const utils = require('@sentry/utils'); const DEFAULT_TAGS = { 'routing.instrumentation': 'next-app-router', } ; /** * Instruments the Next.js Client App Router. */ // TODO(v8): Clean this function up by splitting into pageload and navigation instrumentation respectively. Also remove startTransactionCb in the process. function appRouterInstrumentation( startTransactionCb, startTransactionOnPageLoad = true, startTransactionOnLocationChange = true, startPageloadSpanCallback, startNavigationSpanCallback, ) { // We keep track of the active transaction so we can finish it when we start a navigation transaction. let activeTransaction = undefined; // We keep track of the previous location name so we can set the `from` field on navigation transactions. // This is either a route or a pathname. let prevLocationName = react.WINDOW.location.pathname; if (startTransactionOnPageLoad) { const transactionContext = { name: prevLocationName, op: 'pageload', origin: 'auto.pageload.nextjs.app_router_instrumentation', tags: DEFAULT_TAGS, // pageload should always start at timeOrigin (and needs to be in s, not ms) startTimestamp: utils.browserPerformanceTimeOrigin ? utils.browserPerformanceTimeOrigin / 1000 : undefined, metadata: { source: 'url' }, } ; activeTransaction = startTransactionCb(transactionContext); startPageloadSpanCallback(transactionContext); } if (startTransactionOnLocationChange) { utils.addFetchInstrumentationHandler(handlerData => { // The instrumentation handler is invoked twice - once for starting a request and once when the req finishes // We can use the existence of the end-timestamp to filter out "finishing"-events. if (handlerData.endTimestamp !== undefined) { return; } // Only GET requests can be navigating RSC requests if (handlerData.fetchData.method !== 'GET') { return; } const parsedNavigatingRscFetchArgs = parseNavigatingRscFetchArgs(handlerData.args); if (parsedNavigatingRscFetchArgs === null) { return; } const transactionName = parsedNavigatingRscFetchArgs.targetPathname; const tags = { ...DEFAULT_TAGS, from: prevLocationName, }; prevLocationName = transactionName; if (activeTransaction) { activeTransaction.end(); } const transactionContext = { name: transactionName, op: 'navigation', origin: 'auto.navigation.nextjs.app_router_instrumentation', tags, metadata: { source: 'url' }, } ; startTransactionCb(transactionContext); startNavigationSpanCallback(transactionContext); }); } } function parseNavigatingRscFetchArgs(fetchArgs) { // Make sure the first arg is a URL object if (!fetchArgs[0] || typeof fetchArgs[0] !== 'object' || (fetchArgs[0] ).searchParams === undefined) { return null; } // Make sure the second argument is some kind of fetch config obj that contains headers if (!fetchArgs[1] || typeof fetchArgs[1] !== 'object' || !('headers' in fetchArgs[1])) { return null; } try { const url = fetchArgs[0] ; const headers = fetchArgs[1].headers ; // Not an RSC request if (headers['RSC'] !== '1') { return null; } // Prefetch requests are not navigating RSC requests if (headers['Next-Router-Prefetch'] === '1') { return null; } return { targetPathname: url.pathname, }; } catch (e) { return null; } } exports.appRouterInstrumentation = appRouterInstrumentation; //# sourceMappingURL=appRouterRoutingInstrumentation.js.map