UNPKG

koa2-winston

Version:

koa2 version winston logger like express-winston

131 lines (118 loc) 3.69 kB
/* eslint no-param-reassign: 0 */ const winston = require('winston'); const onFinished = require('on-finished'); const { format } = require('util'); const { generateSchema, generateFormat, defaultSchemas, } = require('./stringify_schema'); const { createLogger, format: { combine: wfcombine, printf: wfprintf }, } = winston; const C = { INFO: 'info', WARN: 'warn', ERROR: 'error', MSG: 'HTTP %s %s', }; const getLogLevel = (statusCode = 200, defaultLevel = C.INFO) => { switch (Math.floor(statusCode / 100)) { case 5: return C.ERROR; case 4: return C.WARN; default: return defaultLevel; } }; /** * logger middleware for koa2 use winston * * @param {object} [payload={}] - input arguments * @param {object[]} [payload.transports=[new winston.transports.Stream({ stream: process.stdout })]] customize transports * @param {string} [payload.level='info'] - default log level of logger * @param {string} [payload.reqKeys=['header','url','method','httpVersion', 'href', 'query', 'length']] - default request fields to be logged * @param {string} [payload.reqSelect=[]] - additional request fields to be logged * @param {string} [payload.reqUnselect=['header.cookie']] - request field will be removed from the log * @param {string} [payload.resKeys=['header', 'status']] - default response fields to be logged * @param {string} [payload.resSelect=[]] - additional response fields to be logged * @param {string} [payload.resUnselect=[]] - response field will be removed from the log * @param {winston.transports.StreamTransportInstance} [payload.logger] - customize winston logger * @param {string} [payload.msg=HTTP %s %s] - customize log msg * @return {function} logger middleware * @example * const { logger } = require('koa2-winston'); * app.use(logger()); * // request logger look like down here * // { * // "req": { * // "header": { * // "host": "127.0.0.1:59534", * // "accept-encoding": "gzip, deflate", * // "user-agent": "node-superagent/3.5.2", * // "connection": "close" * // }, * // "url": "/", * // "method": "GET", * // "href": "http://127.0.0.1:59534/", * // "query": {} * // }, * // "started_at": 1494486039864, * // "res": { * // "header": { * // "content-type": "text/plain; charset=utf-8", * // "content-length": "8" * // }, * // "status": 200 * // }, * // "duration": 26, * // "level": "info", * // "message": "HTTP GET /" * // } */ const logger = (payload = {}) => { const { transports = [new winston.transports.Stream({ stream: process.stdout })], level: defaultLevel = C.INFO, msg = C.MSG, } = payload; // @ts-ignore const stringifyFormat = generateFormat(payload); const winstonLogger = payload.logger || createLogger({ transports, format: wfcombine(wfprintf(stringifyFormat)), }); const onResponseFinished = (ctx, info) => { info.res = ctx.response; info.duration = Date.now() - info.started_at; info.level = getLogLevel(info.res.status, defaultLevel); // @ts-ignore winstonLogger.log(info); }; return async (ctx, next) => { const info = { req: ctx.request, started_at: Date.now() }; info.message = format(msg, info.req.method, info.req.url); let error; try { await next(); } catch (e) { // catch and throw it later error = e; } finally { onFinished(ctx.response, onResponseFinished.bind(null, ctx, info)); } if (error) { throw error; } }; }; module.exports = { logger, getLogLevel, generateSchema, generateFormat, defaultSchemas, };