1 | 'use strict'
|
2 |
|
3 | const { test, tearDown } = require('tap')
|
4 | const http = require('http')
|
5 | const stream = require('stream')
|
6 | const split = require('split2')
|
7 | const Fastify = require('..')
|
8 | const pino = require('pino')
|
9 | const path = require('path')
|
10 | const os = require('os')
|
11 | const fs = require('fs')
|
12 | const sget = require('simple-get').concat
|
13 |
|
14 | const files = []
|
15 | let count = 0
|
16 |
|
17 | function file () {
|
18 | const file = path.join(os.tmpdir(), `sonic-boom-${process.pid}-${process.hrtime().toString()}-${count++}`)
|
19 | files.push(file)
|
20 | return file
|
21 | }
|
22 |
|
23 | tearDown(() => {
|
24 | files.forEach((file) => {
|
25 | try {
|
26 | fs.unlinkSync(file)
|
27 | } catch (e) {
|
28 | console.log(e)
|
29 | }
|
30 | })
|
31 | })
|
32 |
|
33 | test('defaults to info level', t => {
|
34 | t.plan(13)
|
35 | var fastify = null
|
36 | var stream = split(JSON.parse)
|
37 | try {
|
38 | fastify = Fastify({
|
39 | logger: {
|
40 | stream: stream
|
41 | }
|
42 | })
|
43 | } catch (e) {
|
44 | t.fail()
|
45 | }
|
46 |
|
47 | fastify.get('/', function (req, reply) {
|
48 | t.ok(req.log)
|
49 | reply.send({ hello: 'world' })
|
50 | })
|
51 |
|
52 | stream.once('data', listenAtLogLine => {
|
53 | t.ok(listenAtLogLine, 'listen at log message is ok')
|
54 |
|
55 | stream.once('data', line => {
|
56 | const id = line.reqId
|
57 | t.ok(line.reqId, 'reqId is defined')
|
58 | t.ok(line.req, 'req is defined')
|
59 | t.equal(line.msg, 'incoming request', 'message is set')
|
60 | t.equal(line.req.method, 'GET', 'method is get')
|
61 |
|
62 | stream.once('data', line => {
|
63 | t.equal(line.reqId, id)
|
64 | t.ok(line.reqId, 'reqId is defined')
|
65 | t.ok(line.res, 'res is defined')
|
66 | t.equal(line.msg, 'request completed', 'message is set')
|
67 | t.equal(line.res.statusCode, 200, 'statusCode is 200')
|
68 | t.ok(line.responseTime, 'responseTime is defined')
|
69 | })
|
70 | })
|
71 | })
|
72 |
|
73 | fastify.listen(0, err => {
|
74 | t.error(err)
|
75 | fastify.server.unref()
|
76 |
|
77 | http.get('http://localhost:' + fastify.server.address().port)
|
78 | })
|
79 | })
|
80 |
|
81 | test('test log stream', t => {
|
82 | t.plan(12)
|
83 | var fastify = null
|
84 | var stream = split(JSON.parse)
|
85 | try {
|
86 | fastify = Fastify({
|
87 | logger: {
|
88 | stream: stream,
|
89 | level: 'info'
|
90 | }
|
91 | })
|
92 | } catch (e) {
|
93 | t.fail()
|
94 | }
|
95 |
|
96 | fastify.get('/', function (req, reply) {
|
97 | t.ok(req.log)
|
98 | reply.send({ hello: 'world' })
|
99 | })
|
100 |
|
101 | fastify.listen(0, err => {
|
102 | t.error(err)
|
103 | fastify.server.unref()
|
104 |
|
105 | http.get('http://localhost:' + fastify.server.address().port)
|
106 | stream.once('data', listenAtLogLine => {
|
107 | t.ok(listenAtLogLine, 'listen at log message is ok')
|
108 |
|
109 | stream.once('data', line => {
|
110 | const id = line.reqId
|
111 | t.ok(line.reqId, 'reqId is defined')
|
112 | t.ok(line.req, 'req is defined')
|
113 | t.equal(line.msg, 'incoming request', 'message is set')
|
114 | t.equal(line.req.method, 'GET', 'method is get')
|
115 |
|
116 | stream.once('data', line => {
|
117 | t.equal(line.reqId, id)
|
118 | t.ok(line.reqId, 'reqId is defined')
|
119 | t.ok(line.res, 'res is defined')
|
120 | t.equal(line.msg, 'request completed', 'message is set')
|
121 | t.equal(line.res.statusCode, 200, 'statusCode is 200')
|
122 | })
|
123 | })
|
124 | })
|
125 | })
|
126 | })
|
127 |
|
128 | test('test error log stream', t => {
|
129 | t.plan(11)
|
130 | var fastify = null
|
131 | var stream = split(JSON.parse)
|
132 | try {
|
133 | fastify = Fastify({
|
134 | logger: {
|
135 | stream: stream,
|
136 | level: 'info'
|
137 | }
|
138 | })
|
139 | } catch (e) {
|
140 | t.fail()
|
141 | }
|
142 |
|
143 | fastify.get('/error', function (req, reply) {
|
144 | t.ok(req.log)
|
145 | reply.send(new Error('kaboom'))
|
146 | })
|
147 |
|
148 | fastify.listen(0, err => {
|
149 | t.error(err)
|
150 | fastify.server.unref()
|
151 |
|
152 | http.get('http://localhost:' + fastify.server.address().port + '/error')
|
153 | stream.once('data', listenAtLogLine => {
|
154 | t.ok(listenAtLogLine, 'listen at log message is ok')
|
155 |
|
156 | stream.once('data', line => {
|
157 | t.ok(line.reqId, 'reqId is defined')
|
158 | t.ok(line.req, 'req is defined')
|
159 | t.equal(line.msg, 'incoming request', 'message is set')
|
160 | t.equal(line.req.method, 'GET', 'method is get')
|
161 |
|
162 | stream.once('data', line => {
|
163 | t.ok(line.reqId, 'reqId is defined')
|
164 | t.ok(line.res, 'res is defined')
|
165 | t.equal(line.msg, 'kaboom', 'message is set')
|
166 | t.equal(line.res.statusCode, 500, 'statusCode is 500')
|
167 | })
|
168 | })
|
169 | })
|
170 | })
|
171 | })
|
172 |
|
173 | test('can use external logger instance', t => {
|
174 | const lines = [/^Server listening at /, /^incoming request$/, /^log success$/, /^request completed$/]
|
175 | t.plan(lines.length + 2)
|
176 |
|
177 | const splitStream = split(JSON.parse)
|
178 | splitStream.on('data', (line) => {
|
179 | const regex = lines.shift()
|
180 | t.ok(regex.test(line.msg), '"' + line.msg + '" dont match "' + regex + '"')
|
181 | })
|
182 |
|
183 | const logger = require('pino')(splitStream)
|
184 |
|
185 | const localFastify = Fastify({ logger: logger })
|
186 |
|
187 | localFastify.get('/foo', function (req, reply) {
|
188 | t.ok(req.log)
|
189 | req.log.info('log success')
|
190 | reply.send({ hello: 'world' })
|
191 | })
|
192 |
|
193 | localFastify.listen(0, err => {
|
194 | t.error(err)
|
195 | http.get('http://localhost:' + localFastify.server.address().port + '/foo', (res) => {
|
196 | res.resume()
|
197 | res.on('end', () => {
|
198 | localFastify.server.close()
|
199 | })
|
200 | })
|
201 | })
|
202 | })
|
203 |
|
204 | test('can use external logger instance with custom serializer', t => {
|
205 | const lines = [['level', 30], ['req', { url: '/foo' }], ['level', 30], ['res', { statusCode: 200 }]]
|
206 | t.plan(lines.length + 2)
|
207 |
|
208 | const splitStream = split(JSON.parse)
|
209 | splitStream.on('data', (line) => {
|
210 | const check = lines.shift()
|
211 | const key = check[0]
|
212 | const value = check[1]
|
213 |
|
214 | t.deepEqual(line[key], value)
|
215 | })
|
216 |
|
217 | const logger = require('pino')({
|
218 | level: 'info',
|
219 | serializers: {
|
220 | req: function (req) {
|
221 | return {
|
222 | url: req.url
|
223 | }
|
224 | }
|
225 | }
|
226 | }, splitStream)
|
227 |
|
228 | const localFastify = Fastify({
|
229 | logger: logger
|
230 | })
|
231 |
|
232 | localFastify.get('/foo', function (req, reply) {
|
233 | t.ok(req.log)
|
234 | req.log.info('log success')
|
235 | reply.send({ hello: 'world' })
|
236 | })
|
237 |
|
238 | localFastify.listen(0, err => {
|
239 | t.error(err)
|
240 | http.get('http://localhost:' + localFastify.server.address().port + '/foo', (res) => {
|
241 | res.resume()
|
242 | res.on('end', () => {
|
243 | localFastify.server.close()
|
244 | })
|
245 | })
|
246 | })
|
247 | })
|
248 |
|
249 | test('expose the logger', t => {
|
250 | t.plan(2)
|
251 | var fastify = null
|
252 | var stream = split(JSON.parse)
|
253 | try {
|
254 | fastify = Fastify({
|
255 | logger: {
|
256 | stream: stream,
|
257 | level: 'info'
|
258 | }
|
259 | })
|
260 | } catch (e) {
|
261 | t.fail()
|
262 | }
|
263 |
|
264 | t.ok(fastify.log)
|
265 | t.is(typeof fastify.log, 'object')
|
266 | })
|
267 |
|
268 | test('The request id header key can be customized', t => {
|
269 | t.plan(9)
|
270 | const REQUEST_ID = '42'
|
271 |
|
272 | const stream = split(JSON.parse)
|
273 | const fastify = Fastify({
|
274 | logger: { stream: stream, level: 'info' },
|
275 | requestIdHeader: 'my-custom-request-id'
|
276 | })
|
277 | t.tearDown(() => fastify.close())
|
278 |
|
279 | fastify.get('/', (req, reply) => {
|
280 | t.equal(req.raw.id, REQUEST_ID)
|
281 | req.log.info('some log message')
|
282 | reply.send({ id: req.raw.id })
|
283 | })
|
284 |
|
285 | fastify.inject({
|
286 | method: 'GET',
|
287 | url: '/',
|
288 | headers: {
|
289 | 'my-custom-request-id': REQUEST_ID
|
290 | }
|
291 | }, (err, res) => {
|
292 | t.error(err)
|
293 | const payload = JSON.parse(res.payload)
|
294 | t.equal(payload.id, REQUEST_ID)
|
295 |
|
296 | stream.once('data', line => {
|
297 | t.equal(line.reqId, REQUEST_ID)
|
298 | t.equal(line.msg, 'incoming request', 'message is set')
|
299 |
|
300 | stream.once('data', line => {
|
301 | t.equal(line.reqId, REQUEST_ID)
|
302 | t.equal(line.msg, 'some log message', 'message is set')
|
303 |
|
304 | stream.once('data', line => {
|
305 | t.equal(line.reqId, REQUEST_ID)
|
306 | t.equal(line.msg, 'request completed', 'message is set')
|
307 | })
|
308 | })
|
309 | })
|
310 | })
|
311 | })
|
312 |
|
313 | test('The request id header key can be customized along with a custom id generator', t => {
|
314 | t.plan(12)
|
315 | const REQUEST_ID = '42'
|
316 |
|
317 | const stream = split(JSON.parse)
|
318 | const fastify = Fastify({
|
319 | logger: { stream: stream, level: 'info' },
|
320 | requestIdHeader: 'my-custom-request-id',
|
321 | genReqId (req) {
|
322 | return 'foo'
|
323 | }
|
324 | })
|
325 | t.tearDown(() => fastify.close())
|
326 |
|
327 | fastify.get('/one', (req, reply) => {
|
328 | t.equal(req.id, REQUEST_ID)
|
329 | req.log.info('some log message')
|
330 | reply.send({ id: req.id })
|
331 | })
|
332 |
|
333 | fastify.get('/two', (req, reply) => {
|
334 | t.equal(req.id, 'foo')
|
335 | req.log.info('some log message 2')
|
336 | reply.send({ id: req.id })
|
337 | })
|
338 |
|
339 | const matches = [
|
340 | { reqId: REQUEST_ID, msg: /incoming request/ },
|
341 | { reqId: REQUEST_ID, msg: /some log message/ },
|
342 | { reqId: REQUEST_ID, msg: /request completed/ },
|
343 | { reqId: 'foo', msg: /incoming request/ },
|
344 | { reqId: 'foo', msg: /some log message 2/ },
|
345 | { reqId: 'foo', msg: /request completed/ }
|
346 | ]
|
347 |
|
348 | let i = 0
|
349 | stream.on('data', line => {
|
350 | t.match(line, matches[i])
|
351 | i += 1
|
352 | })
|
353 |
|
354 | fastify.inject({
|
355 | method: 'GET',
|
356 | url: '/one',
|
357 | headers: {
|
358 | 'my-custom-request-id': REQUEST_ID
|
359 | }
|
360 | }, (err, res) => {
|
361 | t.error(err)
|
362 | const payload = JSON.parse(res.payload)
|
363 | t.equal(payload.id, REQUEST_ID)
|
364 | })
|
365 |
|
366 | fastify.inject({
|
367 | method: 'GET',
|
368 | url: '/two'
|
369 | }, (err, res) => {
|
370 | t.error(err)
|
371 | const payload = JSON.parse(res.payload)
|
372 | t.equal(payload.id, 'foo')
|
373 | })
|
374 | })
|
375 |
|
376 | test('The request id log label can be changed', t => {
|
377 | t.plan(6)
|
378 | const REQUEST_ID = '42'
|
379 |
|
380 | const stream = split(JSON.parse)
|
381 | const fastify = Fastify({
|
382 | logger: { stream: stream, level: 'info' },
|
383 | requestIdHeader: 'my-custom-request-id',
|
384 | requestIdLogLabel: 'traceId'
|
385 | })
|
386 | t.tearDown(() => fastify.close())
|
387 |
|
388 | fastify.get('/one', (req, reply) => {
|
389 | t.equal(req.id, REQUEST_ID)
|
390 | req.log.info('some log message')
|
391 | reply.send({ id: req.id })
|
392 | })
|
393 |
|
394 | const matches = [
|
395 | { traceId: REQUEST_ID, msg: /incoming request/ },
|
396 | { traceId: REQUEST_ID, msg: /some log message/ },
|
397 | { traceId: REQUEST_ID, msg: /request completed/ }
|
398 | ]
|
399 |
|
400 | let i = 0
|
401 | stream.on('data', line => {
|
402 | t.match(line, matches[i])
|
403 | i += 1
|
404 | })
|
405 |
|
406 | fastify.inject({
|
407 | method: 'GET',
|
408 | url: '/one',
|
409 | headers: {
|
410 | 'my-custom-request-id': REQUEST_ID
|
411 | }
|
412 | }, (err, res) => {
|
413 | t.error(err)
|
414 | const payload = JSON.parse(res.payload)
|
415 | t.equal(payload.id, REQUEST_ID)
|
416 | })
|
417 | })
|
418 |
|
419 | test('The logger should accept custom serializer', t => {
|
420 | t.plan(9)
|
421 |
|
422 | const stream = split(JSON.parse)
|
423 | const fastify = Fastify({
|
424 | logger: {
|
425 | stream: stream,
|
426 | level: 'info',
|
427 | serializers: {
|
428 | req: function (req) {
|
429 | return {
|
430 | url: req.url
|
431 | }
|
432 | }
|
433 | }
|
434 | }
|
435 | })
|
436 |
|
437 | fastify.get('/custom', function (req, reply) {
|
438 | t.ok(req.log)
|
439 | reply.send(new Error('kaboom'))
|
440 | })
|
441 |
|
442 | fastify.listen(0, err => {
|
443 | t.error(err)
|
444 | fastify.server.unref()
|
445 |
|
446 | http.get('http://localhost:' + fastify.server.address().port + '/custom')
|
447 | stream.once('data', listenAtLogLine => {
|
448 | t.ok(listenAtLogLine, 'listen at log message is ok')
|
449 |
|
450 | stream.once('data', line => {
|
451 | t.ok(line.req, 'req is defined')
|
452 | t.equal(line.msg, 'incoming request', 'message is set')
|
453 | t.deepEqual(line.req, { url: '/custom' }, 'custom req serialiser is use')
|
454 |
|
455 | stream.once('data', line => {
|
456 | t.ok(line.res, 'res is defined')
|
457 | t.equal(line.msg, 'kaboom', 'message is set')
|
458 | t.deepEqual(line.res, { statusCode: 500 }, 'default res serialiser is use')
|
459 | })
|
460 | })
|
461 | })
|
462 | })
|
463 | })
|
464 |
|
465 | test('reply.send logs an error if called twice in a row', t => {
|
466 | const lines = ['incoming request', 'request completed', 'Reply already sent', 'Reply already sent']
|
467 | t.plan(lines.length + 2)
|
468 |
|
469 | const splitStream = split(JSON.parse)
|
470 | splitStream.on('data', (line) => {
|
471 | t.is(line.msg, lines.shift())
|
472 | })
|
473 |
|
474 | const logger = pino(splitStream)
|
475 |
|
476 | const fastify = Fastify({
|
477 | logger
|
478 | })
|
479 |
|
480 | fastify.get('/', (req, reply) => {
|
481 | reply.send({ hello: 'world' })
|
482 | reply.send({ hello: 'world2' })
|
483 | reply.send({ hello: 'world3' })
|
484 | })
|
485 |
|
486 | fastify.inject({
|
487 | method: 'GET',
|
488 | url: '/'
|
489 | }, (err, res) => {
|
490 | t.error(err)
|
491 | const payload = JSON.parse(res.payload)
|
492 | t.deepEqual(payload, { hello: 'world' })
|
493 | })
|
494 | })
|
495 |
|
496 | test('logger can be silented', t => {
|
497 | t.plan(17)
|
498 | const fastify = Fastify({
|
499 | logger: false
|
500 | })
|
501 | t.ok(fastify.log)
|
502 | t.is(typeof fastify.log, 'object')
|
503 | t.is(typeof fastify.log.fatal, 'function')
|
504 | t.is(typeof fastify.log.error, 'function')
|
505 | t.is(typeof fastify.log.warn, 'function')
|
506 | t.is(typeof fastify.log.info, 'function')
|
507 | t.is(typeof fastify.log.debug, 'function')
|
508 | t.is(typeof fastify.log.trace, 'function')
|
509 | t.is(typeof fastify.log.child, 'function')
|
510 |
|
511 | const childLog = fastify.log.child()
|
512 |
|
513 | t.is(typeof childLog, 'object')
|
514 | t.is(typeof childLog.fatal, 'function')
|
515 | t.is(typeof childLog.error, 'function')
|
516 | t.is(typeof childLog.warn, 'function')
|
517 | t.is(typeof childLog.info, 'function')
|
518 | t.is(typeof childLog.debug, 'function')
|
519 | t.is(typeof childLog.trace, 'function')
|
520 | t.is(typeof childLog.child, 'function')
|
521 | })
|
522 |
|
523 | test('Should set a custom logLevel for a plugin', t => {
|
524 | const lines = ['incoming request', 'Hello', 'request completed']
|
525 | t.plan(7)
|
526 |
|
527 | const splitStream = split(JSON.parse)
|
528 | splitStream.on('data', (line) => {
|
529 | t.is(line.msg, lines.shift())
|
530 | })
|
531 |
|
532 | const logger = pino({ level: 'error' }, splitStream)
|
533 |
|
534 | const fastify = Fastify({
|
535 | logger
|
536 | })
|
537 |
|
538 | fastify.get('/', (req, reply) => {
|
539 | req.log.info('Hello')
|
540 | reply.send({ hello: 'world' })
|
541 | })
|
542 |
|
543 | fastify.register(function (instance, opts, next) {
|
544 | instance.get('/plugin', (req, reply) => {
|
545 | req.log.info('Hello')
|
546 | reply.send({ hello: 'world' })
|
547 | })
|
548 | next()
|
549 | }, { logLevel: 'info' })
|
550 |
|
551 | fastify.inject({
|
552 | method: 'GET',
|
553 | url: '/'
|
554 | }, (err, res) => {
|
555 | t.error(err)
|
556 | const payload = JSON.parse(res.payload)
|
557 | t.deepEqual(payload, { hello: 'world' })
|
558 | })
|
559 |
|
560 | fastify.inject({
|
561 | method: 'GET',
|
562 | url: '/plugin'
|
563 | }, (err, res) => {
|
564 | t.error(err)
|
565 | const payload = JSON.parse(res.payload)
|
566 | t.deepEqual(payload, { hello: 'world' })
|
567 | })
|
568 | })
|
569 |
|
570 | test('Should set a custom logSerializers for a plugin', t => {
|
571 | t.plan(3)
|
572 |
|
573 | const splitStream = split(JSON.parse)
|
574 | splitStream.on('data', (line) => {
|
575 | if (line.test) {
|
576 | t.is(line.test, 'XHello')
|
577 | }
|
578 | })
|
579 |
|
580 | const logger = pino({ level: 'error' }, splitStream)
|
581 |
|
582 | const fastify = Fastify({
|
583 | logger
|
584 | })
|
585 |
|
586 | fastify.register(function (instance, opts, next) {
|
587 | instance.get('/plugin', (req, reply) => {
|
588 | req.log.info({ test: 'Hello' })
|
589 | reply.send({ hello: 'world' })
|
590 | })
|
591 | next()
|
592 | }, { logLevel: 'info', logSerializers: { test: value => 'X' + value } })
|
593 |
|
594 | fastify.inject({
|
595 | method: 'GET',
|
596 | url: '/plugin'
|
597 | }, (err, res) => {
|
598 | t.error(err)
|
599 | const payload = JSON.parse(res.payload)
|
600 | t.deepEqual(payload, { hello: 'world' })
|
601 | })
|
602 | })
|
603 |
|
604 | test('Should set a custom logLevel for every plugin', t => {
|
605 | const lines = ['incoming request', 'request completed', 'info', 'debug']
|
606 | t.plan(18)
|
607 |
|
608 | const splitStream = split(JSON.parse)
|
609 | splitStream.on('data', (line) => {
|
610 | t.ok(line.level === 30 || line.level === 20)
|
611 | t.ok(lines.indexOf(line.msg) > -1)
|
612 | })
|
613 |
|
614 | const logger = pino({ level: 'error' }, splitStream)
|
615 |
|
616 | const fastify = Fastify({
|
617 | logger
|
618 | })
|
619 |
|
620 | fastify.get('/', (req, reply) => {
|
621 | req.log.warn('Hello')
|
622 | reply.send({ hello: 'world' })
|
623 | })
|
624 |
|
625 | fastify.register(function (instance, opts, next) {
|
626 | instance.get('/info', (req, reply) => {
|
627 | req.log.info('info')
|
628 | req.log.debug('hidden log')
|
629 | reply.send({ hello: 'world' })
|
630 | })
|
631 | next()
|
632 | }, { logLevel: 'info' })
|
633 |
|
634 | fastify.register(function (instance, opts, next) {
|
635 | instance.get('/debug', (req, reply) => {
|
636 | req.log.debug('debug')
|
637 | req.log.trace('hidden log')
|
638 | reply.send({ hello: 'world' })
|
639 | })
|
640 | next()
|
641 | }, { logLevel: 'debug' })
|
642 |
|
643 | fastify.inject({
|
644 | method: 'GET',
|
645 | url: '/'
|
646 | }, (err, res) => {
|
647 | t.error(err)
|
648 | const payload = JSON.parse(res.payload)
|
649 | t.deepEqual(payload, { hello: 'world' })
|
650 | })
|
651 |
|
652 | fastify.inject({
|
653 | method: 'GET',
|
654 | url: '/info'
|
655 | }, (err, res) => {
|
656 | t.error(err)
|
657 | const payload = JSON.parse(res.payload)
|
658 | t.deepEqual(payload, { hello: 'world' })
|
659 | })
|
660 |
|
661 | fastify.inject({
|
662 | method: 'GET',
|
663 | url: '/debug'
|
664 | }, (err, res) => {
|
665 | t.error(err)
|
666 | const payload = JSON.parse(res.payload)
|
667 | t.deepEqual(payload, { hello: 'world' })
|
668 | })
|
669 | })
|
670 |
|
671 | test('Should set a custom logSerializers for every plugin', t => {
|
672 | const lines = ['Hello', 'XHello', 'ZHello']
|
673 | t.plan(9)
|
674 |
|
675 | const splitStream = split(JSON.parse)
|
676 | splitStream.on('data', (line) => {
|
677 | if (line.test) {
|
678 | t.is(line.test, lines.shift())
|
679 | }
|
680 | })
|
681 |
|
682 | const logger = pino({ level: 'info' }, splitStream)
|
683 | const fastify = Fastify({
|
684 | logger
|
685 | })
|
686 |
|
687 | fastify.get('/', (req, reply) => {
|
688 | req.log.warn({ test: 'Hello' })
|
689 | reply.send({ hello: 'world' })
|
690 | })
|
691 |
|
692 | fastify.register(function (instance, opts, next) {
|
693 | instance.get('/test1', (req, reply) => {
|
694 | req.log.info({ test: 'Hello' })
|
695 | reply.send({ hello: 'world' })
|
696 | })
|
697 | next()
|
698 | }, { logSerializers: { test: value => 'X' + value } })
|
699 |
|
700 | fastify.register(function (instance, opts, next) {
|
701 | instance.get('/test2', (req, reply) => {
|
702 | req.log.info({ test: 'Hello' })
|
703 | reply.send({ hello: 'world' })
|
704 | })
|
705 | next()
|
706 | }, { logSerializers: { test: value => 'Z' + value } })
|
707 |
|
708 | fastify.inject({
|
709 | method: 'GET',
|
710 | url: '/'
|
711 | }, (err, res) => {
|
712 | t.error(err)
|
713 | const payload = JSON.parse(res.payload)
|
714 | t.deepEqual(payload, { hello: 'world' })
|
715 | })
|
716 |
|
717 | fastify.inject({
|
718 | method: 'GET',
|
719 | url: '/test1'
|
720 | }, (err, res) => {
|
721 | t.error(err)
|
722 | const payload = JSON.parse(res.payload)
|
723 | t.deepEqual(payload, { hello: 'world' })
|
724 | })
|
725 |
|
726 | fastify.inject({
|
727 | method: 'GET',
|
728 | url: '/test2'
|
729 | }, (err, res) => {
|
730 | t.error(err)
|
731 | const payload = JSON.parse(res.payload)
|
732 | t.deepEqual(payload, { hello: 'world' })
|
733 | })
|
734 | })
|
735 |
|
736 | test('Should override serializers from route', t => {
|
737 | t.plan(3)
|
738 |
|
739 | const splitStream = split(JSON.parse)
|
740 | splitStream.on('data', (line) => {
|
741 | if (line.test) {
|
742 | t.is(line.test, 'ZHello')
|
743 | }
|
744 | })
|
745 |
|
746 | const logger = pino({ level: 'info' }, splitStream)
|
747 | const fastify = Fastify({
|
748 | logger
|
749 | })
|
750 |
|
751 | fastify.register(function (instance, opts, next) {
|
752 | instance.get('/', {
|
753 | logSerializers: {
|
754 | test: value => 'Z' + value
|
755 | }
|
756 | }, (req, reply) => {
|
757 | req.log.info({ test: 'Hello' })
|
758 | reply.send({ hello: 'world' })
|
759 | })
|
760 | next()
|
761 | }, { logSerializers: { test: value => 'X' + value } })
|
762 |
|
763 | fastify.inject({
|
764 | method: 'GET',
|
765 | url: '/'
|
766 | }, (err, res) => {
|
767 | t.error(err)
|
768 | const payload = JSON.parse(res.payload)
|
769 | t.deepEqual(payload, { hello: 'world' })
|
770 | })
|
771 | })
|
772 |
|
773 | test('Should override serializers from plugin', t => {
|
774 | t.plan(3)
|
775 |
|
776 | const splitStream = split(JSON.parse)
|
777 | splitStream.on('data', (line) => {
|
778 | if (line.test) {
|
779 | t.is(line.test, 'ZHello')
|
780 | }
|
781 | })
|
782 |
|
783 | const logger = pino({ level: 'info' }, splitStream)
|
784 | const fastify = Fastify({
|
785 | logger
|
786 | })
|
787 |
|
788 | fastify.register(function (instance, opts, next) {
|
789 | instance.register(context1, {
|
790 | logSerializers: {
|
791 | test: value => 'Z' + value
|
792 | }
|
793 | })
|
794 | next()
|
795 | }, { logSerializers: { test: value => 'X' + value } })
|
796 |
|
797 | function context1 (instance, opts, next) {
|
798 | instance.get('/', (req, reply) => {
|
799 | req.log.info({ test: 'Hello' })
|
800 | reply.send({ hello: 'world' })
|
801 | })
|
802 | next()
|
803 | }
|
804 |
|
805 | fastify.inject({
|
806 | method: 'GET',
|
807 | url: '/'
|
808 | }, (err, res) => {
|
809 | t.error(err)
|
810 | const payload = JSON.parse(res.payload)
|
811 | t.deepEqual(payload, { hello: 'world' })
|
812 | })
|
813 | })
|
814 |
|
815 | test('Should use serializers from plugin and route', t => {
|
816 | t.plan(4)
|
817 |
|
818 | const splitStream = split(JSON.parse)
|
819 | splitStream.on('data', (line) => {
|
820 | if (line.test) {
|
821 | t.is(line.test, 'XHello')
|
822 | }
|
823 | if (line.test2) {
|
824 | t.is(line.test2, 'ZHello')
|
825 | }
|
826 | })
|
827 |
|
828 | const logger = pino({ level: 'info' }, splitStream)
|
829 | const fastify = Fastify({
|
830 | logger
|
831 | })
|
832 |
|
833 | fastify.register(context1, {
|
834 | logSerializers: { test: value => 'X' + value }
|
835 | })
|
836 |
|
837 | function context1 (instance, opts, next) {
|
838 | instance.get('/', {
|
839 | logSerializers: {
|
840 | test2: value => 'Z' + value
|
841 | }
|
842 | }, (req, reply) => {
|
843 | req.log.info({ test: 'Hello', test2: 'Hello' })
|
844 | reply.send({ hello: 'world' })
|
845 | })
|
846 | next()
|
847 | }
|
848 |
|
849 | fastify.inject({
|
850 | method: 'GET',
|
851 | url: '/'
|
852 | }, (err, res) => {
|
853 | t.error(err)
|
854 | const payload = JSON.parse(res.payload)
|
855 | t.deepEqual(payload, { hello: 'world' })
|
856 | })
|
857 | })
|
858 |
|
859 | test('Should use serializers from instance fastify and route', t => {
|
860 | t.plan(4)
|
861 |
|
862 | const splitStream = split(JSON.parse)
|
863 | splitStream.on('data', (line) => {
|
864 | if (line.test) {
|
865 | t.is(line.test, 'XHello')
|
866 | }
|
867 | if (line.test2) {
|
868 | t.is(line.test2, 'ZHello')
|
869 | }
|
870 | })
|
871 |
|
872 | const logger = pino({
|
873 | level: 'info',
|
874 | serializers: {
|
875 | test: value => 'X' + value,
|
876 | test2: value => 'This should be override - ' + value
|
877 | }
|
878 | }, splitStream)
|
879 | const fastify = Fastify({
|
880 | logger
|
881 | })
|
882 |
|
883 | fastify.get('/', {
|
884 | logSerializers: {
|
885 | test2: value => 'Z' + value
|
886 | }
|
887 | }, (req, reply) => {
|
888 | req.log.info({ test: 'Hello', test2: 'Hello' })
|
889 | reply.send({ hello: 'world' })
|
890 | })
|
891 |
|
892 | fastify.inject({
|
893 | method: 'GET',
|
894 | url: '/'
|
895 | }, (err, res) => {
|
896 | t.error(err)
|
897 | const payload = JSON.parse(res.payload)
|
898 | t.deepEqual(payload, { hello: 'world' })
|
899 | })
|
900 | })
|
901 |
|
902 | test('Should use serializers inherit from contexts', t => {
|
903 | t.plan(5)
|
904 |
|
905 | const splitStream = split(JSON.parse)
|
906 | splitStream.on('data', (line) => {
|
907 | if (line.test && line.test2 && line.test3) {
|
908 | t.is(line.test, 'XHello')
|
909 | t.is(line.test2, 'YHello')
|
910 | t.is(line.test3, 'ZHello')
|
911 | }
|
912 | })
|
913 |
|
914 | const logger = pino({
|
915 | level: 'info',
|
916 | serializers: {
|
917 | test: value => 'X' + value
|
918 | }
|
919 | }, splitStream)
|
920 |
|
921 | const fastify = Fastify({ logger })
|
922 | fastify.register(context1, { logSerializers: { test2: value => 'Y' + value } })
|
923 |
|
924 | function context1 (instance, opts, next) {
|
925 | instance.get('/', {
|
926 | logSerializers: {
|
927 | test3: value => 'Z' + value
|
928 | }
|
929 | }, (req, reply) => {
|
930 | req.log.info({ test: 'Hello', test2: 'Hello', test3: 'Hello' })
|
931 | reply.send({ hello: 'world' })
|
932 | })
|
933 | next()
|
934 | }
|
935 |
|
936 | fastify.inject({
|
937 | method: 'GET',
|
938 | url: '/'
|
939 | }, (err, res) => {
|
940 | t.error(err)
|
941 | const payload = JSON.parse(res.payload)
|
942 | t.deepEqual(payload, { hello: 'world' })
|
943 | })
|
944 | })
|
945 |
|
946 | test('Should increase the log level for a specific plugin', t => {
|
947 | t.plan(4)
|
948 |
|
949 | const splitStream = split(JSON.parse)
|
950 | splitStream.on('data', (line) => {
|
951 | t.is(line.msg, 'Hello')
|
952 | t.ok(line.level === 50)
|
953 | })
|
954 |
|
955 | const logger = pino({ level: 'info' }, splitStream)
|
956 |
|
957 | const fastify = Fastify({
|
958 | logger
|
959 | })
|
960 |
|
961 | fastify.register(function (instance, opts, next) {
|
962 | instance.get('/', (req, reply) => {
|
963 | req.log.error('Hello')
|
964 | reply.send({ hello: 'world' })
|
965 | })
|
966 | next()
|
967 | }, { logLevel: 'error' })
|
968 |
|
969 | fastify.inject({
|
970 | method: 'GET',
|
971 | url: '/'
|
972 | }, (err, res) => {
|
973 | t.error(err)
|
974 | const payload = JSON.parse(res.payload)
|
975 | t.deepEqual(payload, { hello: 'world' })
|
976 | })
|
977 | })
|
978 |
|
979 | test('Should set the log level for the customized 404 handler', t => {
|
980 | t.plan(4)
|
981 |
|
982 | const splitStream = split(JSON.parse)
|
983 | splitStream.on('data', (line) => {
|
984 | t.is(line.msg, 'Hello')
|
985 | t.ok(line.level === 50)
|
986 | })
|
987 |
|
988 | const logger = pino({ level: 'warn' }, splitStream)
|
989 |
|
990 | const fastify = Fastify({
|
991 | logger
|
992 | })
|
993 |
|
994 | fastify.register(function (instance, opts, next) {
|
995 | instance.setNotFoundHandler(function (req, reply) {
|
996 | req.log.error('Hello')
|
997 | reply.code(404).send()
|
998 | })
|
999 | next()
|
1000 | }, { logLevel: 'error' })
|
1001 |
|
1002 | fastify.inject({
|
1003 | method: 'GET',
|
1004 | url: '/'
|
1005 | }, (err, res) => {
|
1006 | t.error(err)
|
1007 | t.strictEqual(res.statusCode, 404)
|
1008 | })
|
1009 | })
|
1010 |
|
1011 | test('Should set the log level for the customized 500 handler', t => {
|
1012 | t.plan(4)
|
1013 |
|
1014 | const splitStream = split(JSON.parse)
|
1015 | splitStream.on('data', (line) => {
|
1016 | t.is(line.msg, 'Hello')
|
1017 | t.ok(line.level === 60)
|
1018 | })
|
1019 |
|
1020 | const logger = pino({ level: 'warn' }, splitStream)
|
1021 |
|
1022 | const fastify = Fastify({
|
1023 | logger
|
1024 | })
|
1025 |
|
1026 | fastify.register(function (instance, opts, next) {
|
1027 | instance.get('/', (req, reply) => {
|
1028 | req.log.error('kaboom')
|
1029 | reply.send(new Error('kaboom'))
|
1030 | })
|
1031 |
|
1032 | instance.setErrorHandler(function (e, request, reply) {
|
1033 | reply.log.fatal('Hello')
|
1034 | reply.code(500).send()
|
1035 | })
|
1036 | next()
|
1037 | }, { logLevel: 'fatal' })
|
1038 |
|
1039 | fastify.inject({
|
1040 | method: 'GET',
|
1041 | url: '/'
|
1042 | }, (err, res) => {
|
1043 | t.error(err)
|
1044 | t.strictEqual(res.statusCode, 500)
|
1045 | })
|
1046 | })
|
1047 |
|
1048 | test('Should set a custom log level for a specific route', t => {
|
1049 | const lines = ['incoming request', 'Hello', 'request completed']
|
1050 | t.plan(7)
|
1051 |
|
1052 | const splitStream = split(JSON.parse)
|
1053 | splitStream.on('data', (line) => {
|
1054 | t.is(line.msg, lines.shift())
|
1055 | })
|
1056 |
|
1057 | const logger = pino({ level: 'error' }, splitStream)
|
1058 |
|
1059 | const fastify = Fastify({
|
1060 | logger
|
1061 | })
|
1062 |
|
1063 | fastify.get('/log', { logLevel: 'info' }, (req, reply) => {
|
1064 | req.log.info('Hello')
|
1065 | reply.send({ hello: 'world' })
|
1066 | })
|
1067 |
|
1068 | fastify.get('/no-log', (req, reply) => {
|
1069 | req.log.info('Hello')
|
1070 | reply.send({ hello: 'world' })
|
1071 | })
|
1072 |
|
1073 | fastify.inject({
|
1074 | method: 'GET',
|
1075 | url: '/log'
|
1076 | }, (err, res) => {
|
1077 | t.error(err)
|
1078 | const payload = JSON.parse(res.payload)
|
1079 | t.deepEqual(payload, { hello: 'world' })
|
1080 | })
|
1081 |
|
1082 | fastify.inject({
|
1083 | method: 'GET',
|
1084 | url: '/no-log'
|
1085 | }, (err, res) => {
|
1086 | t.error(err)
|
1087 | const payload = JSON.parse(res.payload)
|
1088 | t.deepEqual(payload, { hello: 'world' })
|
1089 | })
|
1090 | })
|
1091 |
|
1092 | test('The default 404 handler logs the incoming request', t => {
|
1093 | t.plan(5)
|
1094 |
|
1095 | const expectedMessages = [
|
1096 | 'incoming request',
|
1097 | 'Route GET:/not-found not found',
|
1098 | 'request completed'
|
1099 | ]
|
1100 |
|
1101 | const splitStream = split(JSON.parse)
|
1102 | splitStream.on('data', (line) => {
|
1103 | t.is(line.msg, expectedMessages.shift())
|
1104 | })
|
1105 |
|
1106 | const logger = pino({ level: 'trace' }, splitStream)
|
1107 |
|
1108 | const fastify = Fastify({
|
1109 | logger
|
1110 | })
|
1111 |
|
1112 | fastify.inject({
|
1113 | method: 'GET',
|
1114 | url: '/not-found'
|
1115 | }, (err, res) => {
|
1116 | t.error(err)
|
1117 | t.strictEqual(res.statusCode, 404)
|
1118 | })
|
1119 | })
|
1120 |
|
1121 | test('should serialize request and response', t => {
|
1122 | t.plan(3)
|
1123 | const lines = []
|
1124 | const dest = new stream.Writable({
|
1125 | write: function (chunk, enc, cb) {
|
1126 | lines.push(JSON.parse(chunk))
|
1127 | cb()
|
1128 | }
|
1129 | })
|
1130 | const fastify = Fastify({ logger: { level: 'info', stream: dest } })
|
1131 |
|
1132 | fastify.get('/500', (req, reply) => {
|
1133 | reply.code(500).send(Error('500 error'))
|
1134 | })
|
1135 |
|
1136 | fastify.inject({
|
1137 | url: '/500',
|
1138 | method: 'GET'
|
1139 | }, (e, res) => {
|
1140 | const l = lines.find((line) => line.res && line.res.statusCode === 500)
|
1141 | t.ok(l.req)
|
1142 | t.is(l.req.method, 'GET')
|
1143 | t.is(l.req.url, '/500')
|
1144 | })
|
1145 | })
|
1146 |
|
1147 | {
|
1148 | const interfaces = os.networkInterfaces()
|
1149 | const ipv6 = Object.keys(interfaces)
|
1150 | .filter(name => name.substr(0, 2) === 'lo')
|
1151 | .map(name => interfaces[name])
|
1152 | .reduce((list, set) => list.concat(set), [])
|
1153 | .filter(info => info.family === 'IPv6')
|
1154 | .map(info => info.address)
|
1155 | .shift()
|
1156 |
|
1157 | if (ipv6 !== undefined) {
|
1158 | test('Wrap IPv6 address in listening log message', t => {
|
1159 | t.plan(2)
|
1160 | const stream = split(JSON.parse)
|
1161 | const fastify = Fastify({
|
1162 | logger: {
|
1163 | stream: stream,
|
1164 | level: 'info'
|
1165 | }
|
1166 | })
|
1167 | fastify.listen(0, ipv6, err => {
|
1168 | t.error(err)
|
1169 | stream.once('data', line => {
|
1170 | const expected = 'Server listening at http://[' + ipv6 + ']:' +
|
1171 | fastify.server.address().port
|
1172 | t.is(line.msg, expected)
|
1173 | fastify.close()
|
1174 | })
|
1175 | })
|
1176 | })
|
1177 | }
|
1178 | }
|
1179 |
|
1180 | test('Do not wrap IPv4 address', t => {
|
1181 | t.plan(2)
|
1182 | const stream = split(JSON.parse)
|
1183 | const fastify = Fastify({
|
1184 | logger: {
|
1185 | stream: stream,
|
1186 | level: 'info'
|
1187 | }
|
1188 | })
|
1189 | fastify.listen(0, '127.0.0.1', err => {
|
1190 | t.error(err)
|
1191 | stream.once('data', line => {
|
1192 | const expected = 'Server listening at http://127.0.0.1:' +
|
1193 | fastify.server.address().port
|
1194 | t.is(line.msg, expected)
|
1195 | fastify.close()
|
1196 | })
|
1197 | })
|
1198 | })
|
1199 |
|
1200 | test('file option', t => {
|
1201 | t.plan(13)
|
1202 | var fastify = null
|
1203 | var dest = file()
|
1204 |
|
1205 | fastify = Fastify({
|
1206 | logger: {
|
1207 | file: dest
|
1208 | }
|
1209 | })
|
1210 |
|
1211 | fastify.get('/', function (req, reply) {
|
1212 | t.ok(req.log)
|
1213 | reply.send({ hello: 'world' })
|
1214 | })
|
1215 |
|
1216 | fastify.listen(0, err => {
|
1217 | t.error(err)
|
1218 | fastify.server.unref()
|
1219 |
|
1220 | http.get('http://localhost:' + fastify.server.address().port, () => {
|
1221 | const stream = fs.createReadStream(dest).pipe(split(JSON.parse))
|
1222 |
|
1223 | stream.once('data', listenAtLogLine => {
|
1224 | t.ok(listenAtLogLine, 'listen at log message is ok')
|
1225 |
|
1226 | stream.once('data', line => {
|
1227 | const id = line.reqId
|
1228 | t.ok(line.reqId, 'reqId is defined')
|
1229 | t.ok(line.req, 'req is defined')
|
1230 | t.equal(line.msg, 'incoming request', 'message is set')
|
1231 | t.equal(line.req.method, 'GET', 'method is get')
|
1232 |
|
1233 | stream.once('data', line => {
|
1234 | t.equal(line.reqId, id)
|
1235 | t.ok(line.reqId, 'reqId is defined')
|
1236 | t.ok(line.res, 'res is defined')
|
1237 | t.equal(line.msg, 'request completed', 'message is set')
|
1238 | t.equal(line.res.statusCode, 200, 'statusCode is 200')
|
1239 | t.ok(line.responseTime, 'responseTime is defined')
|
1240 | stream.resume()
|
1241 | })
|
1242 | })
|
1243 | })
|
1244 | })
|
1245 | })
|
1246 | })
|
1247 |
|
1248 | test('should log the error if no error handler is defined', t => {
|
1249 | t.plan(8)
|
1250 | const stream = split(JSON.parse)
|
1251 | const fastify = Fastify({
|
1252 | logger: {
|
1253 | stream: stream,
|
1254 | level: 'info'
|
1255 | }
|
1256 | })
|
1257 | fastify.get('/error', function (req, reply) {
|
1258 | t.ok(req.log)
|
1259 | reply.send(new Error('a generic error'))
|
1260 | })
|
1261 | fastify.listen(0, err => {
|
1262 | t.error(err)
|
1263 | fastify.server.unref()
|
1264 | http.get('http://localhost:' + fastify.server.address().port + '/error')
|
1265 | stream.once('data', listenAtLogLine => {
|
1266 | t.ok(listenAtLogLine, 'listen at log message is ok')
|
1267 | stream.once('data', line => {
|
1268 | t.equal(line.msg, 'incoming request', 'message is set')
|
1269 | stream.once('data', line => {
|
1270 | t.equal(line.level, 50, 'level is correct')
|
1271 | t.equal(line.msg, 'a generic error', 'message is set')
|
1272 | stream.once('data', line => {
|
1273 | t.equal(line.msg, 'request completed', 'message is set')
|
1274 | t.deepEqual(line.res, { statusCode: 500 }, 'status code is set')
|
1275 | })
|
1276 | })
|
1277 | })
|
1278 | })
|
1279 | })
|
1280 | })
|
1281 |
|
1282 | test('should log as info if error status code >= 400 and < 500 if no error handler is defined', t => {
|
1283 | t.plan(8)
|
1284 | const stream = split(JSON.parse)
|
1285 | const fastify = Fastify({
|
1286 | logger: {
|
1287 | stream: stream,
|
1288 | level: 'info'
|
1289 | }
|
1290 | })
|
1291 | fastify.get('/400', function (req, reply) {
|
1292 | t.ok(req.log)
|
1293 | reply.send(Object.assign(new Error('a 400 error'), { statusCode: 400 }))
|
1294 | })
|
1295 | fastify.get('/503', function (req, reply) {
|
1296 | t.ok(req.log)
|
1297 | reply.send(Object.assign(new Error('a 503 error'), { statusCode: 503 }))
|
1298 | })
|
1299 | fastify.listen(0, err => {
|
1300 | t.error(err)
|
1301 | fastify.server.unref()
|
1302 | http.get('http://localhost:' + fastify.server.address().port + '/400')
|
1303 | stream.once('data', listenAtLogLine => {
|
1304 | t.ok(listenAtLogLine, 'listen at log message is ok')
|
1305 | stream.once('data', line => {
|
1306 | t.equal(line.msg, 'incoming request', 'message is set')
|
1307 | stream.once('data', line => {
|
1308 | t.equal(line.level, 30, 'level is correct')
|
1309 | t.equal(line.msg, 'a 400 error', 'message is set')
|
1310 | stream.once('data', line => {
|
1311 | t.equal(line.msg, 'request completed', 'message is set')
|
1312 | t.deepEqual(line.res, { statusCode: 400 }, 'status code is set')
|
1313 | })
|
1314 | })
|
1315 | })
|
1316 | })
|
1317 | })
|
1318 | })
|
1319 |
|
1320 | test('should log as error if error status code >= 500 if no error handler is defined', t => {
|
1321 | t.plan(8)
|
1322 | const stream = split(JSON.parse)
|
1323 | const fastify = Fastify({
|
1324 | logger: {
|
1325 | stream: stream,
|
1326 | level: 'info'
|
1327 | }
|
1328 | })
|
1329 | fastify.get('/503', function (req, reply) {
|
1330 | t.ok(req.log)
|
1331 | reply.send(Object.assign(new Error('a 503 error'), { statusCode: 503 }))
|
1332 | })
|
1333 | fastify.listen(0, err => {
|
1334 | t.error(err)
|
1335 | fastify.server.unref()
|
1336 | http.get('http://localhost:' + fastify.server.address().port + '/503')
|
1337 | stream.once('data', listenAtLogLine => {
|
1338 | t.ok(listenAtLogLine, 'listen at log message is ok')
|
1339 | stream.once('data', line => {
|
1340 | t.equal(line.msg, 'incoming request', 'message is set')
|
1341 | stream.once('data', line => {
|
1342 | t.equal(line.level, 50, 'level is correct')
|
1343 | t.equal(line.msg, 'a 503 error', 'message is set')
|
1344 | stream.once('data', line => {
|
1345 | t.equal(line.msg, 'request completed', 'message is set')
|
1346 | t.deepEqual(line.res, { statusCode: 503 }, 'status code is set')
|
1347 | })
|
1348 | })
|
1349 | })
|
1350 | })
|
1351 | })
|
1352 | })
|
1353 |
|
1354 | test('should not log the error if error handler is defined', t => {
|
1355 | t.plan(7)
|
1356 | const stream = split(JSON.parse)
|
1357 | const fastify = Fastify({
|
1358 | logger: {
|
1359 | stream: stream,
|
1360 | level: 'info'
|
1361 | }
|
1362 | })
|
1363 | fastify.get('/error', function (req, reply) {
|
1364 | t.ok(req.log)
|
1365 | reply.send(new Error('something happened'))
|
1366 | })
|
1367 | fastify.setErrorHandler((err, req, reply) => {
|
1368 | reply.send(err)
|
1369 | })
|
1370 | fastify.listen(0, err => {
|
1371 | t.error(err)
|
1372 | fastify.server.unref()
|
1373 | http.get('http://localhost:' + fastify.server.address().port + '/error')
|
1374 | stream.once('data', listenAtLogLine => {
|
1375 | t.ok(listenAtLogLine, 'listen at log message is ok')
|
1376 | stream.once('data', line => {
|
1377 | t.equal(line.msg, 'incoming request', 'message is set')
|
1378 | stream.once('data', line => {
|
1379 | t.equal(line.level, 30, 'level is correct')
|
1380 | t.equal(line.msg, 'request completed', 'message is set')
|
1381 | t.deepEqual(line.res, { statusCode: 500 }, 'status code is set')
|
1382 | })
|
1383 | })
|
1384 | })
|
1385 | })
|
1386 | })
|
1387 |
|
1388 | test('should not rely on raw request to log errors', t => {
|
1389 | t.plan(7)
|
1390 | const stream = split(JSON.parse)
|
1391 | const fastify = Fastify({
|
1392 | modifyCoreObjects: false,
|
1393 | logger: {
|
1394 | stream: stream,
|
1395 | level: 'info'
|
1396 | }
|
1397 | })
|
1398 | fastify.get('/error', function (req, reply) {
|
1399 | t.ok(req.log)
|
1400 | reply.status(415).send(new Error('something happened'))
|
1401 | })
|
1402 | fastify.listen(0, err => {
|
1403 | t.error(err)
|
1404 | fastify.server.unref()
|
1405 | http.get('http://localhost:' + fastify.server.address().port + '/error')
|
1406 | stream.once('data', listenAtLogLine => {
|
1407 | t.ok(listenAtLogLine, 'listen at log message is ok')
|
1408 | stream.once('data', line => {
|
1409 | t.equal(line.msg, 'incoming request', 'message is set')
|
1410 | stream.once('data', line => {
|
1411 | t.equal(line.level, 30, 'level is correct')
|
1412 | t.equal(line.msg, 'something happened', 'message is set')
|
1413 | t.deepEqual(line.res, { statusCode: 415 }, 'status code is set')
|
1414 | })
|
1415 | })
|
1416 | })
|
1417 | })
|
1418 | })
|
1419 |
|
1420 | test('should redact the authorization header if so specified', t => {
|
1421 | t.plan(7)
|
1422 | const stream = split(JSON.parse)
|
1423 | const fastify = Fastify({
|
1424 | logger: {
|
1425 | stream: stream,
|
1426 | redact: ['req.headers.authorization'],
|
1427 | level: 'info',
|
1428 | serializers: {
|
1429 | req (req) {
|
1430 | return {
|
1431 | method: req.method,
|
1432 | url: req.url,
|
1433 | headers: req.headers,
|
1434 | hostname: req.hostname,
|
1435 | remoteAddress: req.ip,
|
1436 | remotePort: req.connection.remotePort
|
1437 | }
|
1438 | }
|
1439 | }
|
1440 | }
|
1441 | })
|
1442 | fastify.get('/', function (req, reply) {
|
1443 | t.is(req.headers.authorization, 'Bearer abcde')
|
1444 | reply.send({ hello: 'world' })
|
1445 | })
|
1446 | stream.once('data', listenAtLogLine => {
|
1447 | t.ok(listenAtLogLine, 'listen at log message is ok')
|
1448 | stream.once('data', line => {
|
1449 | t.equal(line.req.headers.authorization, '[Redacted]', 'authorization is redacted')
|
1450 | })
|
1451 | })
|
1452 | fastify.listen(0, err => {
|
1453 | t.error(err)
|
1454 | fastify.server.unref()
|
1455 | sget({
|
1456 | method: 'GET',
|
1457 | url: 'http://localhost:' + fastify.server.address().port,
|
1458 | headers: {
|
1459 | authorization: 'Bearer abcde'
|
1460 | }
|
1461 | }, (err, response, body) => {
|
1462 | t.error(err)
|
1463 | t.strictEqual(response.statusCode, 200)
|
1464 | t.deepEqual(body.toString(), JSON.stringify({ hello: 'world' }))
|
1465 | })
|
1466 | })
|
1467 | })
|
1468 |
|
1469 | test('should not log incoming request and outgoing response when disabled', t => {
|
1470 | t.plan(3)
|
1471 | const lines = []
|
1472 | const dest = new stream.Writable({
|
1473 | write: function (chunk, enc, cb) {
|
1474 | lines.push(JSON.parse(chunk))
|
1475 | cb()
|
1476 | }
|
1477 | })
|
1478 | const fastify = Fastify({ disableRequestLogging: true, logger: { level: 'info', stream: dest } })
|
1479 |
|
1480 | fastify.get('/500', (req, reply) => {
|
1481 | reply.code(500).send(Error('500 error'))
|
1482 | })
|
1483 |
|
1484 | fastify.inject({
|
1485 | url: '/500',
|
1486 | method: 'GET'
|
1487 | }, (e, res) => {
|
1488 | t.is(lines.length, 1)
|
1489 | t.ok(lines[0].msg)
|
1490 | t.is(lines[0].msg, '500 error')
|
1491 | })
|
1492 | })
|