From d16e850b0392f9c811ea9eaa901d8196a1bb37e5 Mon Sep 17 00:00:00 2001 From: nicohrubec Date: Fri, 2 Aug 2024 12:27:55 +0200 Subject: [PATCH 1/5] Move nest integration to folder --- packages/node/src/index.ts | 2 +- packages/node/src/integrations/tracing/index.ts | 2 +- packages/node/src/integrations/tracing/{ => nest}/nest.ts | 2 +- packages/node/test/integrations/tracing/nest.test.ts | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) rename packages/node/src/integrations/tracing/{ => nest}/nest.ts (99%) diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index 85d001b465e5..ccbce0eefb4f 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -18,7 +18,7 @@ export { mongooseIntegration } from './integrations/tracing/mongoose'; export { mysqlIntegration } from './integrations/tracing/mysql'; export { mysql2Integration } from './integrations/tracing/mysql2'; export { redisIntegration } from './integrations/tracing/redis'; -export { nestIntegration, setupNestErrorHandler } from './integrations/tracing/nest'; +export { nestIntegration, setupNestErrorHandler } from './integrations/tracing/nest/nest'; export { postgresIntegration } from './integrations/tracing/postgres'; export { prismaIntegration } from './integrations/tracing/prisma'; export { hapiIntegration, setupHapiErrorHandler } from './integrations/tracing/hapi'; diff --git a/packages/node/src/integrations/tracing/index.ts b/packages/node/src/integrations/tracing/index.ts index bee4f06db8f5..886c11683674 100644 --- a/packages/node/src/integrations/tracing/index.ts +++ b/packages/node/src/integrations/tracing/index.ts @@ -11,7 +11,7 @@ import { instrumentMongo, mongoIntegration } from './mongo'; import { instrumentMongoose, mongooseIntegration } from './mongoose'; import { instrumentMysql, mysqlIntegration } from './mysql'; import { instrumentMysql2, mysql2Integration } from './mysql2'; -import { instrumentNest, nestIntegration } from './nest'; +import { instrumentNest, nestIntegration } from './nest/nest'; import { instrumentPostgres, postgresIntegration } from './postgres'; import { instrumentRedis, redisIntegration } from './redis'; diff --git a/packages/node/src/integrations/tracing/nest.ts b/packages/node/src/integrations/tracing/nest/nest.ts similarity index 99% rename from packages/node/src/integrations/tracing/nest.ts rename to packages/node/src/integrations/tracing/nest/nest.ts index b3d1b3547118..ef9589344608 100644 --- a/packages/node/src/integrations/tracing/nest.ts +++ b/packages/node/src/integrations/tracing/nest/nest.ts @@ -23,7 +23,7 @@ import { } from '@sentry/core'; import type { IntegrationFn, Span } from '@sentry/types'; import { addNonEnumerableProperty, logger } from '@sentry/utils'; -import { generateInstrumentOnce } from '../../otel/instrument'; +import { generateInstrumentOnce } from '../../../otel/instrument'; interface MinimalNestJsExecutionContext { getType: () => string; diff --git a/packages/node/test/integrations/tracing/nest.test.ts b/packages/node/test/integrations/tracing/nest.test.ts index 3dc321f28008..5db605e16e3f 100644 --- a/packages/node/test/integrations/tracing/nest.test.ts +++ b/packages/node/test/integrations/tracing/nest.test.ts @@ -1,5 +1,5 @@ -import type { InjectableTarget } from '../../../src/integrations/tracing/nest'; -import { isPatched } from '../../../src/integrations/tracing/nest'; +import type { InjectableTarget } from '../../../src/integrations/tracing/nest/nest'; +import { isPatched } from '../../../src/integrations/tracing/nest/nest'; describe('Nest', () => { describe('isPatched', () => { From 087bfd0b55dbb89a7d79522c52b6f92c498a8189 Mon Sep 17 00:00:00 2001 From: nicohrubec Date: Fri, 2 Aug 2024 12:46:04 +0200 Subject: [PATCH 2/5] Extract types and helpers --- .../src/integrations/tracing/nest/helpers.ts | 34 +++++++ .../src/integrations/tracing/nest/nest.ts | 95 +------------------ .../src/integrations/tracing/nest/types.ts | 57 +++++++++++ .../test/integrations/tracing/nest.test.ts | 4 +- 4 files changed, 96 insertions(+), 94 deletions(-) create mode 100644 packages/node/src/integrations/tracing/nest/helpers.ts create mode 100644 packages/node/src/integrations/tracing/nest/types.ts diff --git a/packages/node/src/integrations/tracing/nest/helpers.ts b/packages/node/src/integrations/tracing/nest/helpers.ts new file mode 100644 index 000000000000..32eb3a0d5a39 --- /dev/null +++ b/packages/node/src/integrations/tracing/nest/helpers.ts @@ -0,0 +1,34 @@ +import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core'; +import { addNonEnumerableProperty } from '@sentry/utils'; +import type { InjectableTarget } from './types'; + +const sentryPatched = 'sentryPatched'; + +/** + * Helper checking if a concrete target class is already patched. + * + * We already guard duplicate patching with isWrapped. However, isWrapped checks whether a file has been patched, whereas we use this check for concrete target classes. + * This check might not be necessary, but better to play it safe. + */ +export function isPatched(target: InjectableTarget): boolean { + if (target.sentryPatched) { + return true; + } + + addNonEnumerableProperty(target, sentryPatched, true); + return false; +} + +/** + * Returns span options for nest middleware spans. + */ +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +export function getMiddlewareSpanOptions(target: InjectableTarget) { + return { + name: target.name, + attributes: { + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'middleware.nestjs', + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.middleware.nestjs', + }, + }; +} diff --git a/packages/node/src/integrations/tracing/nest/nest.ts b/packages/node/src/integrations/tracing/nest/nest.ts index ef9589344608..ab890e742750 100644 --- a/packages/node/src/integrations/tracing/nest/nest.ts +++ b/packages/node/src/integrations/tracing/nest/nest.ts @@ -22,104 +22,15 @@ import { withActiveSpan, } from '@sentry/core'; import type { IntegrationFn, Span } from '@sentry/types'; -import { addNonEnumerableProperty, logger } from '@sentry/utils'; +import { logger } from '@sentry/utils'; import { generateInstrumentOnce } from '../../../otel/instrument'; - -interface MinimalNestJsExecutionContext { - getType: () => string; - - switchToHttp: () => { - // minimal request object - // according to official types, all properties are required but - // let's play it safe and assume they're optional - getRequest: () => { - route?: { - path?: string; - }; - method?: string; - }; - }; -} - -interface NestJsErrorFilter { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - catch(exception: any, host: any): void; -} - -interface MinimalNestJsApp { - useGlobalFilters: (arg0: NestJsErrorFilter) => void; - useGlobalInterceptors: (interceptor: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - intercept: (context: MinimalNestJsExecutionContext, next: { handle: () => any }) => any; - }) => void; -} +import { getMiddlewareSpanOptions, isPatched } from './helpers'; +import type { InjectableTarget, MinimalNestJsApp, NestJsErrorFilter } from './types'; const INTEGRATION_NAME = 'Nest'; const supportedVersions = ['>=8.0.0 <11']; -const sentryPatched = 'sentryPatched'; - -/** - * A minimal interface for an Observable. - */ -export interface Observable { - subscribe(observer: (value: T) => void): void; -} - -/** - * A NestJS call handler. Used in interceptors to start the route execution. - */ -export interface CallHandler { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - handle(...args: any[]): Observable; -} - -/** - * Represents an injectable target class in NestJS. - */ -export interface InjectableTarget { - name: string; - sentryPatched?: boolean; - __SENTRY_INTERNAL__?: boolean; - prototype: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - use?: (req: unknown, res: unknown, next: () => void, ...args: any[]) => void; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - canActivate?: (...args: any[]) => boolean | Promise | Observable; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - transform?: (...args: any[]) => any; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - intercept?: (context: unknown, next: CallHandler, ...args: any[]) => Observable; - }; -} - -/** - * Helper checking if a concrete target class is already patched. - * - * We already guard duplicate patching with isWrapped. However, isWrapped checks whether a file has been patched, whereas we use this check for concrete target classes. - * This check might not be necessary, but better to play it safe. - */ -export function isPatched(target: InjectableTarget): boolean { - if (target.sentryPatched) { - return true; - } - - addNonEnumerableProperty(target, sentryPatched, true); - return false; -} - -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type -function getMiddlewareSpanOptions(target: InjectableTarget) { - return { - name: target.name, - attributes: { - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'middleware.nestjs', - [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.middleware.nestjs', - }, - }; -} - /** * Custom instrumentation for nestjs. * diff --git a/packages/node/src/integrations/tracing/nest/types.ts b/packages/node/src/integrations/tracing/nest/types.ts new file mode 100644 index 000000000000..2cdd1b6aefaf --- /dev/null +++ b/packages/node/src/integrations/tracing/nest/types.ts @@ -0,0 +1,57 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +interface MinimalNestJsExecutionContext { + getType: () => string; + + switchToHttp: () => { + // minimal request object + // according to official types, all properties are required but + // let's play it safe and assume they're optional + getRequest: () => { + route?: { + path?: string; + }; + method?: string; + }; + }; +} + +export interface NestJsErrorFilter { + catch(exception: any, host: any): void; +} + +export interface MinimalNestJsApp { + useGlobalFilters: (arg0: NestJsErrorFilter) => void; + useGlobalInterceptors: (interceptor: { + intercept: (context: MinimalNestJsExecutionContext, next: { handle: () => any }) => any; + }) => void; +} + +/** + * A minimal interface for an Observable. + */ +export interface Observable { + subscribe(observer: (value: T) => void): void; +} + +/** + * A NestJS call handler. Used in interceptors to start the route execution. + */ +export interface CallHandler { + handle(...args: any[]): Observable; +} + +/** + * Represents an injectable target class in NestJS. + */ +export interface InjectableTarget { + name: string; + sentryPatched?: boolean; + __SENTRY_INTERNAL__?: boolean; + prototype: { + use?: (req: unknown, res: unknown, next: () => void, ...args: any[]) => void; + canActivate?: (...args: any[]) => boolean | Promise | Observable; + transform?: (...args: any[]) => any; + intercept?: (context: unknown, next: CallHandler, ...args: any[]) => Observable; + }; +} diff --git a/packages/node/test/integrations/tracing/nest.test.ts b/packages/node/test/integrations/tracing/nest.test.ts index 5db605e16e3f..3837e3e4ee3d 100644 --- a/packages/node/test/integrations/tracing/nest.test.ts +++ b/packages/node/test/integrations/tracing/nest.test.ts @@ -1,5 +1,5 @@ -import type { InjectableTarget } from '../../../src/integrations/tracing/nest/nest'; -import { isPatched } from '../../../src/integrations/tracing/nest/nest'; +import { isPatched } from '../../../src/integrations/tracing/nest/helpers'; +import type { InjectableTarget } from '../../../src/integrations/tracing/nest/types'; describe('Nest', () => { describe('isPatched', () => { From d45694ace766cf3d3e6a9d298565acc343814053 Mon Sep 17 00:00:00 2001 From: nicohrubec Date: Fri, 2 Aug 2024 13:02:08 +0200 Subject: [PATCH 3/5] Move SentryNestInstrumentatino --- .../tracing/nest/SentryNestInstrumentation.ts | 180 +++++++++++++++++ .../src/integrations/tracing/nest/nest.ts | 184 +----------------- 2 files changed, 182 insertions(+), 182 deletions(-) create mode 100644 packages/node/src/integrations/tracing/nest/SentryNestInstrumentation.ts diff --git a/packages/node/src/integrations/tracing/nest/SentryNestInstrumentation.ts b/packages/node/src/integrations/tracing/nest/SentryNestInstrumentation.ts new file mode 100644 index 000000000000..52c3a4ad6b40 --- /dev/null +++ b/packages/node/src/integrations/tracing/nest/SentryNestInstrumentation.ts @@ -0,0 +1,180 @@ +import { isWrapped } from '@opentelemetry/core'; +import type { InstrumentationConfig } from '@opentelemetry/instrumentation'; +import { + InstrumentationBase, + InstrumentationNodeModuleDefinition, + InstrumentationNodeModuleFile, +} from '@opentelemetry/instrumentation'; +import { getActiveSpan, startSpan, startSpanManual, withActiveSpan } from '@sentry/core'; +import type { Span } from '@sentry/types'; +import { SDK_VERSION } from '@sentry/utils'; +import { getMiddlewareSpanOptions, isPatched } from './helpers'; +import type { InjectableTarget } from './types'; + +const supportedVersions = ['>=8.0.0 <11']; + +/** + * Custom instrumentation for nestjs. + * + * This hooks into the @Injectable decorator, which is applied on class middleware, interceptors and guards. + */ +export class SentryNestInstrumentation extends InstrumentationBase { + public static readonly COMPONENT = '@nestjs/common'; + public static readonly COMMON_ATTRIBUTES = { + component: SentryNestInstrumentation.COMPONENT, + }; + + public constructor(config: InstrumentationConfig = {}) { + super('sentry-nestjs', SDK_VERSION, config); + } + + /** + * Initializes the instrumentation by defining the modules to be patched. + */ + public init(): InstrumentationNodeModuleDefinition { + const moduleDef = new InstrumentationNodeModuleDefinition(SentryNestInstrumentation.COMPONENT, supportedVersions); + + moduleDef.files.push(this._getInjectableFileInstrumentation(supportedVersions)); + return moduleDef; + } + + /** + * Wraps the @Injectable decorator. + */ + private _getInjectableFileInstrumentation(versions: string[]): InstrumentationNodeModuleFile { + return new InstrumentationNodeModuleFile( + '@nestjs/common/decorators/core/injectable.decorator.js', + versions, + (moduleExports: { Injectable: InjectableTarget }) => { + if (isWrapped(moduleExports.Injectable)) { + this._unwrap(moduleExports, 'Injectable'); + } + this._wrap(moduleExports, 'Injectable', this._createWrapInjectable()); + return moduleExports; + }, + (moduleExports: { Injectable: InjectableTarget }) => { + this._unwrap(moduleExports, 'Injectable'); + }, + ); + } + + /** + * Creates a wrapper function for the @Injectable decorator. + * + * Wraps the use method to instrument nest class middleware. + */ + private _createWrapInjectable() { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return function wrapInjectable(original: any) { + return function wrappedInjectable(options?: unknown) { + return function (target: InjectableTarget) { + // patch middleware + if (typeof target.prototype.use === 'function' && !target.__SENTRY_INTERNAL__) { + // patch only once + if (isPatched(target)) { + return original(options)(target); + } + + target.prototype.use = new Proxy(target.prototype.use, { + apply: (originalUse, thisArgUse, argsUse) => { + const [req, res, next, ...args] = argsUse; + const prevSpan = getActiveSpan(); + + return startSpanManual(getMiddlewareSpanOptions(target), (span: Span) => { + const nextProxy = new Proxy(next, { + apply: (originalNext, thisArgNext, argsNext) => { + span.end(); + + if (prevSpan) { + return withActiveSpan(prevSpan, () => { + return Reflect.apply(originalNext, thisArgNext, argsNext); + }); + } else { + return Reflect.apply(originalNext, thisArgNext, argsNext); + } + }, + }); + + return originalUse.apply(thisArgUse, [req, res, nextProxy, args]); + }); + }, + }); + } + + // patch guards + if (typeof target.prototype.canActivate === 'function' && !target.__SENTRY_INTERNAL__) { + // patch only once + if (isPatched(target)) { + return original(options)(target); + } + + target.prototype.canActivate = new Proxy(target.prototype.canActivate, { + apply: (originalCanActivate, thisArgCanActivate, argsCanActivate) => { + return startSpan(getMiddlewareSpanOptions(target), () => { + return originalCanActivate.apply(thisArgCanActivate, argsCanActivate); + }); + }, + }); + } + + // patch pipes + if (typeof target.prototype.transform === 'function' && !target.__SENTRY_INTERNAL__) { + if (isPatched(target)) { + return original(options)(target); + } + + target.prototype.transform = new Proxy(target.prototype.transform, { + apply: (originalTransform, thisArgTransform, argsTransform) => { + return startSpan(getMiddlewareSpanOptions(target), () => { + return originalTransform.apply(thisArgTransform, argsTransform); + }); + }, + }); + } + + // patch interceptors + if (typeof target.prototype.intercept === 'function' && !target.__SENTRY_INTERNAL__) { + if (isPatched(target)) { + return original(options)(target); + } + + target.prototype.intercept = new Proxy(target.prototype.intercept, { + apply: (originalIntercept, thisArgIntercept, argsIntercept) => { + const [executionContext, next, args] = argsIntercept; + const prevSpan = getActiveSpan(); + + return startSpanManual(getMiddlewareSpanOptions(target), (span: Span) => { + const nextProxy = new Proxy(next, { + get: (thisArgNext, property, receiver) => { + if (property === 'handle') { + const originalHandle = Reflect.get(thisArgNext, property, receiver); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return (...args: any[]) => { + span.end(); + + if (prevSpan) { + return withActiveSpan(prevSpan, () => { + return Reflect.apply(originalHandle, thisArgNext, args); + }); + } else { + return Reflect.apply(originalHandle, thisArgNext, args); + } + }; + } + + return Reflect.get(target, property, receiver); + }, + }); + + return originalIntercept.apply(thisArgIntercept, [executionContext, nextProxy, args]); + }); + }, + }); + } + + return original(options)(target); + }; + }; + }; + } +} diff --git a/packages/node/src/integrations/tracing/nest/nest.ts b/packages/node/src/integrations/tracing/nest/nest.ts index ab890e742750..5d5ee1166e37 100644 --- a/packages/node/src/integrations/tracing/nest/nest.ts +++ b/packages/node/src/integrations/tracing/nest/nest.ts @@ -1,202 +1,22 @@ -import { isWrapped } from '@opentelemetry/core'; -import type { InstrumentationConfig } from '@opentelemetry/instrumentation'; -import { - InstrumentationBase, - InstrumentationNodeModuleDefinition, - InstrumentationNodeModuleFile, -} from '@opentelemetry/instrumentation'; import { NestInstrumentation } from '@opentelemetry/instrumentation-nestjs-core'; import { - SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, captureException, defineIntegration, - getActiveSpan, getClient, getDefaultIsolationScope, getIsolationScope, spanToJSON, - startSpan, - startSpanManual, - withActiveSpan, } from '@sentry/core'; import type { IntegrationFn, Span } from '@sentry/types'; import { logger } from '@sentry/utils'; import { generateInstrumentOnce } from '../../../otel/instrument'; -import { getMiddlewareSpanOptions, isPatched } from './helpers'; -import type { InjectableTarget, MinimalNestJsApp, NestJsErrorFilter } from './types'; +import { SentryNestInstrumentation } from './SentryNestInstrumentation'; +import type { MinimalNestJsApp, NestJsErrorFilter } from './types'; const INTEGRATION_NAME = 'Nest'; -const supportedVersions = ['>=8.0.0 <11']; - -/** - * Custom instrumentation for nestjs. - * - * This hooks into the @Injectable decorator, which is applied on class middleware, interceptors and guards. - */ -export class SentryNestInstrumentation extends InstrumentationBase { - public static readonly COMPONENT = '@nestjs/common'; - public static readonly COMMON_ATTRIBUTES = { - component: SentryNestInstrumentation.COMPONENT, - }; - - public constructor(config: InstrumentationConfig = {}) { - super('sentry-nestjs', SDK_VERSION, config); - } - - /** - * Initializes the instrumentation by defining the modules to be patched. - */ - public init(): InstrumentationNodeModuleDefinition { - const moduleDef = new InstrumentationNodeModuleDefinition(SentryNestInstrumentation.COMPONENT, supportedVersions); - - moduleDef.files.push(this._getInjectableFileInstrumentation(supportedVersions)); - return moduleDef; - } - - /** - * Wraps the @Injectable decorator. - */ - private _getInjectableFileInstrumentation(versions: string[]): InstrumentationNodeModuleFile { - return new InstrumentationNodeModuleFile( - '@nestjs/common/decorators/core/injectable.decorator.js', - versions, - (moduleExports: { Injectable: InjectableTarget }) => { - if (isWrapped(moduleExports.Injectable)) { - this._unwrap(moduleExports, 'Injectable'); - } - this._wrap(moduleExports, 'Injectable', this._createWrapInjectable()); - return moduleExports; - }, - (moduleExports: { Injectable: InjectableTarget }) => { - this._unwrap(moduleExports, 'Injectable'); - }, - ); - } - - /** - * Creates a wrapper function for the @Injectable decorator. - * - * Wraps the use method to instrument nest class middleware. - */ - private _createWrapInjectable() { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return function wrapInjectable(original: any) { - return function wrappedInjectable(options?: unknown) { - return function (target: InjectableTarget) { - // patch middleware - if (typeof target.prototype.use === 'function' && !target.__SENTRY_INTERNAL__) { - // patch only once - if (isPatched(target)) { - return original(options)(target); - } - - target.prototype.use = new Proxy(target.prototype.use, { - apply: (originalUse, thisArgUse, argsUse) => { - const [req, res, next, ...args] = argsUse; - const prevSpan = getActiveSpan(); - - return startSpanManual(getMiddlewareSpanOptions(target), (span: Span) => { - const nextProxy = new Proxy(next, { - apply: (originalNext, thisArgNext, argsNext) => { - span.end(); - - if (prevSpan) { - return withActiveSpan(prevSpan, () => { - return Reflect.apply(originalNext, thisArgNext, argsNext); - }); - } else { - return Reflect.apply(originalNext, thisArgNext, argsNext); - } - }, - }); - - return originalUse.apply(thisArgUse, [req, res, nextProxy, args]); - }); - }, - }); - } - - // patch guards - if (typeof target.prototype.canActivate === 'function' && !target.__SENTRY_INTERNAL__) { - // patch only once - if (isPatched(target)) { - return original(options)(target); - } - - target.prototype.canActivate = new Proxy(target.prototype.canActivate, { - apply: (originalCanActivate, thisArgCanActivate, argsCanActivate) => { - return startSpan(getMiddlewareSpanOptions(target), () => { - return originalCanActivate.apply(thisArgCanActivate, argsCanActivate); - }); - }, - }); - } - - // patch pipes - if (typeof target.prototype.transform === 'function' && !target.__SENTRY_INTERNAL__) { - if (isPatched(target)) { - return original(options)(target); - } - - target.prototype.transform = new Proxy(target.prototype.transform, { - apply: (originalTransform, thisArgTransform, argsTransform) => { - return startSpan(getMiddlewareSpanOptions(target), () => { - return originalTransform.apply(thisArgTransform, argsTransform); - }); - }, - }); - } - - // patch interceptors - if (typeof target.prototype.intercept === 'function' && !target.__SENTRY_INTERNAL__) { - if (isPatched(target)) { - return original(options)(target); - } - - target.prototype.intercept = new Proxy(target.prototype.intercept, { - apply: (originalIntercept, thisArgIntercept, argsIntercept) => { - const [executionContext, next, args] = argsIntercept; - const prevSpan = getActiveSpan(); - - return startSpanManual(getMiddlewareSpanOptions(target), (span: Span) => { - const nextProxy = new Proxy(next, { - get: (thisArgNext, property, receiver) => { - if (property === 'handle') { - const originalHandle = Reflect.get(thisArgNext, property, receiver); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return (...args: any[]) => { - span.end(); - - if (prevSpan) { - return withActiveSpan(prevSpan, () => { - return Reflect.apply(originalHandle, thisArgNext, args); - }); - } else { - return Reflect.apply(originalHandle, thisArgNext, args); - } - }; - } - - return Reflect.get(target, property, receiver); - }, - }); - - return originalIntercept.apply(thisArgIntercept, [executionContext, nextProxy, args]); - }); - }, - }); - } - - return original(options)(target); - }; - }; - }; - } -} - const instrumentNestCore = generateInstrumentOnce('Nest-Core', () => { return new NestInstrumentation(); }); From cbbb371e8f357d83380040ee3d6c4eaf7a36d724 Mon Sep 17 00:00:00 2001 From: nicohrubec Date: Mon, 5 Aug 2024 09:30:39 +0200 Subject: [PATCH 4/5] Rename file --- ...entryNestInstrumentation.ts => sentry-nest-instrumentation.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/node/src/integrations/tracing/nest/{SentryNestInstrumentation.ts => sentry-nest-instrumentation.ts} (100%) diff --git a/packages/node/src/integrations/tracing/nest/SentryNestInstrumentation.ts b/packages/node/src/integrations/tracing/nest/sentry-nest-instrumentation.ts similarity index 100% rename from packages/node/src/integrations/tracing/nest/SentryNestInstrumentation.ts rename to packages/node/src/integrations/tracing/nest/sentry-nest-instrumentation.ts From 29561fd070402cd9e833497824661d7f7858a7d1 Mon Sep 17 00:00:00 2001 From: nicohrubec Date: Mon, 5 Aug 2024 09:42:07 +0200 Subject: [PATCH 5/5] fix build --- packages/node/src/integrations/tracing/nest/nest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/node/src/integrations/tracing/nest/nest.ts b/packages/node/src/integrations/tracing/nest/nest.ts index 5d5ee1166e37..4f7f7a1f59d3 100644 --- a/packages/node/src/integrations/tracing/nest/nest.ts +++ b/packages/node/src/integrations/tracing/nest/nest.ts @@ -12,7 +12,7 @@ import { import type { IntegrationFn, Span } from '@sentry/types'; import { logger } from '@sentry/utils'; import { generateInstrumentOnce } from '../../../otel/instrument'; -import { SentryNestInstrumentation } from './SentryNestInstrumentation'; +import { SentryNestInstrumentation } from './sentry-nest-instrumentation'; import type { MinimalNestJsApp, NestJsErrorFilter } from './types'; const INTEGRATION_NAME = 'Nest';