11import { tracingChannel } from 'node:diagnostics_channel' ;
2- import type { IntegrationFn , LogSeverityLevel } from '@sentry/core' ;
2+ import type { Integration , IntegrationFn , LogSeverityLevel } from '@sentry/core' ;
33import {
44 _INTERNAL_captureLog ,
55 addExceptionMechanism ,
@@ -11,13 +11,16 @@ import {
1111} from '@sentry/core' ;
1212import { addInstrumentationConfig } from '../sdk/injectLoader' ;
1313
14+ const SENTRY_TRACK_SYMBOL = Symbol ( 'sentry-track-pino-logger' ) ;
15+
1416type LevelMapping = {
1517 // Fortunately pino uses the same levels as Sentry
1618 labels : { [ level : number ] : LogSeverityLevel } ;
1719} ;
1820
1921type Pino = {
2022 levels : LevelMapping ;
23+ [ SENTRY_TRACK_SYMBOL ] ?: 'track' | 'ignore' ;
2124} ;
2225
2326type MergeObject = {
@@ -28,6 +31,17 @@ type MergeObject = {
2831type PinoHookArgs = [ MergeObject , string , number ] ;
2932
3033type PinoOptions = {
34+ /**
35+ * Automatically instrument all Pino loggers.
36+ *
37+ * When set to `false`, only loggers marked with `pinoIntegration.trackLogger(logger)` will be captured.
38+ *
39+ * @default true
40+ */
41+ autoInstrument : boolean ;
42+ /**
43+ * Options to enable capturing of error events.
44+ */
3145 error : {
3246 /**
3347 * Levels that trigger capturing of events.
@@ -43,6 +57,9 @@ type PinoOptions = {
4357 */
4458 handled : boolean ;
4559 } ;
60+ /**
61+ * Options to enable capturing of logs.
62+ */
4663 log : {
4764 /**
4865 * Levels that trigger capturing of logs. Logs are only captured if
@@ -55,6 +72,7 @@ type PinoOptions = {
5572} ;
5673
5774const DEFAULT_OPTIONS : PinoOptions = {
75+ autoInstrument : true ,
5876 error : { levels : [ ] , handled : true } ,
5977 log : { levels : [ 'trace' , 'debug' , 'info' , 'warn' , 'error' , 'fatal' ] } ,
6078} ;
@@ -63,18 +81,18 @@ type DeepPartial<T> = {
6381 [ P in keyof T ] ?: T [ P ] extends object ? Partial < T [ P ] > : T [ P ] ;
6482} ;
6583
66- /**
67- * Integration for Pino logging library.
68- * Captures Pino logs as Sentry logs and optionally captures some log levels as events.
69- *
70- * Requires Pino >=v8.0.0 and Node >=20.6.0 or >=18.19.0
71- */
72- export const pinoIntegration = defineIntegration ( ( userOptions : DeepPartial < PinoOptions > = { } ) => {
84+ const _pinoIntegration = defineIntegration ( ( userOptions : DeepPartial < PinoOptions > = { } ) => {
7385 const options : PinoOptions = {
86+ autoInstrument : userOptions . autoInstrument === false ? userOptions . autoInstrument : DEFAULT_OPTIONS . autoInstrument ,
7487 error : { ...DEFAULT_OPTIONS . error , ...userOptions . error } ,
7588 log : { ...DEFAULT_OPTIONS . log , ...userOptions . log } ,
7689 } ;
7790
91+ function shouldTrackLogger ( logger : Pino ) : boolean {
92+ const override = logger [ SENTRY_TRACK_SYMBOL ] ;
93+ return override === 'track' || ( override !== 'ignore' && options . autoInstrument ) ;
94+ }
95+
7896 return {
7997 name : 'Pino' ,
8098 setup : client => {
@@ -95,6 +113,10 @@ export const pinoIntegration = defineIntegration((userOptions: DeepPartial<PinoO
95113 const integratedChannel = tracingChannel ( 'pino_asJson' ) ;
96114
97115 function onPinoStart ( self : Pino , args : PinoHookArgs , result : string ) : void {
116+ if ( ! shouldTrackLogger ( self ) ) {
117+ return ;
118+ }
119+
98120 const [ obj , message , levelNumber ] = args ;
99121 const level = self ?. levels ?. labels ?. [ levelNumber ] || 'info' ;
100122
@@ -157,3 +179,42 @@ export const pinoIntegration = defineIntegration((userOptions: DeepPartial<PinoO
157179 } ,
158180 } ;
159181} ) satisfies IntegrationFn ;
182+
183+ interface PinoIntegrationFunction {
184+ ( userOptions ?: DeepPartial < PinoOptions > ) : Integration ;
185+ /**
186+ * Marks a Pino logger to be tracked by the Pino integration.
187+ *
188+ * @param logger A Pino logger instance.
189+ */
190+ trackLogger ( logger : unknown ) : void ;
191+ /**
192+ * Marks a Pino logger to be ignored by the Pino integration.
193+ *
194+ * @param logger A Pino logger instance.
195+ */
196+ untrackLogger ( logger : unknown ) : void ;
197+ }
198+
199+ /**
200+ * Integration for Pino logging library.
201+ * Captures Pino logs as Sentry logs and optionally captures some log levels as events.
202+ *
203+ * By default, all Pino loggers will be captured. To ignore a specific logger, use `pinoIntegration.untrackLogger(logger)`.
204+ *
205+ * If you disable automatic instrumentation with `autoInstrument: false`, you can mark specific loggers to be tracked with `pinoIntegration.trackLogger(logger)`.
206+ *
207+ * Requires Pino >=v8.0.0 and Node >=20.6.0 or >=18.19.0
208+ */
209+ export const pinoIntegration = Object . assign ( _pinoIntegration , {
210+ trackLogger ( logger : unknown ) : void {
211+ if ( logger && typeof logger === 'object' && 'levels' in logger ) {
212+ ( logger as Pino ) [ SENTRY_TRACK_SYMBOL ] = 'track' ;
213+ }
214+ } ,
215+ untrackLogger ( logger : unknown ) : void {
216+ if ( logger && typeof logger === 'object' && 'levels' in logger ) {
217+ ( logger as Pino ) [ SENTRY_TRACK_SYMBOL ] = 'ignore' ;
218+ }
219+ } ,
220+ } ) as PinoIntegrationFunction ;
0 commit comments