@@ -110,8 +110,7 @@ function wrapMethodWithSentry<T extends OriginalMethod>(
110
110
}
111
111
: { } ;
112
112
113
- // Only create these spans if they have a parent span.
114
- return startSpan ( { name : wrapperOptions . spanName , attributes, onlyIfParent : true } , ( ) => {
113
+ return startSpan ( { name : wrapperOptions . spanName , attributes } , ( ) => {
115
114
try {
116
115
const result = Reflect . apply ( target , thisArg , args ) ;
117
116
@@ -273,46 +272,87 @@ export function instrumentDurableObjectWithSentry<
273
272
) ;
274
273
}
275
274
}
276
- const instrumentedPrototype = instrumentPrototype ( target , options , context ) ;
277
- Object . setPrototypeOf ( obj , instrumentedPrototype ) ;
275
+
276
+ // Store context and options on the instance for prototype methods to access
277
+ Object . defineProperty ( obj , '__SENTRY_CONTEXT__' , {
278
+ value : context ,
279
+ enumerable : false ,
280
+ writable : false ,
281
+ configurable : false ,
282
+ } ) ;
283
+
284
+ Object . defineProperty ( obj , '__SENTRY_OPTIONS__' , {
285
+ value : options ,
286
+ enumerable : false ,
287
+ writable : false ,
288
+ configurable : false ,
289
+ } ) ;
290
+
291
+ instrumentPrototype ( target ) ;
278
292
279
293
return obj ;
280
294
} ,
281
295
} ) ;
282
296
}
283
297
284
- function instrumentPrototype < T extends NewableFunction > (
285
- target : T ,
286
- options : CloudflareOptions ,
287
- context : MethodWrapperOptions [ 'context' ] ,
288
- ) : T {
289
- return new Proxy ( target . prototype , {
290
- get ( target , prop , receiver ) {
291
- const value = Reflect . get ( target , prop , receiver ) ;
292
- if ( prop === 'constructor' || typeof value !== 'function' ) {
293
- return value ;
298
+ function instrumentPrototype < T extends NewableFunction > ( target : T ) : void {
299
+ const proto = target . prototype ;
300
+
301
+ // Get all methods from the prototype chain
302
+ const methodNames = new Set < string > ( ) ;
303
+ let current = proto ;
304
+
305
+ while ( current && current !== Object . prototype ) {
306
+ Object . getOwnPropertyNames ( current ) . forEach ( name => {
307
+ if ( name !== 'constructor' && typeof current [ name ] === 'function' ) {
308
+ methodNames . add ( name ) ;
309
+ }
310
+ } ) ;
311
+ current = Object . getPrototypeOf ( current ) ;
312
+ }
313
+
314
+ // Instrument each method on the prototype
315
+ methodNames . forEach ( methodName => {
316
+ const originalMethod = proto [ methodName ] ;
317
+
318
+ if ( ! originalMethod || isInstrumented ( originalMethod ) ) {
319
+ return ;
320
+ }
321
+
322
+ // Create a wrapper that gets context/options from the instance at runtime
323
+ const wrappedMethod = function ( this : any , ...args : any [ ] ) {
324
+ const instanceContext = this . __SENTRY_CONTEXT__ ;
325
+ const instanceOptions = this . __SENTRY_OPTIONS__ ;
326
+
327
+ if ( ! instanceOptions ) {
328
+ // Fallback to original method if no Sentry data found
329
+ return originalMethod . apply ( this , args ) ;
294
330
}
295
- const wrapped = wrapMethodWithSentry (
296
- { options, context, spanName : prop . toString ( ) , spanOp : 'rpc' } ,
297
- value ,
331
+
332
+ // Use the existing wrapper but with instance-specific context/options
333
+ const wrapper = wrapMethodWithSentry (
334
+ {
335
+ options : instanceOptions ,
336
+ context : instanceContext ,
337
+ spanName : methodName ,
338
+ spanOp : 'rpc' ,
339
+ } ,
340
+ originalMethod ,
298
341
undefined ,
299
- true ,
342
+ true , // noMark = true since we'll mark the prototype method
300
343
) ;
301
- const instrumented = new Proxy ( wrapped , {
302
- get ( target , p , receiver ) {
303
- if ( '__SENTRY_INSTRUMENTED__' === p ) {
304
- return true ;
305
- }
306
- return Reflect . get ( target , p , receiver ) ;
307
- } ,
308
- } ) ;
309
- Object . defineProperty ( receiver , prop , {
310
- value : instrumented ,
311
- enumerable : true ,
312
- writable : true ,
313
- configurable : true ,
314
- } ) ;
315
- return instrumented ;
316
- } ,
344
+
345
+ return wrapper . apply ( this , args ) ;
346
+ } ;
347
+
348
+ markAsInstrumented ( wrappedMethod ) ;
349
+
350
+ // Replace the prototype method
351
+ Object . defineProperty ( proto , methodName , {
352
+ value : wrappedMethod ,
353
+ enumerable : false ,
354
+ writable : true ,
355
+ configurable : true ,
356
+ } ) ;
317
357
} ) ;
318
358
}
0 commit comments