diff --git a/dev-packages/e2e-tests/test-applications/nextjs-14/tests/generation-functions.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-14/tests/generation-functions.test.ts index 303582ec1b24..bf3eca58a307 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-14/tests/generation-functions.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-14/tests/generation-functions.test.ts @@ -17,7 +17,7 @@ test('Should emit a span for a generateMetadata() function invokation', async ({ expect(transaction.spans).toContainEqual( expect.objectContaining({ description: 'generateMetadata /generation-functions/page', - origin: 'manual', + origin: 'auto', parent_span_id: expect.any(String), span_id: expect.any(String), status: 'ok', @@ -74,7 +74,7 @@ test('Should send a transaction event for a generateViewport() function invokati expect((await transactionPromise).spans).toContainEqual( expect.objectContaining({ description: 'generateViewport /generation-functions/page', - origin: 'manual', + origin: 'auto', parent_span_id: expect.any(String), span_id: expect.any(String), status: 'ok', diff --git a/packages/nextjs/src/server/index.ts b/packages/nextjs/src/server/index.ts index 96c97371df24..e787f978cf22 100644 --- a/packages/nextjs/src/server/index.ts +++ b/packages/nextjs/src/server/index.ts @@ -1,4 +1,5 @@ import { + SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, applySdkMetadata, getClient, @@ -189,6 +190,7 @@ export function init(options: NodeOptions): NodeClient | undefined { // with patterns (e.g. http.server spans) that will produce confusing data. if (spanAttributes?.['next.span_type'] !== undefined) { span.setAttribute('sentry.skip_span_data_inference', true); + span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto'); } // We want to rename these spans because they look like "GET /path/to/route" and we already emit spans that look @@ -286,6 +288,28 @@ export function init(options: NodeOptions): NodeClient | undefined { ), ); + getGlobalScope().addEventProcessor( + Object.assign( + (event => { + // Sometimes, the HTTP integration will not work, causing us not to properly set an op for spans generated by + // Next.js that are actually more or less correct server HTTP spans, so we are backfilling the op here. + if ( + event.type === 'transaction' && + event.transaction?.match(/^(RSC )?GET /) && + event.contexts?.trace?.data?.['sentry.rsc'] === true && + !event.contexts.trace.op + ) { + event.contexts.trace.data = event.contexts.trace.data || {}; + event.contexts.trace.data[SEMANTIC_ATTRIBUTE_SENTRY_OP] = 'http.server'; + event.contexts.trace.op = 'http.server'; + } + + return event; + }) satisfies EventProcessor, + { id: 'NextjsTransactionEnhancer' }, + ), + ); + if (process.env.NODE_ENV === 'development') { getGlobalScope().addEventProcessor(devErrorSymbolicationEventProcessor); } diff --git a/packages/opentelemetry/src/spanExporter.ts b/packages/opentelemetry/src/spanExporter.ts index d00319ec2c98..18c935863b75 100644 --- a/packages/opentelemetry/src/spanExporter.ts +++ b/packages/opentelemetry/src/spanExporter.ts @@ -345,6 +345,7 @@ function removeSentryAttributes(data: Record): Record