@@ -36,6 +36,7 @@ type PostgresConnectionContext = {
3636} ;
3737
3838const CONNECTION_CONTEXT_SYMBOL = Symbol ( 'sentryPostgresConnectionContext' ) ;
39+ const INSTRUMENTED_MARKER = Symbol . for ( 'sentry.instrumented.postgresjs' ) ;
3940
4041type PostgresJsInstrumentationConfig = InstrumentationConfig & {
4142 /**
@@ -112,6 +113,13 @@ export class PostgresJsInstrumentation extends InstrumentationBase<PostgresJsIns
112113
113114 const WrappedPostgres = function ( this : unknown , ...args : unknown [ ] ) : unknown {
114115 const sql = Reflect . construct ( Original as ( ...args : unknown [ ] ) => unknown , args ) ;
116+
117+ // Validate that construction succeeded and returned a valid function object
118+ if ( ! sql || typeof sql !== 'function' ) {
119+ DEBUG_BUILD && debug . warn ( 'postgres() did not return a valid instance' ) ;
120+ return sql ;
121+ }
122+
115123 return self . _instrumentSqlInstance ( sql ) ;
116124 } ;
117125
@@ -267,7 +275,8 @@ export class PostgresJsInstrumentation extends InstrumentationBase<PostgresJsIns
267275 */
268276 private _instrumentSqlInstance ( sql : unknown , parentConnectionContext ?: PostgresConnectionContext ) : unknown {
269277 // Check if already instrumented to prevent double-wrapping
270- if ( ( sql as { __sentryInstrumented ?: boolean } ) . __sentryInstrumented ) {
278+ // Using Symbol.for() ensures the marker survives proxying
279+ if ( ( sql as Record < symbol , unknown > ) [ INSTRUMENTED_MARKER ] ) {
271280 return sql ;
272281 }
273282
@@ -313,8 +322,11 @@ export class PostgresJsInstrumentation extends InstrumentationBase<PostgresJsIns
313322 this . _attachConnectionContext ( sql , proxiedSql as Record < symbol , unknown > ) ;
314323 }
315324
316- // Mark as instrumented to prevent double-wrapping
317- ( sql as { __sentryInstrumented ?: boolean } ) . __sentryInstrumented = true ;
325+ // Mark both the original and proxy as instrumented to prevent double-wrapping
326+ // The proxy might be passed to other methods, or the original
327+ // might be accessed directly, so we need to mark both
328+ ( sql as Record < symbol , unknown > ) [ INSTRUMENTED_MARKER ] = true ;
329+ ( proxiedSql as Record < symbol , unknown > ) [ INSTRUMENTED_MARKER ] = true ;
318330
319331 return proxiedSql ;
320332 }
@@ -377,6 +389,8 @@ export class PostgresJsInstrumentation extends InstrumentationBase<PostgresJsIns
377389 try {
378390 config . requestHook ( span , sanitizedSqlQuery , connectionContext ) ;
379391 } catch ( e ) {
392+ // Set attribute to indicate hook failure, making it visible in spans
393+ span . setAttribute ( 'sentry.hook.error' , 'requestHook failed' ) ;
380394 DEBUG_BUILD && debug . error ( `Error in requestHook for ${ INTEGRATION_NAME } integration:` , e ) ;
381395 }
382396 }
@@ -388,28 +402,34 @@ export class PostgresJsInstrumentation extends InstrumentationBase<PostgresJsIns
388402
389403 queryWithCallbacks . resolve = new Proxy ( queryWithCallbacks . resolve as ( ...args : unknown [ ] ) => unknown , {
390404 apply : ( resolveTarget , resolveThisArg , resolveArgs : [ { command ?: string } ] ) => {
391- const result = Reflect . apply ( resolveTarget , resolveThisArg , resolveArgs ) ;
392- self . _setOperationName ( span , sanitizedSqlQuery , resolveArgs ?. [ 0 ] ?. command ) ;
393- span . end ( ) ;
394- return result ;
405+ try {
406+ self . _setOperationName ( span , sanitizedSqlQuery , resolveArgs ?. [ 0 ] ?. command ) ;
407+ span . end ( ) ;
408+ } catch ( e ) {
409+ DEBUG_BUILD && debug . error ( 'Error ending span in resolve callback:' , e ) ;
410+ }
411+
412+ return Reflect . apply ( resolveTarget , resolveThisArg , resolveArgs ) ;
395413 } ,
396414 } ) ;
397415
398416 queryWithCallbacks . reject = new Proxy ( queryWithCallbacks . reject as ( ...args : unknown [ ] ) => unknown , {
399417 apply : ( rejectTarget , rejectThisArg , rejectArgs : { message ?: string ; code ?: string ; name ?: string } [ ] ) => {
400- span . setStatus ( {
401- code : SPAN_STATUS_ERROR ,
402- message : rejectArgs ?. [ 0 ] ?. message || 'unknown_error' ,
403- } ) ;
404-
405- span . setAttribute ( ATTR_DB_RESPONSE_STATUS_CODE , rejectArgs ?. [ 0 ] ?. code || 'unknown' ) ;
406- span . setAttribute ( ATTR_ERROR_TYPE , rejectArgs ?. [ 0 ] ?. name || 'unknown' ) ;
407-
408- self . _setOperationName ( span , sanitizedSqlQuery ) ;
409-
410- const result = Reflect . apply ( rejectTarget , rejectThisArg , rejectArgs ) ;
411- span . end ( ) ;
412- return result ;
418+ try {
419+ span . setStatus ( {
420+ code : SPAN_STATUS_ERROR ,
421+ message : rejectArgs ?. [ 0 ] ?. message || 'unknown_error' ,
422+ } ) ;
423+
424+ span . setAttribute ( ATTR_DB_RESPONSE_STATUS_CODE , rejectArgs ?. [ 0 ] ?. code || 'unknown' ) ;
425+ span . setAttribute ( ATTR_ERROR_TYPE , rejectArgs ?. [ 0 ] ?. name || 'unknown' ) ;
426+
427+ self . _setOperationName ( span , sanitizedSqlQuery ) ;
428+ span . end ( ) ;
429+ } catch ( e ) {
430+ DEBUG_BUILD && debug . error ( 'Error ending span in reject callback:' , e ) ;
431+ }
432+ return Reflect . apply ( rejectTarget , rejectThisArg , rejectArgs ) ;
413433 } ,
414434 } ) ;
415435
0 commit comments