diff --git a/packages/nextjs/package.json b/packages/nextjs/package.json index 109bc5c70f49..33e00d4353fd 100644 --- a/packages/nextjs/package.json +++ b/packages/nextjs/package.json @@ -77,7 +77,6 @@ }, "dependencies": { "@opentelemetry/api": "^1.9.1", - "@opentelemetry/semantic-conventions": "^1.40.0", "@rollup/plugin-commonjs": "28.0.1", "@sentry/browser-utils": "10.57.0", "@sentry/bundler-plugin-core": "^5.3.0", @@ -91,6 +90,7 @@ "stacktrace-parser": "^0.1.11" }, "devDependencies": { + "@sentry/conventions": "^0.11.0", "eslint-plugin-react": "^7.31.11", "next": "14.2.35", "react": "^18.3.1", diff --git a/packages/nextjs/rollup.npm.config.mjs b/packages/nextjs/rollup.npm.config.mjs index 89271a21e9d3..2007b831ae10 100644 --- a/packages/nextjs/rollup.npm.config.mjs +++ b/packages/nextjs/rollup.npm.config.mjs @@ -19,6 +19,12 @@ export default [ packageSpecificConfig: { external: ['next/router', 'next/constants', 'next/headers', 'stacktrace-parser'], + output: { + // keep emitted module paths relative to `src` so the bundled `@sentry/conventions` + // (a devDependency, vendored into the build) doesn't shift the output layout + preserveModulesRoot: 'src', + }, + // Next.js and our users are more happy when our client code has the "use client" directive plugins: [ { diff --git a/packages/nextjs/src/common/utils/dropMiddlewareTunnelRequests.ts b/packages/nextjs/src/common/utils/dropMiddlewareTunnelRequests.ts index fbbe8f704fbe..08bdfeded1fd 100644 --- a/packages/nextjs/src/common/utils/dropMiddlewareTunnelRequests.ts +++ b/packages/nextjs/src/common/utils/dropMiddlewareTunnelRequests.ts @@ -1,4 +1,4 @@ -import { SEMATTRS_HTTP_TARGET } from '@opentelemetry/semantic-conventions'; +import { HTTP_TARGET } from '@sentry/conventions/attributes'; import { getClient, GLOBAL_OBJ, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, type Span, type SpanAttributes } from '@sentry/core'; import { isSentryRequestSpan } from '@sentry/opentelemetry'; import { ATTR_NEXT_SPAN_TYPE } from '../nextSpanAttributes'; @@ -53,8 +53,7 @@ function isTunnelRouteSpan(spanAttributes: Record): boolean { return false; } - // eslint-disable-next-line deprecation/deprecation - const httpTarget = spanAttributes[SEMATTRS_HTTP_TARGET]; + const httpTarget = spanAttributes[HTTP_TARGET]; if (typeof httpTarget === 'string') { // Extract pathname from the target (e.g., "/tunnel?o=123&p=456" -> "/tunnel") diff --git a/packages/nextjs/src/common/utils/tracingUtils.ts b/packages/nextjs/src/common/utils/tracingUtils.ts index ce6bab7946e1..6039f0eff50b 100644 --- a/packages/nextjs/src/common/utils/tracingUtils.ts +++ b/packages/nextjs/src/common/utils/tracingUtils.ts @@ -1,4 +1,4 @@ -import { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions'; +import { HTTP_ROUTE } from '@sentry/conventions/attributes'; import type { PropagationContext, Span, SpanAttributes } from '@sentry/core'; import { debug, @@ -177,7 +177,7 @@ export function maybeEnhanceServerComponentSpanName( } const segment = spanAttributes[ATTR_NEXT_SEGMENT] as string; - const route = rootSpanAttributes[ATTR_HTTP_ROUTE]; + const route = rootSpanAttributes[HTTP_ROUTE]; const enhancedName = getEnhancedResolveSegmentSpanName({ segment, route: typeof route === 'string' ? route : '' }); activeSpan.updateName(enhancedName); activeSpan.setAttributes({ diff --git a/packages/nextjs/src/server/enhanceHandleRequestRootSpan.ts b/packages/nextjs/src/server/enhanceHandleRequestRootSpan.ts index a934380492dc..11af0ee73a61 100644 --- a/packages/nextjs/src/server/enhanceHandleRequestRootSpan.ts +++ b/packages/nextjs/src/server/enhanceHandleRequestRootSpan.ts @@ -1,9 +1,4 @@ -import { - ATTR_HTTP_REQUEST_METHOD, - ATTR_HTTP_ROUTE, - SEMATTRS_HTTP_METHOD, - SEMATTRS_HTTP_TARGET, -} from '@opentelemetry/semantic-conventions'; +import { HTTP_METHOD, HTTP_REQUEST_METHOD, HTTP_ROUTE, HTTP_TARGET } from '@sentry/conventions/attributes'; import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, stripUrlQueryAndFragment } from '@sentry/core'; import { ATTR_NEXT_ROUTE, ATTR_NEXT_SPAN_NAME, ATTR_NEXT_SPAN_TYPE } from '../common/nextSpanAttributes'; import { TRANSACTION_ATTR_SENTRY_ROUTE_BACKFILL } from '../common/span-attributes-with-logic-attached'; @@ -41,11 +36,9 @@ export function enhanceHandleRequestRootSpan(span: MutableRootSpan): void { span.setName(stripUrlQueryAndFragment(currentName)); } - // eslint-disable-next-line deprecation/deprecation - const method = attributes[SEMATTRS_HTTP_METHOD] ?? attributes[ATTR_HTTP_REQUEST_METHOD]; - // eslint-disable-next-line deprecation/deprecation - const target = attributes[SEMATTRS_HTTP_TARGET]; - const route = attributes[ATTR_HTTP_ROUTE] || attributes[ATTR_NEXT_ROUTE]; + const method = attributes[HTTP_METHOD] ?? attributes[HTTP_REQUEST_METHOD]; + const target = attributes[HTTP_TARGET]; + const route = attributes[HTTP_ROUTE] || attributes[ATTR_NEXT_ROUTE]; const spanName = attributes[ATTR_NEXT_SPAN_NAME]; if (typeof method === 'string' && typeof route === 'string' && !route.startsWith('middleware')) { diff --git a/packages/nextjs/src/server/handleOnSpanStart.ts b/packages/nextjs/src/server/handleOnSpanStart.ts index 21af973f2b2f..b852ed729e04 100644 --- a/packages/nextjs/src/server/handleOnSpanStart.ts +++ b/packages/nextjs/src/server/handleOnSpanStart.ts @@ -1,5 +1,5 @@ import { context } from '@opentelemetry/api'; -import { ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_ROUTE, SEMATTRS_HTTP_METHOD } from '@opentelemetry/semantic-conventions'; +import { HTTP_METHOD, HTTP_REQUEST_METHOD, HTTP_ROUTE } from '@sentry/conventions/attributes'; import type { Span } from '@sentry/core'; import { getCapturedScopesOnSpan, @@ -37,20 +37,18 @@ export function handleOnSpanStart(span: Span): void { if (typeof spanAttributes?.[ATTR_NEXT_ROUTE] === 'string') { // Only hoist the http.route attribute if the transaction doesn't already have it if ( - // eslint-disable-next-line deprecation/deprecation - (rootSpanAttributes?.[ATTR_HTTP_REQUEST_METHOD] || rootSpanAttributes?.[SEMATTRS_HTTP_METHOD]) && - !rootSpanAttributes?.[ATTR_HTTP_ROUTE] + (rootSpanAttributes?.[HTTP_REQUEST_METHOD] || rootSpanAttributes?.[HTTP_METHOD]) && + !rootSpanAttributes?.[HTTP_ROUTE] ) { const route = spanAttributes[ATTR_NEXT_ROUTE].replace(/\/route$/, ''); rootSpan.updateName(route); - rootSpan.setAttribute(ATTR_HTTP_ROUTE, route); + rootSpan.setAttribute(HTTP_ROUTE, route); // Preserving the original attribute despite internally not depending on it rootSpan.setAttribute(ATTR_NEXT_ROUTE, route); // Update the isolation scope's transaction name so that non-transaction events // (e.g. captureMessage, captureException) also get the parameterized route. - // eslint-disable-next-line deprecation/deprecation - const method = rootSpanAttributes?.[ATTR_HTTP_REQUEST_METHOD] || rootSpanAttributes?.[SEMATTRS_HTTP_METHOD]; + const method = rootSpanAttributes?.[HTTP_REQUEST_METHOD] || rootSpanAttributes?.[HTTP_METHOD]; if (typeof method === 'string') { getIsolationScope().setTransactionName(`${method} ${route}`); } @@ -67,7 +65,7 @@ export function handleOnSpanStart(span: Span): void { const middlewareName = spanAttributes[ATTR_NEXT_SPAN_NAME]; if (typeof middlewareName === 'string') { rootSpan.updateName(middlewareName); - rootSpan.setAttribute(ATTR_HTTP_ROUTE, middlewareName); + rootSpan.setAttribute(HTTP_ROUTE, middlewareName); rootSpan.setAttribute(ATTR_NEXT_SPAN_NAME, middlewareName); } span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto'); diff --git a/packages/nextjs/src/server/index.ts b/packages/nextjs/src/server/index.ts index b22ba38ecd83..cf5de6760a47 100644 --- a/packages/nextjs/src/server/index.ts +++ b/packages/nextjs/src/server/index.ts @@ -1,7 +1,7 @@ // 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 */ -import { ATTR_URL_QUERY, SEMATTRS_HTTP_TARGET } from '@opentelemetry/semantic-conventions'; +import { HTTP_TARGET, URL_QUERY } from '@sentry/conventions/attributes'; import type { EventProcessor } from '@sentry/core'; import { applySdkMetadata, @@ -185,15 +185,12 @@ export function init(options: NodeOptions): NodeClient | undefined { // because we didn't get the chance to do `suppressTracing`, since this happens outside of userland. // We need to drop these spans. if ( - // eslint-disable-next-line deprecation/deprecation - (typeof spanAttributes[SEMATTRS_HTTP_TARGET] === 'string' && - // eslint-disable-next-line deprecation/deprecation - spanAttributes[SEMATTRS_HTTP_TARGET].includes('sentry_key') && - // eslint-disable-next-line deprecation/deprecation - spanAttributes[SEMATTRS_HTTP_TARGET].includes('sentry_client')) || - (typeof spanAttributes[ATTR_URL_QUERY] === 'string' && - spanAttributes[ATTR_URL_QUERY].includes('sentry_key') && - spanAttributes[ATTR_URL_QUERY].includes('sentry_client')) + (typeof spanAttributes[HTTP_TARGET] === 'string' && + spanAttributes[HTTP_TARGET].includes('sentry_key') && + spanAttributes[HTTP_TARGET].includes('sentry_client')) || + (typeof spanAttributes[URL_QUERY] === 'string' && + spanAttributes[URL_QUERY].includes('sentry_key') && + spanAttributes[URL_QUERY].includes('sentry_client')) ) { samplingDecision.decision = false; } diff --git a/yarn.lock b/yarn.lock index 5f7a5fcbdbbc..29f88030819f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7578,6 +7578,11 @@ "@sentry/cli-win32-i686" "2.58.6" "@sentry/cli-win32-x64" "2.58.6" +"@sentry/conventions@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@sentry/conventions/-/conventions-0.11.0.tgz#5a324b8368dc5c141260bd8ccc684756ea3dd843" + integrity sha512-AQTAKeq9mDpOElDFSPymZTPZF/c50rk355mWTf5Y1ZxZJKKOBli5qTttskJyCxrE5ynNgN1KwcXoU5MRrMSRmQ== + "@sentry/node-cpu-profiler@^2.4.2": version "2.4.2" resolved "https://registry.yarnpkg.com/@sentry/node-cpu-profiler/-/node-cpu-profiler-2.4.2.tgz#d0ba01370545297d015df1497daf7f81e27f2ab5"