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
1 line
13 KiB
Plaintext
1 line
13 KiB
Plaintext
{"version":3,"file":"pagesRouterRoutingInstrumentation.js","sources":["../../../../src/client/routing/pagesRouterRoutingInstrumentation.ts"],"sourcesContent":["import type { Client, TransactionSource } from '@sentry/core';\nimport {\n browserPerformanceTimeOrigin,\n debug,\n parseBaggageHeader,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n stripUrlQueryAndFragment,\n} from '@sentry/core';\nimport { startBrowserTracingNavigationSpan, startBrowserTracingPageLoadSpan, WINDOW } from '@sentry/react';\nimport type { NEXT_DATA } from 'next/dist/shared/lib/utils';\nimport RouterImport from 'next/router';\nimport type { ParsedUrlQuery } from 'querystring';\nimport { DEBUG_BUILD } from '../../common/debug-build';\n\n// next/router v10 is CJS\n//\n// For ESM/CJS interoperability 'reasons', depending on how this file is loaded, Router might be on the default export\nconst Router: typeof RouterImport = RouterImport.events\n ? RouterImport\n : (RouterImport as unknown as { default: typeof RouterImport }).default;\n\nconst globalObject = WINDOW as typeof WINDOW & {\n __BUILD_MANIFEST?: {\n sortedPages?: string[];\n };\n};\n\n/**\n * Describes data located in the __NEXT_DATA__ script tag. This tag is present on every page of a Next.js app.\n */\ninterface SentryEnhancedNextData extends NEXT_DATA {\n props: {\n pageProps?: {\n _sentryTraceData?: string; // trace parent info, if injected by a data-fetcher\n _sentryBaggage?: string; // baggage, if injected by a data-fetcher\n // These two values are only injected by `getStaticProps` in a very special case with the following conditions:\n // 1. The page's `getStaticPaths` method must have returned `fallback: 'blocking'`.\n // 2. The requested page must be a \"miss\" in terms of \"Incremental Static Regeneration\", meaning the requested page has not been generated before.\n // In this case, a page is requested and only served when `getStaticProps` is done. There is not even a fallback page or similar.\n };\n };\n}\n\ninterface NextDataTagInfo {\n route?: string;\n params?: ParsedUrlQuery;\n sentryTrace?: string;\n baggage?: string;\n}\n\n/**\n * Every Next.js page (static and dynamic ones) comes with a script tag with the id \"__NEXT_DATA__\". This script tag\n * contains a JSON object with data that was either generated at build time for static pages (`getStaticProps`), or at\n * runtime with data fetchers like `getServerSideProps.`.\n *\n * We can use this information to:\n * - Always get the parameterized route we're in when loading a page.\n * - Send trace information (trace-id, baggage) from the server to the client.\n *\n * This function extracts this information.\n */\nfunction extractNextDataTagInformation(): NextDataTagInfo {\n let nextData: SentryEnhancedNextData | undefined;\n // Let's be on the safe side and actually check first if there is really a __NEXT_DATA__ script tag on the page.\n // Theoretically this should always be the case though.\n const nextDataTag = globalObject.document.getElementById('__NEXT_DATA__');\n if (nextDataTag?.innerHTML) {\n try {\n nextData = JSON.parse(nextDataTag.innerHTML);\n } catch {\n DEBUG_BUILD && debug.warn('Could not extract __NEXT_DATA__');\n }\n }\n\n if (!nextData) {\n return {};\n }\n\n const nextDataTagInfo: NextDataTagInfo = {};\n\n const { page, query, props } = nextData;\n\n // `nextData.page` always contains the parameterized route - except for when an error occurs in a data fetching\n // function, then it is \"/_error\", but that isn't a problem since users know which route threw by looking at the\n // parent transaction\n // TODO: Actually this is a problem (even though it is not that big), because the DSC and the transaction payload will contain\n // a different transaction name. Maybe we can fix this. Idea: Also send transaction name via pageProps when available.\n nextDataTagInfo.route = page;\n nextDataTagInfo.params = query;\n\n if (props?.pageProps) {\n nextDataTagInfo.sentryTrace = props.pageProps._sentryTraceData;\n nextDataTagInfo.baggage = props.pageProps._sentryBaggage;\n }\n\n return nextDataTagInfo;\n}\n\n/**\n * Instruments the Next.js pages router for pageloads.\n * Only supported for client side routing. Works for Next >= 10.\n *\n * Leverages the SingletonRouter from the `next/router` to\n * generate pageload/navigation transactions and parameterize\n * transaction names.\n */\nexport function pagesRouterInstrumentPageLoad(client: Client): void {\n const { route, params, sentryTrace, baggage } = extractNextDataTagInformation();\n const parsedBaggage = parseBaggageHeader(baggage);\n let name = route || globalObject.location.pathname;\n\n // /_error is the fallback page for all errors. If there is a transaction name for /_error, use that instead\n if (parsedBaggage?.['sentry-transaction'] && name === '/_error') {\n name = parsedBaggage['sentry-transaction'];\n // Strip any HTTP method from the span name\n name = name.replace(/^(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS|TRACE|CONNECT)\\s+/i, '');\n }\n\n const origin = browserPerformanceTimeOrigin();\n startBrowserTracingPageLoadSpan(\n client,\n {\n name,\n // pageload should always start at timeOrigin (and needs to be in s, not ms)\n startTime: origin ? origin / 1000 : undefined,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'pageload',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.pageload.nextjs.pages_router_instrumentation',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: route ? 'route' : 'url',\n ...(params && client.getOptions().sendDefaultPii && { ...params }),\n },\n },\n { sentryTrace, baggage },\n );\n}\n\n/**\n * Instruments the Next.js pages router for navigation.\n * Only supported for client side routing. Works for Next >= 10.\n *\n * Leverages the SingletonRouter from the `next/router` to\n * generate pageload/navigation transactions and parameterize\n * transaction names.\n */\nexport function pagesRouterInstrumentNavigation(client: Client): void {\n Router.events.on('routeChangeStart', (navigationTarget: string) => {\n const strippedNavigationTarget = stripUrlQueryAndFragment(navigationTarget);\n const matchedRoute = getNextRouteFromPathname(strippedNavigationTarget);\n\n let newLocation: string;\n let spanSource: TransactionSource;\n\n if (matchedRoute) {\n newLocation = matchedRoute;\n spanSource = 'route';\n } else {\n newLocation = strippedNavigationTarget;\n spanSource = 'url';\n }\n\n startBrowserTracingNavigationSpan(client, {\n name: newLocation,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.nextjs.pages_router_instrumentation',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: spanSource,\n },\n });\n });\n}\n\nfunction getNextRouteFromPathname(pathname: string): string | undefined {\n const pageRoutes = globalObject.__BUILD_MANIFEST?.sortedPages;\n\n // Page route should in 99.999% of the cases be defined by now but just to be sure we make a check here\n if (!pageRoutes) {\n return;\n }\n\n return pageRoutes.find(route => {\n const routeRegExp = convertNextRouteToRegExp(route);\n return pathname.match(routeRegExp);\n });\n}\n\n/**\n * Converts a Next.js style route to a regular expression that matches on pathnames (no query params or URL fragments).\n *\n * In general this involves replacing any instances of square brackets in a route with a wildcard:\n * e.g. \"/users/[id]/info\" becomes /\\/users\\/([^/]+?)\\/info/\n *\n * Some additional edgecases need to be considered:\n * - All routes have an optional slash at the end, meaning users can navigate to \"/users/[id]/info\" or\n * \"/users/[id]/info/\" - both will be resolved to \"/users/[id]/info\".\n * - Non-optional \"catchall\"s at the end of a route must be considered when matching (e.g. \"/users/[...params]\").\n * - Optional \"catchall\"s at the end of a route must be considered when matching (e.g. \"/users/[[...params]]\").\n *\n * @param route A Next.js style route as it is found in `global.__BUILD_MANIFEST.sortedPages`\n */\nfunction convertNextRouteToRegExp(route: string): RegExp {\n // We can assume a route is at least \"/\".\n const routeParts = route.split('/');\n\n let optionalCatchallWildcardRegex = '';\n if (routeParts[routeParts.length - 1]?.match(/^\\[\\[\\.\\.\\..+\\]\\]$/)) {\n // If last route part has pattern \"[[...xyz]]\" we pop the latest route part to get rid of the required trailing\n // slash that would come before it if we didn't pop it.\n routeParts.pop();\n optionalCatchallWildcardRegex = '(?:/(.+?))?';\n }\n\n const rejoinedRouteParts = routeParts\n .map(\n routePart =>\n routePart\n .replace(/^\\[\\.\\.\\..+\\]$/, '(.+?)') // Replace catch all wildcard with regex wildcard\n .replace(/^\\[.*\\]$/, '([^/]+?)'), // Replace route wildcards with lazy regex wildcards\n )\n .join('/');\n\n // eslint-disable-next-line @sentry-internal/sdk/no-regexp-constructor -- routeParts are from the build manifest, so no raw user input\n return new RegExp(\n `^${rejoinedRouteParts}${optionalCatchallWildcardRegex}(?:/)?$`, // optional slash at the end\n );\n}\n"],"names":["RouterImport","WINDOW","DEBUG_BUILD","debug","parseBaggageHeader","browserPerformanceTimeOrigin","startBrowserTracingPageLoadSpan","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","stripUrlQueryAndFragment","startBrowserTracingNavigationSpan"],"mappings":"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"} |