solive-winston-logger
Version:
handle logs for solive projects
104 lines (93 loc) • 2.83 kB
JavaScript
import winston from 'winston'
import _ from 'lodash'
import parse from './parse'
import { colors, levels } from './constants'
class Logger {
/**
* creates a loggger and initiates the socket client
* to send all the logs to a log-manager
*
* @param {Object} config
* @param {string} config.env - should be one of production|testing|development
* @param {Function} config.onNewLog - a function that's called on each log
* @param {Object} fields - all the fields that are needed to log
* like tag, action, name, error, ...
*/
constructor({ env, onNewLog }, fields = {}) {
this.logger = this.createLogger(env)
this.env = env
this.fields = { ...fields }
this.onNewLog = onNewLog
this.populateLogger()
}
/**
* Creates a winston logger based on the env
*
* @param {String} env - needed to set the logger level
* in production, we don't want to log everything like the trace
* or the debug should be omitted
* @returns {Object} An instance of a Winston logger
*/
createLogger = env => new (winston.Logger)({
colors,
levels,
transports: [
new (winston.transports.Console)({
timestamp: false,
colorize: env !== 'production',
prettyPrint: true,
level: env === 'production' ? 'info' : 'trace',
}),
],
})
/**
* Populates the logger with all the logging functions
* Once this function executes, this should includes
* the following methods: trace, debug, info, warn, error, fatal
*/
populateLogger = () => _.forEach(levels, (level, key) => {
this[key] = this.log(key)
})
/**
* Will parse then display the log on the stdout or stderr
* and send it via socket if the env is "production"
* It throws if a required field is not provided
*
* @param {String} key - one of trace|debug|info|warn|error|fatal
* @param {String} message - the message of the log
* @param {Object} fields - all the fields that are needed to log
* like tag, action, name, error, ...
*/
log = key => (message, fields = {}) => {
const log = {
message,
...this.fields,
...fields,
date: new Date(),
}
if (typeof fields !== typeof {}) {
const error = 'fields should be an object'
console.error(new Error(error))
return error
}
const err = parse(key, log)
if (err) {
console.error(new Error(err))
return err
}
this.logger.log.call(this.logger, key, message, _.omit(log, ['message']))
if (this.onNewLog) {
this.onNewLog(log)
}
}
/**
* Creates a new logger based on the previous on but with different fields
* @param {Object} fields - all the fields that are needed to log
* like tag, action, name, error, ...
*/
create = fields => new Logger(
{ env: this.env, onNewLog: this.onNewLog },
{ ...this.fields, ...fields },
)
}
export default ({ env, onNewLog }) => new Logger({ env, onNewLog })