Last active
June 5, 2021 15:36
-
-
Save nebarf/ccfd71cadd5545284b1f344109602e8f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { createWriteStream } = require('fs'); | |
const { join } = require('path'); | |
const { EOL } = require('os'); | |
const logLevels = { | |
off: -1, | |
debug: 0, | |
info: 1, | |
warn: 2, | |
error: 3, | |
}; | |
class ConsoleLogStrategy { | |
_logLevelToActionMap = { | |
[logLevels.debug]: 'debug', | |
[logLevels.info]: 'info', | |
[logLevels.warn]: 'warn', | |
[logLevels.error]: 'error' | |
}; | |
write(logLevel, ...args) { | |
const action = this._logLevelToActionMap[logLevel]; | |
console[action](...args); | |
} | |
} | |
class FileLogStrategy { | |
_logLevelToFileMap = { | |
[logLevels.debug]: 'debug.log', | |
[logLevels.info]: 'info.log', | |
[logLevels.warn]: 'warn.log', | |
[logLevels.error]: 'error.log' | |
}; | |
_streamsCache = {}; | |
constructor(logDir) { | |
this._logDir = logDir; | |
} | |
_getWriteStream(logLevel) { | |
const streamCacheKey = `stream_${logLevel}`; | |
if (!this._streamsCache[streamCacheKey]) { | |
const fileName = this._logLevelToFileMap[logLevel]; | |
const logPath = this._logDir ? join(this._logDir, fileName) : fileName; | |
const writeStream = createWriteStream(logPath, { | |
// Append mode | |
flags: 'a', | |
}); | |
this._streamsCache[streamCacheKey] = writeStream; | |
} | |
return this._streamsCache[streamCacheKey]; | |
} | |
_stringifyArgs(...args) { | |
return args.map((arg) => { | |
let stringifiedArg = arg; | |
if (typeof arg === 'object') { | |
return JSON.stringify(arg); | |
} | |
return stringifiedArg; | |
}); | |
} | |
write(logLevel, ...args) { | |
const stringifiedArgs = this._stringifyArgs(...args); | |
const writeStream = this._getWriteStream(logLevel); | |
const writeRes = writeStream.write(stringifiedArgs.join(' ') + EOL); | |
// Internal buffer is full, retry writing when it is drained. | |
if (!writeRes) { | |
writeStream.once('drain', this.write(logLevel, ...args)); | |
} | |
} | |
} | |
class Logger { | |
constructor(strategy, globalLevel) { | |
if (this._globalLevel < logLevels.off || this._globalLevel > logLevels.error) { | |
throw new Error('The provided log level is wrong.'); | |
} | |
this._strategy = strategy; | |
this._globalLevel = globalLevel || logLevels.debug; | |
} | |
_writeLog(logLevel, ...args) { | |
if (logLevel < this._globalLevel || this._globalLevel === logLevels.off) { | |
return; | |
} | |
this._strategy.write(logLevel, ...args); | |
} | |
debug(...args) { | |
this._writeLog(logLevels.debug, ...args); | |
} | |
info(...args) { | |
this._writeLog(logLevels.info, ...args); | |
} | |
warn(...args) { | |
this._writeLog(logLevels.warn, ...args); | |
} | |
error(...args) { | |
this._writeLog(logLevels.error, ...args); | |
} | |
} | |
const consoleLogger = new Logger(new ConsoleLogStrategy()); | |
const fileLogger = new Logger(new FileLogStrategy(), logLevels.info); | |
consoleLogger.debug('Debug log', { level: 'debug' }); | |
consoleLogger.info('Info log', { level: 'info' }); | |
consoleLogger.warn('Warn log', { level: 'warn' }); | |
consoleLogger.error('Error log', { level: 'error' }); | |
fileLogger.debug('Debug log', { level: 'debug' }); | |
fileLogger.info('Info log', { level: 'info' }); | |
fileLogger.warn('Warn log', { level: 'warn' }); | |
fileLogger.error('Error log', { level: 'error' }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment