/**
 * A basic append-only file logger.
 */ import { ILogger } from 'polar-shared/src/logger/ILogger' ; import { Files } from 'polar-shared/src/util/Files' ; import * as util from 'util' ; export class FileLogger implements ILogger { public readonly name : string ; private path : string ; private fd : number ; constructor ( path , fd ) { this . path = path ; this . fd = fd ; this . name = 'file-logger:' + path ; } public notice ( msg , ... args ) { this . append ( 'notice' , msg , ... args ) ; } public debug ( msg , ... args ) { this . append ( 'debug' , msg , ... args ) ; } public error ( msg , ... args ) { this . append ( 'error' , msg , ... args ) ; } public info ( msg , ... args ) { this . append ( 'info' , msg , ... args ) ; } public verbose ( msg , ... args ) { this . append ( 'verbose' , msg , ... args ) ; } public warn ( msg , ... args ) { this . append ( 'warn' , msg , ... args ) ; } public async sync ( ) { return Files . fsyncAsync ( this . fd ) ; } public async close ( ) { await Files . closeAsync ( this . fd ) ; } private append ( level , msg , ... args ) { const line = FileLogger . format ( level , msg , ... args ) ; Files . appendFileAsync ( this . fd , line ) . catch ( ( err ) => console . error ( "Could not write to file logger: " , err ) ) ; } public static async create ( path ) { const fd = await Files . openAsync ( path , 'a' ) ; return new FileLogger ( path , fd ) ; } protected static format ( level , msg , ... args ) { const timestamp = new Date ( ) . toISOString ( ) ; let line = `[${ timestamp }] [${ level }] ${ msg }` ; if ( args . length > 0 ) { args . forEach ( arg => { if ( ! line . endsWith ( ' ' ) ) { line += ' ' ; } if ( arg instanceof Error ) { const err = arg ; line += '\n' + err . stack ; } else if ( typeof arg === 'string' || typeof arg === 'boolean' || typeof arg === 'number' ) { line += arg . toString ( ) ; } else { line += util . inspect ( arg , false , undefined , false ) ; } } ) ; } line += '\n' ; return line ; } }