@@ -431,4 +431,97 @@ describe('createLogger', () => {
431431 expect ( logOutput ) . not . toContain ( 'nodeHostname=' )
432432 } )
433433 } )
434+
435+ describe ( 'BUILD_SHA in production logs' , ( ) => {
436+ it ( 'should include build_sha in logfmt output when BUILD_SHA env var is set' , async ( ) => {
437+ vi . stubEnv ( 'BUILD_SHA' , 'abc123def456' )
438+ vi . stubEnv ( 'LOG_LIKE_PRODUCTION' , 'true' )
439+
440+ vi . resetModules ( )
441+ const { createLogger : freshCreateLogger } = await import ( '@/observability/logger' )
442+
443+ const logger = freshCreateLogger ( 'file:///path/to/test.js' )
444+ logger . info ( 'Build SHA test' )
445+
446+ expect ( consoleLogs ) . toHaveLength ( 1 )
447+ const logOutput = consoleLogs [ 0 ]
448+ expect ( logOutput ) . toContain ( 'build_sha=abc123def456' )
449+ } )
450+
451+ it ( 'should not include build_sha in logfmt output when BUILD_SHA env var is absent' , async ( ) => {
452+ vi . stubEnv ( 'LOG_LIKE_PRODUCTION' , 'true' )
453+ delete process . env . BUILD_SHA
454+
455+ vi . resetModules ( )
456+ const { createLogger : freshCreateLogger } = await import ( '@/observability/logger' )
457+
458+ const logger = freshCreateLogger ( 'file:///path/to/test.js' )
459+ logger . info ( 'No build SHA test' )
460+
461+ expect ( consoleLogs ) . toHaveLength ( 1 )
462+ const logOutput = consoleLogs [ 0 ]
463+ expect ( logOutput ) . not . toContain ( 'build_sha=' )
464+ } )
465+ } )
466+
467+ describe ( 'error serialization in production logs' , ( ) => {
468+ it ( 'should include error_code and error_name when Error has a .code property' , async ( ) => {
469+ vi . stubEnv ( 'LOG_LIKE_PRODUCTION' , 'true' )
470+
471+ vi . resetModules ( )
472+ const { createLogger : freshCreateLogger } = await import ( '@/observability/logger' )
473+
474+ const logger = freshCreateLogger ( 'file:///path/to/test.js' )
475+ const error = new Error ( 'Connection reset' ) as NodeJS . ErrnoException
476+ error . code = 'ECONNRESET'
477+ logger . error ( 'Network failure' , error )
478+
479+ expect ( consoleLogs ) . toHaveLength ( 1 )
480+ const logOutput = consoleLogs [ 0 ]
481+ expect ( logOutput ) . toContain ( 'included.error="Connection reset"' )
482+ expect ( logOutput ) . toContain ( 'included.error_code=ECONNRESET' )
483+ expect ( logOutput ) . toContain ( 'included.error_name=Error' )
484+ expect ( logOutput ) . toContain ( 'included.error_stack=' )
485+ } )
486+
487+ it ( 'should include error_name even when .code is undefined' , async ( ) => {
488+ vi . stubEnv ( 'LOG_LIKE_PRODUCTION' , 'true' )
489+
490+ vi . resetModules ( )
491+ const { createLogger : freshCreateLogger } = await import ( '@/observability/logger' )
492+
493+ const logger = freshCreateLogger ( 'file:///path/to/test.js' )
494+ const error = new TypeError ( 'Cannot read property' )
495+ logger . error ( 'Type error occurred' , error )
496+
497+ expect ( consoleLogs ) . toHaveLength ( 1 )
498+ const logOutput = consoleLogs [ 0 ]
499+ expect ( logOutput ) . toContain ( 'included.error="Cannot read property"' )
500+ expect ( logOutput ) . toContain ( 'included.error_name=TypeError' )
501+ // When .code is undefined, error_code is present but empty
502+ expect ( logOutput ) . toMatch ( / i n c l u d e d \. e r r o r _ c o d e = / )
503+ expect ( logOutput ) . toContain ( 'included.error_stack=' )
504+ } )
505+
506+ it ( 'should serialize multiple errors with indexed keys' , async ( ) => {
507+ vi . stubEnv ( 'LOG_LIKE_PRODUCTION' , 'true' )
508+
509+ vi . resetModules ( )
510+ const { createLogger : freshCreateLogger } = await import ( '@/observability/logger' )
511+
512+ const logger = freshCreateLogger ( 'file:///path/to/test.js' )
513+ const error1 = new Error ( 'First' ) as NodeJS . ErrnoException
514+ error1 . code = 'ERR_FIRST'
515+ const error2 = new Error ( 'Second' )
516+ logger . error ( 'Multiple errors' , error1 , error2 )
517+
518+ expect ( consoleLogs ) . toHaveLength ( 1 )
519+ const logOutput = consoleLogs [ 0 ]
520+ expect ( logOutput ) . toContain ( 'included.error_1=First' )
521+ expect ( logOutput ) . toContain ( 'included.error_1_code=ERR_FIRST' )
522+ expect ( logOutput ) . toContain ( 'included.error_1_name=Error' )
523+ expect ( logOutput ) . toContain ( 'included.error_2=Second' )
524+ expect ( logOutput ) . toContain ( 'included.error_2_name=Error' )
525+ } )
526+ } )
434527} )
0 commit comments