1 | <h1 align="center">Fastify</h1>
|
2 |
|
3 | ## Logging
|
4 |
|
5 | Logging is disabled by default, and you can enable it by passing
|
6 | `{ logger: true }` or `{ logger: { level: 'info' } }` when you create
|
7 | a fastify instance. Note that if the logger is disabled, it is impossible to
|
8 | enable it at runtime. We use
|
9 | [abstract-logging](https://www.npmjs.com/package/abstract-logging) for
|
10 | this purpose.
|
11 |
|
12 | Since 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'`.
|
13 |
|
14 | Enabling the logger is extremely easy:
|
15 |
|
16 | ```js
|
17 | const fastify = require('fastify')({
|
18 | logger: true
|
19 | })
|
20 |
|
21 | fastify.get('/', options, function (request, reply) {
|
22 | request.log.info('Some info about the current request')
|
23 | reply.send({ hello: 'world' })
|
24 | })
|
25 | ```
|
26 |
|
27 | If you want to pass some options to the logger, just pass them to Fastify.
|
28 | You can find all available options in the [Pino documentation](https://github.com/pinojs/pino/blob/master/docs/api.md#pinooptions-stream). If you want to specify a file destination, use:
|
29 |
|
30 | ```js
|
31 | const fastify = require('fastify')({
|
32 | logger: {
|
33 | level: 'info',
|
34 | file: '/path/to/file' // Will use pino.destination()
|
35 | }
|
36 | })
|
37 |
|
38 | fastify.get('/', options, function (request, reply) {
|
39 | request.log.info('Some info about the current request')
|
40 | reply.send({ hello: 'world' })
|
41 | })
|
42 | ```
|
43 |
|
44 | If you want to pass a custom stream to the Pino instance, just add a stream field to the logger object.
|
45 |
|
46 | ```js
|
47 | const split = require('split2')
|
48 | const stream = split(JSON.parse)
|
49 |
|
50 | const fastify = require('fastify')({
|
51 | logger: {
|
52 | level: 'info',
|
53 | stream: stream
|
54 | }
|
55 | })
|
56 | ```
|
57 |
|
58 | <a name="logging-request-id"></a>
|
59 |
|
60 | 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`](https://github.com/fastify/fastify/blob/master/docs/Server.md#factory-request-id-header) and Fastify Factory [`genReqId`](https://github.com/fastify/fastify/blob/master/docs/Server.md#gen-request-id) for customization options.
|
61 |
|
62 | The default logger is configured with a set of standard serializers that serialize objects with `req`, `res`, and `err` properties. This behaviour can be customized by specifying custom serializers.
|
63 | ```js
|
64 | const fastify = require('fastify')({
|
65 | logger: {
|
66 | serializers: {
|
67 | req: function (req) {
|
68 | return { url: req.url }
|
69 | }
|
70 | }
|
71 | }
|
72 | })
|
73 | ```
|
74 | For example, the response payload and headers could be logged using the approach below (even if it is *not recommended*):
|
75 |
|
76 | ```js
|
77 | const fastify = require('fastify')({
|
78 | logger: {
|
79 | prettyPrint: true,
|
80 | serializers: {
|
81 | res(res) {
|
82 | // The default
|
83 | return {
|
84 | statusCode: res.statusCode
|
85 | }
|
86 | },
|
87 | req(req) {
|
88 | return {
|
89 | method: req.method,
|
90 | url: req.url,
|
91 | path: req.path,
|
92 | parameters: req.parameters,
|
93 | // Including the headers in the log could be in violation
|
94 | // of privacy laws, e.g. GDPR. You should use the "redact" option to
|
95 | // remove sensitive fields. It could also leak authentication data in
|
96 | // the logs.
|
97 | headers: req.headers
|
98 | };
|
99 | }
|
100 | }
|
101 | }
|
102 | });
|
103 | ```
|
104 | **Note**: The body cannot be serialized inside `req` method because the request is serialized when we create the child logger. At that time, the body is not yet parsed.
|
105 |
|
106 | See an approach to log `req.body`
|
107 |
|
108 | ```js
|
109 | app.addHook('preHandler', function (req, reply, done) {
|
110 | if (req.body) {
|
111 | req.log.info({ body: req.body }, 'parsed body')
|
112 | }
|
113 | done()
|
114 | })
|
115 | ```
|
116 |
|
117 |
|
118 | *This option will be ignored by any logger other than Pino.*
|
119 |
|
120 | You can also supply your own logger instance. Instead of passing configuration options, simply pass the instance.
|
121 | The logger you supply must conform to the Pino interface; that is, it must have the following methods:
|
122 | `info`, `error`, `debug`, `fatal`, `warn`, `trace`, `child`.
|
123 |
|
124 | Example:
|
125 |
|
126 | ```js
|
127 | const log = require('pino')({ level: 'info' })
|
128 | const fastify = require('fastify')({ logger: log })
|
129 |
|
130 | log.info('does not have request information')
|
131 |
|
132 | fastify.get('/', function (request, reply) {
|
133 | request.log.info('includes request information, but is the same logger instance as `log`')
|
134 | reply.send({ hello: 'world' })
|
135 | })
|
136 | ```
|
137 |
|
138 | *The logger instance for the current request is available in every part of the [lifecycle](https://github.com/fastify/fastify/blob/master/docs/Lifecycle.md).*
|
139 |
|
140 | ## Log Redaction
|
141 |
|
142 | [Pino](https://getpino.io) supports low-overhead log redaction for
|
143 | obscuring values of specific properties in recorded logs.
|
144 | As an example, we might want to log all the HTTP headers minus the
|
145 | `Authorization` header for security concerns:
|
146 |
|
147 | ```js
|
148 | const fastify = Fastify({
|
149 | logger: {
|
150 | stream: stream,
|
151 | redact: ['req.headers.authorization'],
|
152 | level: 'info',
|
153 | serializers: {
|
154 | req (req) {
|
155 | return {
|
156 | method: req.method,
|
157 | url: req.url,
|
158 | headers: req.headers,
|
159 | hostname: req.hostname,
|
160 | remoteAddress: req.ip,
|
161 | remotePort: req.connection.remotePort
|
162 | }
|
163 | }
|
164 | }
|
165 | }
|
166 | })
|
167 | ```
|
168 |
|
169 | See https://getpino.io/#/docs/redaction for more details.
|