import * as winston from "winston" ; import { ActionheroConfigInterface } from "actionhero" ; const namespace = "logger" ; declare module "actionhero" { export interface ActionheroConfigInterface { [ namespace ] : ReturnType < typeof DEFAULT [ typeof namespace ] > ; } } type ActionheroConfigLoggerBuilderArray = Array < ( config : any ) => winston . Logger > ; export const DEFAULT = { [ namespace ] : ( config ) => { const loggers = [ ] ; loggers . push ( buildConsoleLogger ( process . env . LOG_LEVEL ) ) ; config . general . paths . log . forEach ( ( p ) => { loggers . push ( buildFileLogger ( p , process . env . LOG_LEVEL ) ) ; } ) ; return { loggers , maxLogStringLength : 100 , maxLogArrayLength : 10 , } ; } , } ; export const test = { [ namespace ] : ( config ) => { const loggers = [ ] ; loggers . push ( buildConsoleLogger ( process . env . LOG_LEVEL ?? "crit" ) ) ; config . general . paths . log . forEach ( ( path ) => { loggers . push ( buildFileLogger ( path , "debug" , 1 ) ) ; } ) ; return { loggers } ; } , } ; function buildConsoleLogger ( level = "info" ) { return function ( ) { return winston . createLogger ( { format : winston . format . combine ( winston . format . timestamp ( ) , winston . format . colorize ( ) , winston . format . printf ( ( info ) => { return `${ info . timestamp } - ${ info . level }: ${ info . message } ${ stringifyExtraMessagePropertiesForConsole ( info ) }` ; } ) ) , level , levels : winston . config . syslog . levels , transports : [ new winston . transports . Console ( ) ] , } ) ; } ; } function buildFileLogger ( path , level = "info" , maxFiles ? ) { return function ( config ) { const filename = `${ path }/${ config . process . id }-${ config . process . env }.log` ; return winston . createLogger ( { format : winston . format . combine ( winston . format . timestamp ( ) , winston . format . json ( ) ) , level , levels : winston . config . syslog . levels , transports : [ new winston . transports . File ( { filename , maxFiles , } ) , ] , } ) ; } ; } function stringifyExtraMessagePropertiesForConsole ( info ) { const skippedProperties = [ "message" , "timestamp" , "level" ] ; let response = "" ; for ( const key in info ) { const value = info [ key ] ; if ( skippedProperties . includes ( key ) ) { continue ; } if ( value === undefined || value === null || value === "" ) { continue ; } response += `${ key }=${ value } ` ; } return response ; }