pino-http
Version:
High-speed HTTP logger for Node.js
242 lines (184 loc) • 6.12 kB
Markdown
# pino-http [](https://travis-ci.org/pinojs/pino-http)[](https://coveralls.io/github/pinojs/pino-http?branch=master)
High-speed HTTP logger for Node.js
To our knowledge, `pino-http` is the [fastest](#benchmarks) HTTP logger in town.
* [Installation](#install)
* [Usage](#usage)
* [Benchmarks](#benchmarks)
* [API](#api)
* [Team](#team)
* [Acknowledgements](#acknowledgements)
* [License](#license)
## Benchmarks
Benchmarks log each request/response pair while returning
`'hello world'`, using
[autocannon](https://github.com/mcollina/autocannon) with 100
connections and 10 pipelined requests.
* `http-ndjson` (equivalent info): 7730.73 req/sec
* `http-ndjson` (standard minimum info): 9522.37 req/sec
* `pino-http`: 21496 req/sec
* `pino-http` (extreme): 25770.91 req/sec
* no logger: 46139.64 req/sec
All benchmarks where taken on a Macbook Pro 2013 (2.6GHZ i7, 16GB of RAM).
## Install
```
npm i pino-http --save
```
## Example
```js
'use strict'
var http = require('http')
var server = http.createServer(handle)
var logger = require('pino-http')()
function handle (req, res) {
logger(req, res)
req.log.info('something else')
res.end('hello world')
}
server.listen(3000)
```
```
$ node example.js | pino
[2016-03-31T16:53:21.079Z] INFO (46316 on MBP-di-Matteo): something else
req: {
"id": 1,
"method": "GET",
"url": "/",
"headers": {
"host": "localhost:3000",
"user-agent": "curl/7.43.0",
"accept": "*/*"
},
"remoteAddress": "::1",
"remotePort": 64386
}
[2016-03-31T16:53:21.087Z] INFO (46316 on MBP-di-Matteo): request completed
res: {
"statusCode": 200,
"header": "HTTP/1.1 200 OK\r\nX-Powered-By: restify\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: 11\r\nETag: W/\"b-XrY7u+Ae7tCTyyK7j1rNww\"\r\nDate: Thu, 31 Mar 2016 16:53:21 GMT\r\nConnection: keep-alive\r\n\r\n"
}
responseTime: 10
req: {
"id": 1,
"method": "GET",
"url": "/",
"headers": {
"host": "localhost:3000",
"user-agent": "curl/7.43.0",
"accept": "*/*"
},
"remoteAddress": "::1",
"remotePort": 64386
}
```
## API
### pinoHttp([opts], [stream])
`opts`: it has all the options as [pino](http://npm.im/pino) and
* `logger`: `pino-http` can reuse a pino instance if passed with the `logger` property
* `genReqId`: you can pass a function which gets used to generate a request id. The first argument is the request itself. As fallback `pino-http` is just using an integer. This default might not be the desired behavior if you're running multiple instances of the app
* `useLevel`: the logger level `pino-http` is using to log out the response. default: `info`
* `stream`: same as the second parameter
`stream`: the destination stream. Could be passed in as an option too.
#### Examples
##### Logger options
```js
'use strict'
var http = require('http')
var server = http.createServer(handle)
var pino = require('pino')()
var logger = require('pino-http')({
// Reuse an existing logger instance
logger: pino,
// Define a custom request id function
genReqId: function (req) { return req.id },
// Define custom serializers
serializers: {
req: pino.stdSerializers.req,
res: pino.stdSerializers.res
},
// Logger level is `info` by default
useLevel: 'info'
})
function handle (req, res) {
logger(req, res)
req.log.info('something else')
res.end('hello world')
}
server.listen(3000)
```
##### pinoHttp.startTime (Symbol)
The `pinoHttp` function has a property called `startTime` which contains a symbol
that is used to attach and reference a start time on the HTTP `res` object. If the function
returned from `pinoHttp` is not *the first* function to be called in an HTTP servers request
listener function then the `responseTime` key in the log output will be offset by any
processing that happens before a response is logged. This can be corrected by manually attaching
the start time to the `res` object with the `pinoHttp.startTime` symbol, like so:
```js
var http = require('http')
var logger = require('pino-http')()
var someImportantThingThatHasToBeFirst = require('some-important-thing')
http.createServer((req, res) => {
res[logger.startTime] = Date.now()
someImportantThingThatHasToBeFirst(req, res)
logger(req, res)
res.end('hello world')
}).listen(3000)
```
#### Default serializers
##### pinoHttp.stdSerializers.req
Generates a JSONifiable object from the HTTP `request` object passed to
the `createServer` callback of Node's HTTP server.
It returns an object in the form:
```js
{
pid: 93535,
hostname: 'your host',
level: 30,
msg: 'my request',
time: '2016-03-07T12:21:48.766Z',
v: 0,
req: {
id: 42,
method: 'GET',
url: '/',
headers: {
host: 'localhost:50201',
connection: 'close'
},
remoteAddress: '::ffff:127.0.0.1',
remotePort: 50202
}
}
```
##### pinoHttp.stdSerializers.res
Generates a JSONifiable object from the HTTP `response` object passed to
the `createServer` callback of Node's HTTP server.
It returns an object in the form:
```js
{
pid: 93581,
hostname: 'myhost',
level: 30,
msg: 'my response',
time: '2016-03-07T12:23:18.041Z',
v: 0,
res: {
statusCode: 200,
header: 'HTTP/1.1 200 OK\r\nDate: Mon, 07 Mar 2016 12:23:18 GMT\r\nConnection: close\r\nContent-Length: 5\r\n\r\n'
}
}
```
## Team
### Matteo Collina
<https://github.com/mcollina>
<https://www.npmjs.com/~matteo.collina>
<https://twitter.com/matteocollina>
### David Mark Clements
<https://github.com/davidmarkclements>
<https://www.npmjs.com/~davidmarkclements>
<https://twitter.com/davidmarkclem>
<a name="acknowledgements"></a>
## Acknowledgements
This project was kindly sponsored by [nearForm](http://nearform.com).
Logo and identity designed by Beibhinn Murphy O'Brien: https://www.behance.net/BeibhinnMurphyOBrien.
## License
MIT