@@ -12,6 +12,12 @@ import {
12
12
import type { IntegrationFn , Span } from '@sentry/types' ;
13
13
import { logger } from '@sentry/utils' ;
14
14
import { generateInstrumentOnce } from '../../otel/instrument' ;
15
+ import type { InstrumentationConfig } from '@opentelemetry/instrumentation' ;
16
+ import {
17
+ InstrumentationBase ,
18
+ InstrumentationNodeModuleDefinition , InstrumentationNodeModuleFile
19
+ } from '@opentelemetry/instrumentation' ;
20
+ import { isWrapped } from '@opentelemetry/core' ;
15
21
16
22
interface MinimalNestJsExecutionContext {
17
23
getType : ( ) => string ;
@@ -44,7 +50,96 @@ interface MinimalNestJsApp {
44
50
45
51
const INTEGRATION_NAME = 'Nest' ;
46
52
47
- export const instrumentNest = generateInstrumentOnce ( INTEGRATION_NAME , ( ) => new NestInstrumentation ( ) ) ;
53
+ const supportedVersions = [ '>=8.0.0 <11' ] ;
54
+
55
+ /**
56
+ *
57
+ */
58
+ export class SentryNestInstrumentation extends InstrumentationBase {
59
+ public static readonly COMPONENT = '@nestjs/common' ;
60
+ public static readonly COMMON_ATTRIBUTES = {
61
+ component : SentryNestInstrumentation . COMPONENT ,
62
+ } ;
63
+
64
+ public constructor ( config : InstrumentationConfig = { } ) {
65
+ super ( 'sentry-nestjs' , '1.0.0' , config ) ;
66
+ }
67
+
68
+ /**
69
+ *
70
+ */
71
+ public init ( ) : void {
72
+ logger . log ( 'init!' ) ;
73
+ const module = new InstrumentationNodeModuleDefinition (
74
+ SentryNestInstrumentation . COMPONENT ,
75
+ supportedVersions
76
+ )
77
+
78
+ module . files . push (
79
+ this . _getInjectableFileInstrumentation ( supportedVersions )
80
+ )
81
+ }
82
+
83
+ /**
84
+ *
85
+ */
86
+ private _getInjectableFileInstrumentation ( versions : string [ ] ) : InstrumentationNodeModuleFile {
87
+ logger . log ( 'create instrumentation node module file' ) ;
88
+ return new InstrumentationNodeModuleFile (
89
+ '@nestjs/common/decorators/core/injectable.decorator.js' ,
90
+ versions ,
91
+ ( moduleExports : any ) => {
92
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
93
+ if ( isWrapped ( moduleExports . Injectable ) ) {
94
+ this . _unwrap ( moduleExports , 'Injectable' ) ;
95
+ }
96
+ this . _wrap ( moduleExports , 'Injectable' , this . _createWrapInjectable ( ) ) ;
97
+ return moduleExports ;
98
+ } ,
99
+ ( moduleExports : any ) => {
100
+ this . _unwrap ( moduleExports , 'Injectable' ) ;
101
+ }
102
+ )
103
+ }
104
+
105
+ /**
106
+ *
107
+ */
108
+ private _createWrapInjectable ( ) {
109
+ return function wrapInjectable ( original : any ) {
110
+ return function wrappedInjectable ( options ?: any ) {
111
+ return function ( target : any ) {
112
+ logger . log ( 'Injectable target:' , target ) ;
113
+
114
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
115
+ if ( typeof target . prototype . use === 'function' ) {
116
+ logger . log ( 'middleware!' ) ;
117
+ }
118
+
119
+ return original ( options ) ( target ) ;
120
+ } ;
121
+ } ;
122
+ } ;
123
+ }
124
+ }
125
+
126
+ const instrumentNestCore = generateInstrumentOnce ( 'Nest-Core' , ( ) => {
127
+ logger . log ( 'init nest core instrumentation' ) ;
128
+ return new NestInstrumentation ( ) ;
129
+ } ) ;
130
+
131
+ const instrumentMiddleware = generateInstrumentOnce ( 'Nest-Middleware' , ( ) => {
132
+ logger . log ( 'init nest middleware instrumentation' ) ;
133
+ return new SentryNestInstrumentation ( ) ;
134
+ } ) ;
135
+
136
+ export const instrumentNest = Object . assign (
137
+ ( ) : void => {
138
+ instrumentNestCore ( ) ;
139
+ instrumentMiddleware ( ) ;
140
+ } ,
141
+ { id : INTEGRATION_NAME } ,
142
+ ) ;
48
143
49
144
const _nestIntegration = ( ( ) => {
50
145
return {
0 commit comments