Skip to content

Commit a028e22

Browse files
committed
added proxy target detection for manual tracking scenarios
1 parent 80b4705 commit a028e22

1 file changed

Lines changed: 82 additions & 7 deletions

File tree

  • packages/node-core/src/integrations

packages/node-core/src/integrations/pino.ts

Lines changed: 82 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ import { addInstrumentationConfig } from '../sdk/injectLoader';
1313

1414
const SENTRY_TRACK_SYMBOL = Symbol('sentry-track-pino-logger');
1515

16+
const trackedLoggers = new WeakSet<Pino>();
17+
const ignoredLoggers = new WeakSet<Pino>();
18+
1619
type 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+
238313
export 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

Comments
 (0)