@@ -25,7 +25,9 @@ type MethodWrapperOptions = {
2525} ;
2626
2727// eslint-disable-next-line @typescript-eslint/no-explicit-any
28- function wrapMethodWithSentry < T extends ( ...args : any [ ] ) => any > (
28+ type OriginalMethod = ( ...args : any [ ] ) => any ;
29+
30+ function wrapMethodWithSentry < T extends OriginalMethod > (
2931 wrapperOptions : MethodWrapperOptions ,
3032 handler : T ,
3133 callback ?: ( ...args : Parameters < T > ) => void ,
@@ -221,8 +223,65 @@ export function instrumentDurableObjectWithSentry<
221223 ) ;
222224 }
223225 }
226+ const instrumentedPrototype = instrumentPrototype ( target , options , context ) ;
227+ Object . setPrototypeOf ( obj , instrumentedPrototype ) ;
224228
225229 return obj ;
226230 } ,
227231 } ) ;
228232}
233+
234+ function instrumentPrototype < T extends NewableFunction > (
235+ target : T ,
236+ options : CloudflareOptions ,
237+ context : MethodWrapperOptions [ 'context' ] ,
238+ ) : typeof target . prototype {
239+ const sentryMethods = new Map < string | symbol , OriginalMethod > ( ) ;
240+ let proto = target . prototype ;
241+ const instrumentedPrototype = new Proxy ( proto , {
242+ get ( target , prop , receiver ) {
243+ if ( sentryMethods . has ( prop ) ) {
244+ return sentryMethods . get ( prop ) ;
245+ }
246+ return Reflect . get ( target , prop , receiver ) ;
247+ } ,
248+ } ) ;
249+ while ( proto && proto !== Object . prototype ) {
250+ for ( const method of Object . getOwnPropertyNames ( proto ) ) {
251+ if ( method === 'constructor' || sentryMethods . has ( method ) ) {
252+ continue ;
253+ }
254+
255+ const descriptor = Object . getOwnPropertyDescriptor ( proto , method ) as {
256+ value ?: OriginalMethod ;
257+ get ?: ( ) => OriginalMethod ;
258+ } ;
259+ const value = descriptor . value ?? descriptor . get ?.( ) ;
260+ if ( typeof value === 'function' ) {
261+ sentryMethods . set (
262+ method ,
263+ wrapMethodWithSentry (
264+ {
265+ options,
266+ context,
267+ spanName : method ,
268+ spanOp : 'rpc' ,
269+ } ,
270+ // <editor-fold desc="Disable __SENTRY_INSTRUMENTED__ for prototype methods">
271+ new Proxy ( value , {
272+ set ( target , p , newValue , receiver ) : boolean {
273+ if ( '__SENTRY_INSTRUMENTED__' === p ) {
274+ return true ;
275+ }
276+ return Reflect . set ( target , p , newValue , receiver ) ;
277+ } ,
278+ } ) ,
279+ // </editor-fold>
280+ ) ,
281+ ) ;
282+ }
283+ }
284+ proto = Object . getPrototypeOf ( proto ) ;
285+ }
286+ return instrumentedPrototype ;
287+ }
0 commit comments