22
33const {
44 DateNow,
5- Error ,
5+ ErrorIsError ,
66 JSONStringify,
77 ObjectAssign,
88 ObjectKeys,
@@ -21,11 +21,13 @@ const {
2121 validateObject,
2222 validateString,
2323 validateOneOf,
24+ validateFunction,
2425} = require ( 'internal/validators' ) ;
2526
2627const Utf8Stream = require ( 'internal/streams/fast-utf8-stream' ) ;
2728const diagnosticsChannel = require ( 'diagnostics_channel' ) ;
2829const { kEmptyObject } = require ( 'internal/util' ) ;
30+ const stdSerializers = require ( 'internal/logger/serializers' ) ;
2931
3032// Create channels for each log level
3133const channels = {
@@ -69,7 +71,6 @@ class LogConsumer {
6971
7072 validateOneOf ( level , 'options.level' , LEVEL_NAMES ) ;
7173
72- this . #level = level ;
7374 this . #levelValue = LEVELS [ level ] ;
7475 }
7576
@@ -220,10 +221,15 @@ class Logger {
220221 #level;
221222 #levelValue;
222223 #bindings;
224+ #serializers;
223225
224226 constructor ( options = kEmptyObject ) {
225227 validateObject ( options , 'options' ) ;
226- const { level = 'info' , bindings = kEmptyObject } = options ;
228+ const {
229+ level = 'info' ,
230+ bindings = kEmptyObject ,
231+ serializers = kEmptyObject ,
232+ } = options ;
227233
228234 validateString ( level , 'options.level' ) ;
229235 if ( ! LEVELS [ level ] ) {
@@ -235,11 +241,26 @@ class Logger {
235241 }
236242
237243 validateObject ( bindings , 'options.bindings' ) ;
244+ validateObject ( serializers , 'options.serializers' ) ;
245+
246+ // Validate serializers are functions
247+ for ( const key in serializers ) {
248+ validateFunction ( serializers [ key ] , `options.serializers.${ key } ` ) ;
249+ }
238250
239251 this . #level = level ;
240252 this . #levelValue = LEVELS [ level ] ;
241253 this . #bindings = bindings ;
242254
255+ // Create serializers object with default err serializer
256+ this . #serializers = { __proto__ : null } ;
257+ // Add default err serializer (can be overridden)
258+ this . #serializers. err = stdSerializers . err ;
259+ // Add custom serializers
260+ for ( const key in serializers ) {
261+ this . #serializers[ key ] = serializers [ key ] ;
262+ }
263+
243264 this . #setLogMethods( ) ;
244265 }
245266
@@ -283,9 +304,30 @@ class Logger {
283304 bindings ,
284305 ) ;
285306
307+ // Handle serializers inheritance
308+ let childSerializers ;
309+ if ( options . serializers ) {
310+ validateObject ( options . serializers , 'options.serializers' ) ;
311+
312+ // Create new serializers object
313+ childSerializers = { __proto__ : null } ;
314+
315+ // Copy parent serializers
316+ for ( const key in this . #serializers) {
317+ childSerializers [ key ] = this . #serializers[ key ] ;
318+ }
319+
320+ // Override with child serializers
321+ for ( const key in options . serializers ) {
322+ validateFunction ( options . serializers [ key ] , `options.serializers.${ key } ` ) ;
323+ childSerializers [ key ] = options . serializers [ key ] ;
324+ }
325+ }
326+
286327 const childLogger = new Logger ( {
287328 level : options . level || this . #level,
288329 bindings : mergedBindings ,
330+ serializers : childSerializers || this . #serializers,
289331 } ) ;
290332
291333 return childLogger ;
@@ -298,7 +340,32 @@ class Logger {
298340 * @private
299341 */
300342 #isError( value ) {
301- return Error . isError ( value ) ;
343+ return ErrorIsError ( value ) ;
344+ }
345+
346+ /**
347+ * Apply serializers to an object's properties
348+ * @param {object } obj - Object to serialize
349+ * @returns {object } Serialized object
350+ * @private
351+ */
352+ #applySerializers( obj ) {
353+ if ( ! obj || typeof obj !== 'object' ) {
354+ return obj ;
355+ }
356+
357+ const serialized = { __proto__ : null } ;
358+ const serializers = this . #serializers;
359+
360+ for ( const key in obj ) {
361+ const value = obj [ key ] ;
362+ // Apply serializer if exists for this key
363+ serialized [ key ] = serializers [ key ] ?
364+ serializers [ key ] ( value ) :
365+ value ;
366+ }
367+
368+ return serialized ;
302369 }
303370
304371 /**
@@ -332,24 +399,44 @@ class Logger {
332399
333400 if ( this . #isError( msgOrObj ) ) {
334401 msg = msgOrObj . message ;
402+ // Use err serializer for Error objects
403+ const serializedErr = this . #serializers. err ?
404+ this . #serializers. err ( msgOrObj ) :
405+ this . #serializeError( msgOrObj ) ;
406+
335407 logFields = {
336- err : this . #serializeError( msgOrObj ) ,
337- ...fields ,
408+ err : serializedErr ,
338409 } ;
410+
411+ // Apply serializers to additional fields
412+ if ( fields ) {
413+ const serializedFields = this . #applySerializers( fields ) ;
414+ for ( const key in serializedFields ) {
415+ logFields [ key ] = serializedFields [ key ] ;
416+ }
417+ }
339418 } else if ( typeof msgOrObj === 'string' ) {
340419 msg = msgOrObj ;
341- logFields = fields ?? kEmptyObject ;
420+ // Apply serializers to fields
421+ logFields = fields ? this . #applySerializers( fields ) : kEmptyObject ;
342422 } else {
343423 const { msg : extractedMsg , ...restFields } = msgOrObj ;
344424 msg = extractedMsg ;
345- logFields = restFields ;
346425
347- if ( logFields . err && this . #isError( logFields . err ) ) {
348- logFields . err = this . #serializeError( logFields . err ) ;
426+ // Apply serializers to object fields
427+ logFields = this . #applySerializers( restFields ) ;
428+
429+ // Special handling for err/error fields
430+ if ( logFields . err && this . #isError( restFields . err ) ) {
431+ logFields . err = this . #serializers. err ?
432+ this . #serializers. err ( restFields . err ) :
433+ this . #serializeError( restFields . err ) ;
349434 }
350435
351- if ( logFields . error && this . #isError( logFields . error ) ) {
352- logFields . error = this . #serializeError( logFields . error ) ;
436+ if ( logFields . error && this . #isError( restFields . error ) ) {
437+ logFields . error = this . #serializers. err ?
438+ this . #serializers. err ( restFields . error ) :
439+ this . #serializeError( restFields . error ) ;
353440 }
354441 }
355442
@@ -446,6 +533,7 @@ module.exports = {
446533 LEVELS ,
447534 channels,
448535 createLogger,
536+ stdSerializers,
449537 Handler : LogConsumer ,
450538 JSONHandler : JSONConsumer ,
451539} ;
0 commit comments