diff --git a/dev-packages/e2e-tests/test-applications/node-nestjs/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/node-nestjs/tests/transactions.test.ts index 2739dbe20b07..9268e777b502 100644 --- a/dev-packages/e2e-tests/test-applications/node-nestjs/tests/transactions.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-nestjs/tests/transactions.test.ts @@ -107,7 +107,8 @@ test('Sends an API route transaction', async ({ baseURL }) => { span_id: expect.any(String), trace_id: expect.any(String), data: { - 'sentry.origin': 'manual', + 'sentry.origin': 'auto.http.otel.nestjs', + 'sentry.op': 'handler.nestjs', component: '@nestjs/core', 'nestjs.version': expect.any(String), 'nestjs.type': 'handler', @@ -119,7 +120,8 @@ test('Sends an API route transaction', async ({ baseURL }) => { start_timestamp: expect.any(Number), timestamp: expect.any(Number), status: 'ok', - origin: 'manual', + origin: 'auto.http.otel.nestjs', + op: 'handler.nestjs', }, ]), transaction: 'GET /test-transaction', diff --git a/packages/node/src/integrations/tracing/connect.ts b/packages/node/src/integrations/tracing/connect.ts index 7dfecef3a482..60bb9d74448a 100644 --- a/packages/node/src/integrations/tracing/connect.ts +++ b/packages/node/src/integrations/tracing/connect.ts @@ -40,7 +40,7 @@ export const setupConnectErrorHandler = (app: ConnectApp): void => { // Sadly, ConnectInstrumentation has no requestHook, so we need to add the attributes here // We register this hook in this method, because if we register it in the integration `setup`, - // it would always run even for users that are not even using fastify + // it would always run even for users that are not even using connect const client = getClient(); if (client) { client.on('spanStart', span => { diff --git a/packages/node/src/integrations/tracing/nest.ts b/packages/node/src/integrations/tracing/nest.ts index c1a4b9e7a3c0..cc66e745da1d 100644 --- a/packages/node/src/integrations/tracing/nest.ts +++ b/packages/node/src/integrations/tracing/nest.ts @@ -1,7 +1,16 @@ import { NestInstrumentation } from '@opentelemetry/instrumentation-nestjs-core'; -import { captureException, defineIntegration, getDefaultIsolationScope, getIsolationScope } from '@sentry/core'; +import { + SEMANTIC_ATTRIBUTE_SENTRY_OP, + SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, + captureException, + defineIntegration, + getClient, + getDefaultIsolationScope, + getIsolationScope, + spanToJSON, +} from '@sentry/core'; import { addOpenTelemetryInstrumentation } from '@sentry/opentelemetry'; -import type { IntegrationFn } from '@sentry/types'; +import type { IntegrationFn, Span } from '@sentry/types'; import { logger } from '@sentry/utils'; interface MinimalNestJsExecutionContext { @@ -52,6 +61,16 @@ export const nestIntegration = defineIntegration(_nestIntegration); * Setup an error handler for Nest. */ export function setupNestErrorHandler(app: MinimalNestJsApp, baseFilter: NestJsErrorFilter): void { + // Sadly, NestInstrumentation has no requestHook, so we need to add the attributes here + // We register this hook in this method, because if we register it in the integration `setup`, + // it would always run even for users that are not even using Nest.js + const client = getClient(); + if (client) { + client.on('spanStart', span => { + addNestSpanAttributes(span); + }); + } + app.useGlobalInterceptors({ intercept(context, next) { if (getIsolationScope() === getDefaultIsolationScope()) { @@ -86,3 +105,20 @@ export function setupNestErrorHandler(app: MinimalNestJsApp, baseFilter: NestJsE app.useGlobalFilters(wrappedFilter); } + +function addNestSpanAttributes(span: Span): void { + const attributes = spanToJSON(span).data || {}; + + // this is one of: app_creation, request_context, handler + const type = attributes['nestjs.type']; + + // If this is already set, or we have no nest.js span, no need to process again... + if (attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] || !type) { + return; + } + + span.setAttributes({ + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.otel.nestjs', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: `${type}.nestjs`, + }); +}