strong-tie/inbound-calls
0
1<h1 align="center">Fastify</h1>2 3## Logging4 5### Enable logging6Logging is disabled by default, and you can enable it by passing `{ logger: true7}` or `{ logger: { level: 'info' } }` when you create a Fastify instance. Note8that if the logger is disabled, it is impossible to enable it at runtime. We use9[abstract-logging](https://www.npmjs.com/package/abstract-logging) for this10purpose.11 12As Fastify is focused on performance, it uses13[pino](https://github.com/pinojs/pino) as its logger, with the default log14level, when enabled, set to `'info'`.15 16Enabling the production JSON logger:17 18```js19const fastify = require('fastify')({20 logger: true21})22```23 24Enabling the logger with appropriate configuration for both local development25and production and test environment requires a bit more configuration:26 27```js28const envToLogger = {29 development: {30 transport: {31 target: 'pino-pretty',32 options: {33 translateTime: 'HH:MM:ss Z',34 ignore: 'pid,hostname',35 },36 },37 },38 production: true,39 test: false,40}41const fastify = require('fastify')({42 logger: envToLogger[environment] ?? true // defaults to true if no entry matches in the map43})44```45⚠️ `pino-pretty` needs to be installed as a dev dependency, it is not included46by default for performance reasons.47 48### Usage49You can use the logger like this in your route handlers:50 51```js52fastify.get('/', options, function (request, reply) {53 request.log.info('Some info about the current request')54 reply.send({ hello: 'world' })55})56```57 58You can trigger new logs outside route handlers by using the Pino instance from59the Fastify instance:60```js61fastify.log.info('Something important happened!');62```63 64If you want to pass some options to the logger, just pass them to Fastify.65You can find all available options in the66[Pino documentation](https://github.com/pinojs/pino/blob/master/docs/api.md#options).67If you want to specify a file destination, use:68 69```js70const fastify = require('fastify')({71 logger: {72 level: 'info',73 file: '/path/to/file' // Will use pino.destination()74 }75})76 77fastify.get('/', options, function (request, reply) {78 request.log.info('Some info about the current request')79 reply.send({ hello: 'world' })80})81```82 83If you want to pass a custom stream to the Pino instance, just add a stream84field to the logger object.85 86```js87const split = require('split2')88const stream = split(JSON.parse)89 90const fastify = require('fastify')({91 logger: {92 level: 'info',93 stream: stream94 }95})96```97 98<a id="logging-request-id"></a>99 100By default, Fastify adds an ID to every request for easier tracking. If the101requestIdHeader-option is set and the corresponding header is present than102its value is used, otherwise a new incremental ID is generated. See Fastify103Factory [`requestIdHeader`](./Server.md#factory-request-id-header) and Fastify104Factory [`genReqId`](./Server.md#genreqid) for customization options.105 106The default logger is configured with a set of standard serializers that107serialize objects with `req`, `res`, and `err` properties. The object received108by `req` is the Fastify [`Request`](./Request.md) object, while the object109received by `res` is the Fastify [`Reply`](./Reply.md) object. This behavior110can be customized by specifying custom serializers.111 112```js113const fastify = require('fastify')({114 logger: {115 serializers: {116 req (request) {117 return { url: request.url }118 }119 }120 }121})122```123For example, the response payload and headers could be logged using the approach124below (even if it is *not recommended*):125 126```js127const fastify = require('fastify')({128 logger: {129 transport: {130 target: 'pino-pretty'131 },132 serializers: {133 res (reply) {134 // The default135 return {136 statusCode: reply.statusCode137 }138 },139 req (request) {140 return {141 method: request.method,142 url: request.url,143 path: request.routeOptions.url,144 parameters: request.params,145 // Including the headers in the log could be in violation146 // of privacy laws, e.g. GDPR. You should use the "redact" option to147 // remove sensitive fields. It could also leak authentication data in148 // the logs.149 headers: request.headers150 };151 }152 }153 }154});155```156 157**Note**: In certain cases, the [`Reply`](./Reply.md) object passed to the `res`158serializer cannot be fully constructed. When writing a custom `res` serializer,159it is necessary to check for the existence of any properties on `reply` aside160from `statusCode`, which is always present. For example, the existence of161`getHeaders` must be verified before it can be called:162 163```js164const fastify = require('fastify')({165 logger: {166 transport: {167 target: 'pino-pretty'168 },169 serializers: {170 res (reply) {171 // The default172 return {173 statusCode: reply.statusCode174 headers: typeof reply.getHeaders === 'function'175 ? reply.getHeaders()176 : {}177 }178 },179 }180 }181});182```183 184**Note**: The body cannot be serialized inside a `req` method because the185request is serialized when we create the child logger. At that time, the body is186not yet parsed.187 188See an approach to log `req.body`189 190```js191app.addHook('preHandler', function (req, reply, done) {192 if (req.body) {193 req.log.info({ body: req.body }, 'parsed body')194 }195 done()196})197```198 199**Note**: Care should be taken to ensure serializers never throw, as an error200thrown from a serializer has the potential to cause the Node process to exit.201See the [Pino documentation](https://getpino.io/#/docs/api?id=opt-serializers)202on serializers for more information.203 204*Any logger other than Pino will ignore this option.*205 206You can also supply your own logger instance. Instead of passing configuration207options, pass the instance as `loggerInstance`. The logger you supply must208conform to the Pino interface; that is, it must have the following methods:209`info`, `error`, `debug`, `fatal`, `warn`, `trace`, `silent`, `child` and a210string property `level`.211 212Example:213 214```js215const log = require('pino')({ level: 'info' })216const fastify = require('fastify')({ loggerInstance: log })217 218log.info('does not have request information')219 220fastify.get('/', function (request, reply) {221 request.log.info('includes request information, but is the same logger instance as `log`')222 reply.send({ hello: 'world' })223})224```225 226*The logger instance for the current request is available in every part of the227[lifecycle](./Lifecycle.md).*228 229## Log Redaction230 231[Pino](https://getpino.io) supports low-overhead log redaction for obscuring232values of specific properties in recorded logs. As an example, we might want to233log all the HTTP headers minus the `Authorization` header for security concerns:234 235```js236const fastify = Fastify({237 logger: {238 stream: stream,239 redact: ['req.headers.authorization'],240 level: 'info',241 serializers: {242 req (request) {243 return {244 method: request.method,245 url: request.url,246 headers: request.headers,247 host: request.host,248 remoteAddress: request.ip,249 remotePort: request.socket.remotePort250 }251 }252 }253 }254})255```256 257See https://getpino.io/#/docs/redaction for more details.258 