Skip to content

yidinghan/koa2-winston

Repository files navigation

koa2-winston

GitHub Action npm npm npm node

koa2 version winston logger like express-winston

Add logger to your koa2 server in 3 lines

中文介绍

Usage

Installation

npm i --save koa2-winston

Quick Start

const { logger } = require('koa2-winston');
app.use(logger());

request log will look like

{
  "req": {
    "header": {
      "host": "localhost:3000",
      "connection": "keep-alive",
      "upgrade-insecure-requests": "1",
      "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36",
      "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
      "dnt": "1",
      "accept-encoding": "gzip, deflate, sdch, br",
      "accept-language": "zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4,de;q=0.2,ja;q=0.2,it;q=0.2"
    },
    "url": "/hello",
    "method": "GET",
    "href": "http://localhost:3000/hello",
    "query": {}
  },
  "started_at": 1494554053492,
  "res": {
    "header": {
      "content-type": "application/json; charset=utf-8",
      "content-length": "16"
    },
    "status": 200
  },
  "duration": 8,
  "level": "info",
  "message": "HTTP GET /hello"
}

Configuration

Each parameter has a default value, and you can customize your logger by changing the configuration

app.use(
  logger({
    transports: new winston.transports.Console({ json: true, stringify: true }),
    level: 'info',
    reqKeys: [
      'header',
      'url',
      'method',
      'httpVersion',
      'href',
      'query',
      'length',
    ],
    reqSelect: [],
    reqUnselect: ['header.cookie'],
    resKeys: ['header', 'status'],
    resSelect: [],
    resUnselect: [],
  })
);

Many configuration explain can be found in logger

Examples

Do not record any request fields

app.use(
  logger({
    reqKeys: [],
  })
);

The req object will be empty

{
  "req": {},
  "started_at": 1494486039864,
  "res": {
    "header": {
      "content-type": "text/plain; charset=utf-8",
      "content-length": "8"
    },
    "status": 200
  },
  "duration": 26,
  "level": "info",
  "message": "HTTP GET /"
}

Do not record any response fields

app.use(
  logger({
    resKeys: [],
  })
);

The res object will be empty

{
  "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": {},
  "duration": 26,
  "level": "info",
  "message": "HTTP GET /"
}

Do not record UA

app.use(
  logger({
    reqUnselect: ['header.cookie', 'header.user-agent'],
  })
);

The UA of request will be ignored

{
  "req": {
    "header": {
      "host": "127.0.0.1:59534",
      "accept-encoding": "gzip, deflate",
      "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 /"
}

Record a response body filed

app.use(
  logger({
    resSelect: ['body.success'],
  })
);

The success field on body will be recorded

{
  "req": {
    "header": {
      "host": "127.0.0.1:59534",
      "accept-encoding": "gzip, deflate",
      "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,
    "body": {
      // Any possible value given by the server
      "success": false
    }
  },
  "duration": 26,
  "level": "info",
  "message": "HTTP GET /"
}

Simple Benchmark

At node 8.2

middleware x 90,281 ops/sec ±7.89% (13 runs sampled)

At node 8.4

middleware x 112,011 ops/sec ±10.26% (18 runs sampled)

Schema Stringify

With fast-json-stringify support, default transport logger is much faster

total ops/sec { jsonstringify: 73544 }
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
total ops/sec { schemastringify: 90223 }
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

schemastringify is 1.23x faster then jsonstringify in this case

v1.7.1 vs v2.4.0

total ops/sec { 'v1.7.1': 111416 }
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
total ops/sec { 'v2.4.0': 131234 }
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

v2.4.0 is 1.18x faster then v1.7.1 in this case

Math.floor vs parseInt

Related commit in HERE

JSPerf link in HERE

Testing in Chrome 70.0.3505 / Mac OS X 10.13.5

parseInt(401 / 100, 10) { 160,092,130 Ops/sec }
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
Math.floor(401 / 100) { 810,032,369 Ops/sec }
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

Math.floor is 5.06x faster then parseInt in this case

v3

Finally, winston v3 support. But winston will install as dependencies not peerDependencies.

With better backward compatibility, users don't have to worry about the new version of koa2-winston will conflict with other winston usage in the project.

v3.1

The fastest koa2-winston ever. Nearly 3x faster than previous versions.

total ops/sec { 'v3.0.2': 180020 }
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
total ops/sec { 'v3.1.0': 541854 }
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

The above statistics come from npm run bench.

Biggest change

  • Remove key recorder
  • Generate json-schema for fast-json-stringify, not only for object serialization (log message), but also as key selector.
  • Log info object key rename.
    - {req,res}.headers
    + {req,res}.header

JSDoc

Table of Contents

logger

logger middleware for koa2 use winston

Parameters

  • payload object input arguments (optional, default {})
    • payload.transports Array<object> customize transports (optional, default [newwinston.transports.Stream({stream:process.stdout})])
    • payload.level string default log level of logger (optional, default 'info')
    • payload.reqKeys string default request fields to be logged (optional, default ['header','url','method','httpVersion','href','query','length'])
    • payload.reqSelect string additional request fields to be logged (optional, default [])
    • payload.reqUnselect string request field will be removed from the log (optional, default ['header.cookie'])
    • payload.resKeys string default response fields to be logged (optional, default ['header','status'])
    • payload.resSelect string additional response fields to be logged (optional, default [])
    • payload.resUnselect string response field will be removed from the log (optional, default [])
    • payload.logger winston.transports.StreamTransportInstance? customize winston logger
    • payload.msg string customize log msg (optional, default HTTP%s%s)

Examples

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 /"
// }

Returns function logger middleware

asJsonSchemaPath

Parameters

ensureTypeObject

Parameters

  • schema object generated json schema

schemaKeysHandlerFn

Type: Function

Parameters

schemaKeysHandler

Parameters

generateSchema

logger middleware for koa2 use winston

Parameters

  • payload object input arguments (optional, default {})
    • payload.reqKeys Array<string> default request fields to be logged (optional, default ['header','url','method','httpVersion','href','query','length'])
    • payload.reqSelect Array<string> additional request fields to be logged (optional, default [])
    • payload.reqUnselect Array<string> request field will be removed from the log (optional, default ['header.cookie'])
    • payload.resKeys Array<string> default response fields to be logged (optional, default ['header','status'])
    • payload.resSelect Array<string> additional response fields to be logged (optional, default [])
    • payload.resUnselect Array<string> response field will be removed from the log (optional, default [])