@@ -13,6 +13,9 @@ import { addInstrumentationConfig } from '../sdk/injectLoader';
1313
1414const SENTRY_TRACK_SYMBOL = Symbol ( 'sentry-track-pino-logger' ) ;
1515
16+ const trackedLoggers = new WeakSet < Pino > ( ) ;
17+ const ignoredLoggers = new WeakSet < Pino > ( ) ;
18+
1619type LevelMapping = {
1720 // Fortunately pino uses the same levels as Sentry
1821 labels : { [ level : number ] : LogSeverityLevel } ;
@@ -24,6 +27,29 @@ type Pino = {
2427 [ SENTRY_TRACK_SYMBOL ] ?: 'track' | 'ignore' ;
2528} ;
2629
30+ function isPinoLogger ( obj : unknown ) : obj is Pino {
31+ if ( ! obj || typeof obj !== 'object' ) {
32+ return false ;
33+ }
34+
35+ if ( 'levels' in obj && obj . levels && typeof obj . levels === 'object' && 'labels' in obj . levels ) {
36+ return true ;
37+ }
38+
39+ const hasPinoSymbols = Object . getOwnPropertySymbols ( obj ) . some ( sym =>
40+ sym . toString ( ) . includes ( 'pino' )
41+ ) ;
42+ let proto = Object . getPrototypeOf ( obj ) ;
43+ while ( proto && proto !== Object . prototype ) {
44+ if ( 'levels' in proto && proto . levels && typeof proto . levels === 'object' && 'labels' in proto . levels ) {
45+ return true ;
46+ }
47+ proto = Object . getPrototypeOf ( proto ) ;
48+ }
49+
50+ return hasPinoSymbols ;
51+ }
52+
2753/**
2854 * Gets a custom Pino key from a logger instance by searching for the symbol.
2955 * Pino uses non-global symbols like Symbol('pino.messageKey'): https://github.com/pinojs/pino/blob/8a816c0b1f72de5ae9181f3bb402109b66f7d812/lib/symbols.js
@@ -118,9 +144,22 @@ const _pinoIntegration = defineIntegration((userOptions: DeepPartial<PinoOptions
118144 log : { ...DEFAULT_OPTIONS . log , ...userOptions . log } ,
119145 } ;
120146
121- function shouldTrackLogger ( logger : Pino ) : boolean {
122- const override = logger [ SENTRY_TRACK_SYMBOL ] ;
123- return override === 'track' || ( override !== 'ignore' && options . autoInstrument ) ;
147+ function shouldTrackLogger ( logger : unknown ) : boolean {
148+ if ( ! isPinoLogger ( logger ) ) {
149+ return false ;
150+ }
151+
152+ const pinoLogger = logger as Pino ;
153+
154+ if ( ignoredLoggers . has ( pinoLogger ) ) {
155+ return false ;
156+ }
157+
158+ if ( trackedLoggers . has ( pinoLogger ) ) {
159+ return true ;
160+ }
161+
162+ return options . autoInstrument ;
124163 }
125164
126165 return {
@@ -235,15 +274,51 @@ interface PinoIntegrationFunction {
235274 *
236275 * Requires Pino >=v8.0.0 and Node >=20.6.0 or >=18.19.0
237276 */
277+ function trackLoggerInstance ( logger : Pino ) : void {
278+ trackedLoggers . add ( logger ) ;
279+ ignoredLoggers . delete ( logger ) ;
280+
281+ try {
282+ // @ts -expect-error - Checking proxy internals
283+ if ( logger . constructor === Proxy ) {
284+ const target = ( logger as any ) . __target__ || ( logger as any ) . target ;
285+ if ( target && isPinoLogger ( target ) ) {
286+ trackedLoggers . add ( target ) ;
287+ ignoredLoggers . delete ( target ) ;
288+ }
289+ }
290+ } catch {
291+ // Ignore errors when trying to access proxy internals
292+ }
293+ }
294+
295+ function untrackLoggerInstance ( logger : Pino ) : void {
296+ ignoredLoggers . add ( logger ) ;
297+ trackedLoggers . delete ( logger ) ;
298+
299+ try {
300+ // @ts -expect-error - Checking proxy internals
301+ if ( logger . constructor === Proxy ) {
302+ const target = ( logger as any ) . __target__ || ( logger as any ) . target ;
303+ if ( target && isPinoLogger ( target ) ) {
304+ ignoredLoggers . add ( target ) ;
305+ trackedLoggers . delete ( target ) ;
306+ }
307+ }
308+ } catch {
309+ // Ignore errors
310+ }
311+ }
312+
238313export const pinoIntegration = Object . assign ( _pinoIntegration , {
239314 trackLogger ( logger : unknown ) : void {
240- if ( logger && typeof logger === 'object' && 'levels' in logger ) {
241- ( logger as Pino ) [ SENTRY_TRACK_SYMBOL ] = 'track' ;
315+ if ( isPinoLogger ( logger ) ) {
316+ trackLoggerInstance ( logger as Pino ) ;
242317 }
243318 } ,
244319 untrackLogger ( logger : unknown ) : void {
245- if ( logger && typeof logger === 'object' && 'levels' in logger ) {
246- ( logger as Pino ) [ SENTRY_TRACK_SYMBOL ] = 'ignore' ;
320+ if ( isPinoLogger ( logger ) ) {
321+ untrackLoggerInstance ( logger as Pino ) ;
247322 }
248323 } ,
249324} ) as PinoIntegrationFunction ;
0 commit comments