Winston Logger
Hands-on example that shows how to capture logs with Winston in Node-based projects.
Project
Clone the sample project and run it to see the generated log files.
Download the repository.
git clone https://github.com/AlexQuispe/winston-logger-example.git
Enter the project directory.
cd winston-logger-example
Install the dependencies.
npm install
Run the script.
node index.js
30/04/2020 22:02:27 [info] Mensaje informativo 30/04/2020 22:02:27 [warn] Mensaje de advertencia 30/04/2020 22:02:27 [error] Mensaje de error 30/04/2020 22:02:27 [info] Mensaje con datos { user: 'John Smith' }
Result
Before running the script.
app
├─ logger.js
└─ index.js
After running the script.
app
├─ logs
│ ├─ info.log
│ ├─ warn.log
│ └─ error.log
├─ logger.js
└─ index.js
The resulting log files contain entries like the following:
logs/info.log
{"timestamp":"30/04/2020 22:02:27","level":"info","message":"Mensaje informativo","data":null}
{"timestamp":"30/04/2020 22:02:27","level":"warn","message":"Mensaje de advertencia","data":null}
{"timestamp":"30/04/2020 22:02:27","level":"error","message":"Mensaje de error","data":null}
{"timestamp":"30/04/2020 22:02:27","level":"info","message":"Mensaje con datos","data":"{ user: 'John Smith' }"}
logs/warn.log
{"timestamp":"30/04/2020 22:02:27","level":"warn","message":"Mensaje de advertencia","data":null}
{"timestamp":"30/04/2020 22:02:27","level":"error","message":"Mensaje de error","data":null}
logs/error.log
{"timestamp":"30/04/2020 22:02:27","level":"error","message":"Mensaje de error","data":null}
How it works
The project defines a Logger
class that bundles Winston's transports and formatting helpers.
index.js
const Logger = require('./logger')
const logger = new Logger()
logger.info('Mensaje informativo')
logger.warn('Mensaje de advertencia')
logger.error('Mensaje de error')
logger.info('Mensaje con datos', { user: 'John Smith' })
logger.js
const util = require('util')
const moment = require('moment')
const winston = require('winston')
class Logger {
constructor() { this.winstonLogger = winston.createLogger({ ... }) }
info(message, data) { this.winstonLogger.info({ message, data }) }
warn(message, data) { this.winstonLogger.warn({ message, data }) }
error(message, data) { this.winstonLogger.error({ message, data }) }
_createTransports() { ... }
_consoleFormat () { ... }
_fileFormat() { ... }
}
module.exports = Logger
[Fn] constructor
Creates the underlying Winston logger instance.
constructor() {
this.winstonLogger = winston.createLogger({
levels : { error: 1, warn: 2, info: 3 },
transports : this._createTransports(),
exitOnError : false,
})
}
[Fn] _createTransports
Configures the transports that will persist console and file logs.
_createTransports() {
const TRANSPORTS = []
TRANSPORTS.push(new winston.transports.Console({
format : winston.format.printf(this._consoleFormat()),
level : 'info', // Muestra logs de nivel 3 o menor
handleExceptions : false,
colorize : false,
json : false,
}))
Array.from(['info', 'warn', 'error']).forEach(level => {
TRANSPORTS.push(new winston.transports.File({
format : winston.format.printf(this._fileFormat()),
level : level,
handleExceptions : false,
colorize : false,
json : true,
filename : `logs/${level}.log`,
maxsize : 5242880, // 5242880 Bytes = 5 MB
maxFiles : 5,
}))
})
return TRANSPORTS
}
[Fn] _consoleFormat
Defines the console output format.
_consoleFormat () {
const COLORS = {
error : `\x1b[91m`, // LIGHT_RED
warn : `\x1b[93m`, // LIGHT_YELLOW
info : `\x1b[96m`, // LIGHT_CYAN
reset : `\x1b[0m`, // Restaura al color por defecto
}
return (info) => {
const START = COLORS[info.level]
const END = COLORS.reset
const TIMESTAMP = moment().format('DD/MM/YYYY HH:mm:ss')
const LEVEL = info.level
const MESSAGE = info.message
const DATA = info.data ? util.inspect(info.data, false, null) : ''
return `${START} ${TIMESTAMP} [${LEVEL}] ${MESSAGE} ${DATA} ${END}`
}
}
[Fn] _fileFormat
Defines the JSON structure stored in log files.
_fileFormat() {
return (info) => {
const TIMESTAMP = moment().format('DD/MM/YYYY HH:mm:ss')
const LEVEL = info.level
const MESSAGE = info.message
const DATA = info.data ? util.inspect(info.data, false, null) : null
return JSON.stringify({
timestamp : TIMESTAMP,
level : LEVEL,
message : MESSAGE,
data : DATA,
})
}
}
Log Levels
According to RFC5424—which Winston follows—log levels are identified numerically from most to least critical.
For example:
Severity | Level | Description | Optional color |
---|---|---|---|
fatal | 0 | Critical messages | \x1b[31m RED |
error | 1 | Error messages | \x1b[91m LIGHT_RED |
warn | 2 | Warning messages | \x1b[93m LIGHT_YELLOW |
notice | 3 | Notice-level information | \x1b[92m LIGHT_GREEN |
info | 4 | Informational messages | \x1b[97m LIGHT_WHITE |
verbose | 5 | Verbose messages | \x1b[96m LIGHT_CYAN |
debug | 6 | Debug output | \x1b[94m LIGHT_BLUE |
silly | 7 | Low-priority chatter | \x1b[95m LIGHT_MAGENTA |
See https://github.com/shiena/ansicolor for the full color reference.
References
Published: May 26, 2020