UNPKG

fastify

Version:

Fast and low overhead web framework, for Node.js

257 lines (218 loc) 7.2 kB
<h1 align="center">Fastify</h1> ## Logging ### Enable logging Logging is disabled by default, and you can enable it by passing `{ logger: true }` or `{ logger: { level: 'info' } }` when you create a Fastify instance. Note that if the logger is disabled, it is impossible to enable it at runtime. We use [abstract-logging](https://www.npmjs.com/package/abstract-logging) for this purpose. As Fastify is focused on performance, it uses [pino](https://github.com/pinojs/pino) as its logger, with the default log level, when enabled, set to `'info'`. Enabling the production JSON logger: ```js const fastify = require('fastify')({ logger: true }) ``` Enabling the logger with appropriate configuration for both local development and production and test environment requires a bit more configuration: ```js const envToLogger = { development: { transport: { target: 'pino-pretty', options: { translateTime: 'HH:MM:ss Z', ignore: 'pid,hostname', }, }, }, production: true, test: false, } const fastify = require('fastify')({ logger: envToLogger[environment] ?? true // defaults to true if no entry matches in the map }) ``` ⚠️ `pino-pretty` needs to be installed as a dev dependency, it is not included by default for performance reasons. ### Usage You can use the logger like this in your route handlers: ```js fastify.get('/', options, function (request, reply) { request.log.info('Some info about the current request') reply.send({ hello: 'world' }) }) ``` You can trigger new logs outside route handlers by using the Pino instance from the Fastify instance: ```js fastify.log.info('Something important happened!'); ``` If you want to pass some options to the logger, just pass them to Fastify. You can find all available options in the [Pino documentation](https://github.com/pinojs/pino/blob/master/docs/api.md#options). If you want to specify a file destination, use: ```js const fastify = require('fastify')({ logger: { level: 'info', file: '/path/to/file' // Will use pino.destination() } }) fastify.get('/', options, function (request, reply) { request.log.info('Some info about the current request') reply.send({ hello: 'world' }) }) ``` If you want to pass a custom stream to the Pino instance, just add a stream field to the logger object. ```js const split = require('split2') const stream = split(JSON.parse) const fastify = require('fastify')({ logger: { level: 'info', stream: stream } }) ``` <a id="logging-request-id"></a> By default, Fastify adds an ID to every request for easier tracking. If the "request-id" header is present its value is used, otherwise a new incremental ID is generated. See Fastify Factory [`requestIdHeader`](./Server.md#factory-request-id-header) and Fastify Factory [`genReqId`](./Server.md#genreqid) for customization options. The default logger is configured with a set of standard serializers that serialize objects with `req`, `res`, and `err` properties. The object received by `req` is the Fastify [`Request`](./Request.md) object, while the object received by `res` is the Fastify [`Reply`](./Reply.md) object. This behavior can be customized by specifying custom serializers. ```js const fastify = require('fastify')({ logger: { serializers: { req (request) { return { url: request.url } } } } }) ``` For example, the response payload and headers could be logged using the approach below (even if it is *not recommended*): ```js const fastify = require('fastify')({ logger: { transport: { target: 'pino-pretty' }, serializers: { res (reply) { // The default return { statusCode: reply.statusCode } }, req (request) { return { method: request.method, url: request.url, path: request.routerPath, parameters: request.params, // Including the headers in the log could be in violation // of privacy laws, e.g. GDPR. You should use the "redact" option to // remove sensitive fields. It could also leak authentication data in // the logs. headers: request.headers }; } } } }); ``` **Note**: In certain cases, the [`Reply`](./Reply.md) object passed to the `res` serializer cannot be fully constructed. When writing a custom `res` serializer, it is necessary to check for the existence of any properties on `reply` aside from `statusCode`, which is always present. For example, the existence of `getHeaders` must be verified before it can be called: ```js const fastify = require('fastify')({ logger: { transport: { target: 'pino-pretty' }, serializers: { res (reply) { // The default return { statusCode: reply.statusCode headers: typeof reply.getHeaders === 'function' ? reply.getHeaders() : {} } }, } } }); ``` **Note**: The body cannot be serialized inside a `req` method because the request is serialized when we create the child logger. At that time, the body is not yet parsed. See an approach to log `req.body` ```js app.addHook('preHandler', function (req, reply, done) { if (req.body) { req.log.info({ body: req.body }, 'parsed body') } done() }) ``` **Note**: Care should be taken to ensure serializers never throw, as an error thrown from a serializer has the potential to cause the Node process to exit. See the [Pino documentation](https://getpino.io/#/docs/api?id=opt-serializers) on serializers for more information. *Any logger other than Pino will ignore this option.* You can also supply your own logger instance. Instead of passing configuration options, pass the instance. The logger you supply must conform to the Pino interface; that is, it must have the following methods: `info`, `error`, `debug`, `fatal`, `warn`, `trace`, `silent`, `child` and a string property `level`. Example: ```js const log = require('pino')({ level: 'info' }) const fastify = require('fastify')({ logger: log }) log.info('does not have request information') fastify.get('/', function (request, reply) { request.log.info('includes request information, but is the same logger instance as `log`') reply.send({ hello: 'world' }) }) ``` *The logger instance for the current request is available in every part of the [lifecycle](./Lifecycle.md).* ## Log Redaction [Pino](https://getpino.io) supports low-overhead log redaction for obscuring values of specific properties in recorded logs. As an example, we might want to log all the HTTP headers minus the `Authorization` header for security concerns: ```js const fastify = Fastify({ logger: { stream: stream, redact: ['req.headers.authorization'], level: 'info', serializers: { req (request) { return { method: request.method, url: request.url, headers: request.headers, hostname: request.hostname, remoteAddress: request.ip, remotePort: request.socket.remotePort } } } } }) ``` See https://getpino.io/#/docs/redaction for more details.