fastify 4.23.2 → 4.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/docs/Guides/Ecosystem.md +6 -0
- package/docs/Reference/Hooks.md +1 -0
- package/docs/Reference/Plugins.md +1 -1
- package/docs/Reference/Reply.md +4 -3
- package/docs/Reference/Request.md +3 -2
- package/docs/Reference/Server.md +31 -3
- package/docs/Reference/Type-Providers.md +2 -2
- package/docs/Reference/TypeScript.md +21 -7
- package/fastify.d.ts +2 -2
- package/fastify.js +8 -1
- package/lib/contentTypeParser.js +1 -1
- package/lib/reply.js +20 -3
- package/lib/reqIdGenFactory.js +15 -9
- package/lib/request.js +1 -1
- package/lib/route.js +18 -3
- package/lib/schemas.js +3 -3
- package/lib/warnings.js +3 -1
- package/package.json +2 -2
- package/test/async-dispose.test.js +21 -0
- package/test/constrained-routes.test.js +127 -3
- package/test/hooks-async.test.js +160 -10
- package/test/input-validation.js +3 -3
- package/test/internals/reply.test.js +33 -4
- package/test/logger/instantiation.test.js +338 -0
- package/test/logger/logger-test-utils.js +47 -0
- package/test/logger/logging.test.js +406 -0
- package/test/logger/options.test.js +500 -0
- package/test/logger/request.test.js +292 -0
- package/test/logger/response.test.js +184 -0
- package/test/reply-code.test.js +64 -0
- package/test/types/reply.test-d.ts +3 -3
- package/test/types/request.test-d.ts +9 -9
- package/test/types/type-provider.test-d.ts +89 -0
- package/test/types/using.test-d.ts +14 -0
- package/types/context.d.ts +9 -2
- package/types/instance.d.ts +4 -1
- package/types/plugin.d.ts +2 -1
- package/types/reply.d.ts +2 -2
- package/types/request.d.ts +3 -3
- package/types/route.d.ts +5 -5
- package/test/serial/logger.0.test.js +0 -866
- package/test/serial/logger.1.test.js +0 -862
- /package/test/{serial → logger}/tap-parallel-not-ok +0 -0
|
@@ -1,866 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const http = require('node:http')
|
|
4
|
-
const stream = require('node:stream')
|
|
5
|
-
|
|
6
|
-
const t = require('tap')
|
|
7
|
-
const split = require('split2')
|
|
8
|
-
const pino = require('pino')
|
|
9
|
-
|
|
10
|
-
const Fastify = require('../../fastify')
|
|
11
|
-
const helper = require('../helper')
|
|
12
|
-
const { FST_ERR_LOG_INVALID_LOGGER } = require('../../lib/errors')
|
|
13
|
-
const { on } = stream
|
|
14
|
-
|
|
15
|
-
function createDeferredPromise () {
|
|
16
|
-
const promise = {}
|
|
17
|
-
promise.promise = new Promise(function (resolve) {
|
|
18
|
-
promise.resolve = resolve
|
|
19
|
-
})
|
|
20
|
-
return promise
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function request (url, cleanup = () => { }) {
|
|
24
|
-
const promise = createDeferredPromise()
|
|
25
|
-
http.get(url, (res) => {
|
|
26
|
-
const chunks = []
|
|
27
|
-
// we consume the response
|
|
28
|
-
res.on('data', function (chunk) {
|
|
29
|
-
chunks.push(chunk)
|
|
30
|
-
})
|
|
31
|
-
res.once('end', function () {
|
|
32
|
-
cleanup(res, Buffer.concat(chunks).toString())
|
|
33
|
-
promise.resolve()
|
|
34
|
-
})
|
|
35
|
-
})
|
|
36
|
-
return promise.promise
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
t.test('test log stream', (t) => {
|
|
40
|
-
t.setTimeout(60000)
|
|
41
|
-
|
|
42
|
-
let localhost
|
|
43
|
-
let localhostForURL
|
|
44
|
-
|
|
45
|
-
t.plan(22)
|
|
46
|
-
|
|
47
|
-
t.before(async function () {
|
|
48
|
-
[localhost, localhostForURL] = await helper.getLoopbackHost()
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
t.test('defaults to info level', async (t) => {
|
|
52
|
-
const lines = [
|
|
53
|
-
{ reqId: /req-/, req: { method: 'GET' }, msg: 'incoming request' },
|
|
54
|
-
{ reqId: /req-/, res: { statusCode: 200 }, msg: 'request completed' }
|
|
55
|
-
]
|
|
56
|
-
t.plan(lines.length * 2 + 1)
|
|
57
|
-
const stream = split(JSON.parse)
|
|
58
|
-
const fastify = Fastify({
|
|
59
|
-
logger: {
|
|
60
|
-
stream
|
|
61
|
-
}
|
|
62
|
-
})
|
|
63
|
-
t.teardown(fastify.close.bind(fastify))
|
|
64
|
-
|
|
65
|
-
fastify.get('/', function (req, reply) {
|
|
66
|
-
t.ok(req.log)
|
|
67
|
-
reply.send({ hello: 'world' })
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
await fastify.ready()
|
|
71
|
-
await fastify.listen({ port: 0 })
|
|
72
|
-
|
|
73
|
-
await request(`http://${localhostForURL}:` + fastify.server.address().port)
|
|
74
|
-
|
|
75
|
-
let id
|
|
76
|
-
for await (const [line] of on(stream, 'data')) {
|
|
77
|
-
// we skip the non-request log
|
|
78
|
-
if (typeof line.reqId !== 'string') continue
|
|
79
|
-
if (id === undefined && line.reqId) id = line.reqId
|
|
80
|
-
if (id !== undefined && line.reqId) t.equal(line.reqId, id)
|
|
81
|
-
t.match(line, lines.shift())
|
|
82
|
-
if (lines.length === 0) break
|
|
83
|
-
}
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
t.test('test log stream', async (t) => {
|
|
87
|
-
const lines = [
|
|
88
|
-
{ msg: /^Server listening at / },
|
|
89
|
-
{ reqId: /req-/, req: { method: 'GET' }, msg: 'incoming request' },
|
|
90
|
-
{ reqId: /req-/, res: { statusCode: 200 }, msg: 'request completed' }
|
|
91
|
-
]
|
|
92
|
-
t.plan(lines.length + 3)
|
|
93
|
-
|
|
94
|
-
const stream = split(JSON.parse)
|
|
95
|
-
const fastify = Fastify({
|
|
96
|
-
logger: {
|
|
97
|
-
stream,
|
|
98
|
-
level: 'info'
|
|
99
|
-
}
|
|
100
|
-
})
|
|
101
|
-
t.teardown(fastify.close.bind(fastify))
|
|
102
|
-
|
|
103
|
-
fastify.get('/', function (req, reply) {
|
|
104
|
-
t.ok(req.log)
|
|
105
|
-
reply.send({ hello: 'world' })
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
await fastify.ready()
|
|
109
|
-
await fastify.listen({ port: 0, host: localhost })
|
|
110
|
-
|
|
111
|
-
await request(`http://${localhostForURL}:` + fastify.server.address().port)
|
|
112
|
-
|
|
113
|
-
let id
|
|
114
|
-
for await (const [line] of on(stream, 'data')) {
|
|
115
|
-
if (id === undefined && line.reqId) id = line.reqId
|
|
116
|
-
if (id !== undefined && line.reqId) t.equal(line.reqId, id)
|
|
117
|
-
t.match(line, lines.shift())
|
|
118
|
-
if (lines.length === 0) break
|
|
119
|
-
}
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
t.test('test error log stream', async (t) => {
|
|
123
|
-
const lines = [
|
|
124
|
-
{ msg: /^Server listening at / },
|
|
125
|
-
{ reqId: /req-/, req: { method: 'GET' }, msg: 'incoming request' },
|
|
126
|
-
{ reqId: /req-/, res: { statusCode: 500 }, msg: 'kaboom' },
|
|
127
|
-
{ reqId: /req-/, res: { statusCode: 500 }, msg: 'request completed' }
|
|
128
|
-
]
|
|
129
|
-
t.plan(lines.length + 4)
|
|
130
|
-
|
|
131
|
-
const stream = split(JSON.parse)
|
|
132
|
-
const fastify = Fastify({
|
|
133
|
-
logger: {
|
|
134
|
-
stream,
|
|
135
|
-
level: 'info'
|
|
136
|
-
}
|
|
137
|
-
})
|
|
138
|
-
t.teardown(fastify.close.bind(fastify))
|
|
139
|
-
|
|
140
|
-
fastify.get('/error', function (req, reply) {
|
|
141
|
-
t.ok(req.log)
|
|
142
|
-
reply.send(new Error('kaboom'))
|
|
143
|
-
})
|
|
144
|
-
|
|
145
|
-
await fastify.ready()
|
|
146
|
-
await fastify.listen({ port: 0, host: localhost })
|
|
147
|
-
|
|
148
|
-
await request(`http://${localhostForURL}:` + fastify.server.address().port + '/error')
|
|
149
|
-
|
|
150
|
-
let id
|
|
151
|
-
for await (const [line] of on(stream, 'data')) {
|
|
152
|
-
if (id === undefined && line.reqId) id = line.reqId
|
|
153
|
-
if (id !== undefined && line.reqId) t.equal(line.reqId, id)
|
|
154
|
-
t.match(line, lines.shift())
|
|
155
|
-
if (lines.length === 0) break
|
|
156
|
-
}
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
t.test('can use external logger instance', async (t) => {
|
|
160
|
-
const lines = [/^Server listening at /, /^incoming request$/, /^log success$/, /^request completed$/]
|
|
161
|
-
t.plan(lines.length + 1)
|
|
162
|
-
|
|
163
|
-
const stream = split(JSON.parse)
|
|
164
|
-
|
|
165
|
-
const logger = require('pino')(stream)
|
|
166
|
-
|
|
167
|
-
const fastify = Fastify({ logger })
|
|
168
|
-
t.teardown(fastify.close.bind(fastify))
|
|
169
|
-
|
|
170
|
-
fastify.get('/foo', function (req, reply) {
|
|
171
|
-
t.ok(req.log)
|
|
172
|
-
req.log.info('log success')
|
|
173
|
-
reply.send({ hello: 'world' })
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
await fastify.ready()
|
|
177
|
-
await fastify.listen({ port: 0, host: localhost })
|
|
178
|
-
|
|
179
|
-
await request(`http://${localhostForURL}:` + fastify.server.address().port + '/foo')
|
|
180
|
-
|
|
181
|
-
for await (const [line] of on(stream, 'data')) {
|
|
182
|
-
const regex = lines.shift()
|
|
183
|
-
t.ok(regex.test(line.msg), '"' + line.msg + '" dont match "' + regex + '"')
|
|
184
|
-
if (lines.length === 0) break
|
|
185
|
-
}
|
|
186
|
-
})
|
|
187
|
-
|
|
188
|
-
t.test('can use external logger instance with custom serializer', async (t) => {
|
|
189
|
-
const lines = [['level', 30], ['req', { url: '/foo' }], ['level', 30], ['res', { statusCode: 200 }]]
|
|
190
|
-
t.plan(lines.length + 1)
|
|
191
|
-
|
|
192
|
-
const stream = split(JSON.parse)
|
|
193
|
-
const logger = require('pino')({
|
|
194
|
-
level: 'info',
|
|
195
|
-
serializers: {
|
|
196
|
-
req: function (req) {
|
|
197
|
-
return {
|
|
198
|
-
url: req.url
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}, stream)
|
|
203
|
-
|
|
204
|
-
const fastify = Fastify({
|
|
205
|
-
logger
|
|
206
|
-
})
|
|
207
|
-
t.teardown(fastify.close.bind(fastify))
|
|
208
|
-
|
|
209
|
-
fastify.get('/foo', function (req, reply) {
|
|
210
|
-
t.ok(req.log)
|
|
211
|
-
req.log.info('log success')
|
|
212
|
-
reply.send({ hello: 'world' })
|
|
213
|
-
})
|
|
214
|
-
|
|
215
|
-
await fastify.ready()
|
|
216
|
-
await fastify.listen({ port: 0, host: localhost })
|
|
217
|
-
|
|
218
|
-
await request(`http://${localhostForURL}:` + fastify.server.address().port + '/foo')
|
|
219
|
-
|
|
220
|
-
for await (const [line] of on(stream, 'data')) {
|
|
221
|
-
const check = lines.shift()
|
|
222
|
-
const key = check[0]
|
|
223
|
-
const value = check[1]
|
|
224
|
-
t.same(line[key], value)
|
|
225
|
-
if (lines.length === 0) break
|
|
226
|
-
}
|
|
227
|
-
})
|
|
228
|
-
|
|
229
|
-
t.test('should throw in case the external logger provided does not have a child method', async (t) => {
|
|
230
|
-
t.plan(1)
|
|
231
|
-
const loggerInstance = {
|
|
232
|
-
info: console.info,
|
|
233
|
-
error: console.error,
|
|
234
|
-
debug: console.debug,
|
|
235
|
-
fatal: console.error,
|
|
236
|
-
warn: console.warn,
|
|
237
|
-
trace: console.trace
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
try {
|
|
241
|
-
const fastify = Fastify({ logger: loggerInstance })
|
|
242
|
-
await fastify.ready()
|
|
243
|
-
} catch (err) {
|
|
244
|
-
t.equal(
|
|
245
|
-
err instanceof FST_ERR_LOG_INVALID_LOGGER,
|
|
246
|
-
true,
|
|
247
|
-
"Invalid logger object provided. The logger instance should have these functions(s): 'child'."
|
|
248
|
-
)
|
|
249
|
-
}
|
|
250
|
-
})
|
|
251
|
-
|
|
252
|
-
t.test('should throw in case a partially matching logger is provided', async (t) => {
|
|
253
|
-
t.plan(1)
|
|
254
|
-
|
|
255
|
-
try {
|
|
256
|
-
const fastify = Fastify({ logger: console })
|
|
257
|
-
await fastify.ready()
|
|
258
|
-
} catch (err) {
|
|
259
|
-
t.equal(
|
|
260
|
-
err instanceof FST_ERR_LOG_INVALID_LOGGER,
|
|
261
|
-
true,
|
|
262
|
-
"Invalid logger object provided. The logger instance should have these functions(s): 'fatal,child'."
|
|
263
|
-
)
|
|
264
|
-
}
|
|
265
|
-
})
|
|
266
|
-
|
|
267
|
-
t.test('expose the logger', async (t) => {
|
|
268
|
-
t.plan(2)
|
|
269
|
-
const stream = split(JSON.parse)
|
|
270
|
-
const fastify = Fastify({
|
|
271
|
-
logger: {
|
|
272
|
-
stream,
|
|
273
|
-
level: 'info'
|
|
274
|
-
}
|
|
275
|
-
})
|
|
276
|
-
t.teardown(fastify.close.bind(fastify))
|
|
277
|
-
|
|
278
|
-
await fastify.ready()
|
|
279
|
-
|
|
280
|
-
t.ok(fastify.log)
|
|
281
|
-
t.same(typeof fastify.log, 'object')
|
|
282
|
-
})
|
|
283
|
-
|
|
284
|
-
t.test('The request id header key can be customized', async (t) => {
|
|
285
|
-
const lines = ['incoming request', 'some log message', 'request completed']
|
|
286
|
-
t.plan(lines.length * 2 + 2)
|
|
287
|
-
const REQUEST_ID = '42'
|
|
288
|
-
|
|
289
|
-
const stream = split(JSON.parse)
|
|
290
|
-
const fastify = Fastify({
|
|
291
|
-
logger: { stream, level: 'info' },
|
|
292
|
-
requestIdHeader: 'my-custom-request-id'
|
|
293
|
-
})
|
|
294
|
-
t.teardown(fastify.close.bind(fastify))
|
|
295
|
-
|
|
296
|
-
fastify.get('/', (req, reply) => {
|
|
297
|
-
t.equal(req.id, REQUEST_ID)
|
|
298
|
-
req.log.info('some log message')
|
|
299
|
-
reply.send({ id: req.id })
|
|
300
|
-
})
|
|
301
|
-
|
|
302
|
-
const response = await fastify.inject({ method: 'GET', url: '/', headers: { 'my-custom-request-id': REQUEST_ID } })
|
|
303
|
-
const body = await response.json()
|
|
304
|
-
t.equal(body.id, REQUEST_ID)
|
|
305
|
-
|
|
306
|
-
for await (const [line] of on(stream, 'data')) {
|
|
307
|
-
t.equal(line.reqId, REQUEST_ID)
|
|
308
|
-
t.equal(line.msg, lines.shift(), 'message is set')
|
|
309
|
-
if (lines.length === 0) break
|
|
310
|
-
}
|
|
311
|
-
})
|
|
312
|
-
|
|
313
|
-
t.test('The request id header key can be ignored', async (t) => {
|
|
314
|
-
const lines = ['incoming request', 'some log message', 'request completed']
|
|
315
|
-
t.plan(lines.length * 2 + 2)
|
|
316
|
-
const REQUEST_ID = 'ignore-me'
|
|
317
|
-
|
|
318
|
-
const stream = split(JSON.parse)
|
|
319
|
-
const fastify = Fastify({
|
|
320
|
-
logger: { stream, level: 'info' },
|
|
321
|
-
requestIdHeader: false
|
|
322
|
-
})
|
|
323
|
-
t.teardown(fastify.close.bind(fastify))
|
|
324
|
-
|
|
325
|
-
fastify.get('/', (req, reply) => {
|
|
326
|
-
t.equal(req.id, 'req-1')
|
|
327
|
-
req.log.info('some log message')
|
|
328
|
-
reply.send({ id: req.id })
|
|
329
|
-
})
|
|
330
|
-
const response = await fastify.inject({ method: 'GET', url: '/', headers: { 'request-id': REQUEST_ID } })
|
|
331
|
-
const body = await response.json()
|
|
332
|
-
t.equal(body.id, 'req-1')
|
|
333
|
-
|
|
334
|
-
for await (const [line] of on(stream, 'data')) {
|
|
335
|
-
t.equal(line.reqId, 'req-1')
|
|
336
|
-
t.equal(line.msg, lines.shift(), 'message is set')
|
|
337
|
-
if (lines.length === 0) break
|
|
338
|
-
}
|
|
339
|
-
})
|
|
340
|
-
|
|
341
|
-
t.test('The request id header key can be customized along with a custom id generator', async (t) => {
|
|
342
|
-
const REQUEST_ID = '42'
|
|
343
|
-
const matches = [
|
|
344
|
-
{ reqId: REQUEST_ID, msg: /incoming request/ },
|
|
345
|
-
{ reqId: REQUEST_ID, msg: /some log message/ },
|
|
346
|
-
{ reqId: REQUEST_ID, msg: /request completed/ },
|
|
347
|
-
{ reqId: 'foo', msg: /incoming request/ },
|
|
348
|
-
{ reqId: 'foo', msg: /some log message 2/ },
|
|
349
|
-
{ reqId: 'foo', msg: /request completed/ }
|
|
350
|
-
]
|
|
351
|
-
t.plan(matches.length + 4)
|
|
352
|
-
|
|
353
|
-
const stream = split(JSON.parse)
|
|
354
|
-
const fastify = Fastify({
|
|
355
|
-
logger: { stream, level: 'info' },
|
|
356
|
-
requestIdHeader: 'my-custom-request-id',
|
|
357
|
-
genReqId (req) {
|
|
358
|
-
return 'foo'
|
|
359
|
-
}
|
|
360
|
-
})
|
|
361
|
-
t.teardown(fastify.close.bind(fastify))
|
|
362
|
-
|
|
363
|
-
fastify.get('/one', (req, reply) => {
|
|
364
|
-
t.equal(req.id, REQUEST_ID)
|
|
365
|
-
req.log.info('some log message')
|
|
366
|
-
reply.send({ id: req.id })
|
|
367
|
-
})
|
|
368
|
-
|
|
369
|
-
fastify.get('/two', (req, reply) => {
|
|
370
|
-
t.equal(req.id, 'foo')
|
|
371
|
-
req.log.info('some log message 2')
|
|
372
|
-
reply.send({ id: req.id })
|
|
373
|
-
})
|
|
374
|
-
|
|
375
|
-
{
|
|
376
|
-
const response = await fastify.inject({ method: 'GET', url: '/one', headers: { 'my-custom-request-id': REQUEST_ID } })
|
|
377
|
-
const body = await response.json()
|
|
378
|
-
t.equal(body.id, REQUEST_ID)
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
{
|
|
382
|
-
const response = await fastify.inject({ method: 'GET', url: '/two' })
|
|
383
|
-
const body = await response.json()
|
|
384
|
-
t.equal(body.id, 'foo')
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
for await (const [line] of on(stream, 'data')) {
|
|
388
|
-
t.match(line, matches.shift())
|
|
389
|
-
if (matches.length === 0) break
|
|
390
|
-
}
|
|
391
|
-
})
|
|
392
|
-
|
|
393
|
-
t.test('The request id header key can be ignored along with a custom id generator', async (t) => {
|
|
394
|
-
const REQUEST_ID = 'ignore-me'
|
|
395
|
-
const matches = [
|
|
396
|
-
{ reqId: 'foo', msg: /incoming request/ },
|
|
397
|
-
{ reqId: 'foo', msg: /some log message/ },
|
|
398
|
-
{ reqId: 'foo', msg: /request completed/ },
|
|
399
|
-
{ reqId: 'foo', msg: /incoming request/ },
|
|
400
|
-
{ reqId: 'foo', msg: /some log message 2/ },
|
|
401
|
-
{ reqId: 'foo', msg: /request completed/ }
|
|
402
|
-
]
|
|
403
|
-
t.plan(matches.length + 4)
|
|
404
|
-
|
|
405
|
-
const stream = split(JSON.parse)
|
|
406
|
-
const fastify = Fastify({
|
|
407
|
-
logger: { stream, level: 'info' },
|
|
408
|
-
requestIdHeader: false,
|
|
409
|
-
genReqId (req) {
|
|
410
|
-
return 'foo'
|
|
411
|
-
}
|
|
412
|
-
})
|
|
413
|
-
t.teardown(fastify.close.bind(fastify))
|
|
414
|
-
|
|
415
|
-
fastify.get('/one', (req, reply) => {
|
|
416
|
-
t.equal(req.id, 'foo')
|
|
417
|
-
req.log.info('some log message')
|
|
418
|
-
reply.send({ id: req.id })
|
|
419
|
-
})
|
|
420
|
-
|
|
421
|
-
fastify.get('/two', (req, reply) => {
|
|
422
|
-
t.equal(req.id, 'foo')
|
|
423
|
-
req.log.info('some log message 2')
|
|
424
|
-
reply.send({ id: req.id })
|
|
425
|
-
})
|
|
426
|
-
|
|
427
|
-
{
|
|
428
|
-
const response = await fastify.inject({ method: 'GET', url: '/one', headers: { 'request-id': REQUEST_ID } })
|
|
429
|
-
const body = await response.json()
|
|
430
|
-
t.equal(body.id, 'foo')
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
{
|
|
434
|
-
const response = await fastify.inject({ method: 'GET', url: '/two' })
|
|
435
|
-
const body = await response.json()
|
|
436
|
-
t.equal(body.id, 'foo')
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
for await (const [line] of on(stream, 'data')) {
|
|
440
|
-
t.match(line, matches.shift())
|
|
441
|
-
if (matches.length === 0) break
|
|
442
|
-
}
|
|
443
|
-
})
|
|
444
|
-
|
|
445
|
-
t.test('The request id log label can be changed', async (t) => {
|
|
446
|
-
const REQUEST_ID = '42'
|
|
447
|
-
const matches = [
|
|
448
|
-
{ traceId: REQUEST_ID, msg: /incoming request/ },
|
|
449
|
-
{ traceId: REQUEST_ID, msg: /some log message/ },
|
|
450
|
-
{ traceId: REQUEST_ID, msg: /request completed/ }
|
|
451
|
-
]
|
|
452
|
-
t.plan(matches.length + 2)
|
|
453
|
-
|
|
454
|
-
const stream = split(JSON.parse)
|
|
455
|
-
const fastify = Fastify({
|
|
456
|
-
logger: { stream, level: 'info' },
|
|
457
|
-
requestIdHeader: 'my-custom-request-id',
|
|
458
|
-
requestIdLogLabel: 'traceId'
|
|
459
|
-
})
|
|
460
|
-
t.teardown(fastify.close.bind(fastify))
|
|
461
|
-
|
|
462
|
-
fastify.get('/one', (req, reply) => {
|
|
463
|
-
t.equal(req.id, REQUEST_ID)
|
|
464
|
-
req.log.info('some log message')
|
|
465
|
-
reply.send({ id: req.id })
|
|
466
|
-
})
|
|
467
|
-
|
|
468
|
-
{
|
|
469
|
-
const response = await fastify.inject({ method: 'GET', url: '/one', headers: { 'my-custom-request-id': REQUEST_ID } })
|
|
470
|
-
const body = await response.json()
|
|
471
|
-
t.equal(body.id, REQUEST_ID)
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
for await (const [line] of on(stream, 'data')) {
|
|
475
|
-
t.match(line, matches.shift())
|
|
476
|
-
if (matches.length === 0) break
|
|
477
|
-
}
|
|
478
|
-
})
|
|
479
|
-
|
|
480
|
-
t.test('The logger should accept custom serializer', async (t) => {
|
|
481
|
-
const lines = [
|
|
482
|
-
{ msg: /^Server listening at / },
|
|
483
|
-
{ req: { url: '/custom' }, msg: 'incoming request' },
|
|
484
|
-
{ res: { statusCode: 500 }, msg: 'kaboom' },
|
|
485
|
-
{ res: { statusCode: 500 }, msg: 'request completed' }
|
|
486
|
-
]
|
|
487
|
-
t.plan(lines.length + 1)
|
|
488
|
-
|
|
489
|
-
const stream = split(JSON.parse)
|
|
490
|
-
const fastify = Fastify({
|
|
491
|
-
logger: {
|
|
492
|
-
stream,
|
|
493
|
-
level: 'info',
|
|
494
|
-
serializers: {
|
|
495
|
-
req: function (req) {
|
|
496
|
-
return {
|
|
497
|
-
url: req.url
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
})
|
|
503
|
-
t.teardown(fastify.close.bind(fastify))
|
|
504
|
-
|
|
505
|
-
fastify.get('/custom', function (req, reply) {
|
|
506
|
-
t.ok(req.log)
|
|
507
|
-
reply.send(new Error('kaboom'))
|
|
508
|
-
})
|
|
509
|
-
|
|
510
|
-
await fastify.ready()
|
|
511
|
-
await fastify.listen({ port: 0, host: localhost })
|
|
512
|
-
|
|
513
|
-
await request(`http://${localhostForURL}:` + fastify.server.address().port + '/custom')
|
|
514
|
-
|
|
515
|
-
for await (const [line] of on(stream, 'data')) {
|
|
516
|
-
t.match(line, lines.shift())
|
|
517
|
-
if (lines.length === 0) break
|
|
518
|
-
}
|
|
519
|
-
})
|
|
520
|
-
|
|
521
|
-
t.test('reply.send logs an error if called twice in a row', async (t) => {
|
|
522
|
-
const lines = [
|
|
523
|
-
'incoming request',
|
|
524
|
-
'request completed',
|
|
525
|
-
'Reply was already sent, did you forget to "return reply" in "/" (GET)?',
|
|
526
|
-
'Reply was already sent, did you forget to "return reply" in "/" (GET)?'
|
|
527
|
-
]
|
|
528
|
-
t.plan(lines.length + 1)
|
|
529
|
-
|
|
530
|
-
const stream = split(JSON.parse)
|
|
531
|
-
const logger = pino(stream)
|
|
532
|
-
|
|
533
|
-
const fastify = Fastify({
|
|
534
|
-
logger
|
|
535
|
-
})
|
|
536
|
-
t.teardown(fastify.close.bind(fastify))
|
|
537
|
-
|
|
538
|
-
fastify.get('/', (req, reply) => {
|
|
539
|
-
reply.send({ hello: 'world' })
|
|
540
|
-
reply.send({ hello: 'world2' })
|
|
541
|
-
reply.send({ hello: 'world3' })
|
|
542
|
-
})
|
|
543
|
-
|
|
544
|
-
const response = await fastify.inject({ method: 'GET', url: '/' })
|
|
545
|
-
const body = await response.json()
|
|
546
|
-
t.same(body, { hello: 'world' })
|
|
547
|
-
|
|
548
|
-
for await (const [line] of on(stream, 'data')) {
|
|
549
|
-
t.same(line.msg, lines.shift())
|
|
550
|
-
if (lines.length === 0) break
|
|
551
|
-
}
|
|
552
|
-
})
|
|
553
|
-
|
|
554
|
-
t.test('logger can be silented', (t) => {
|
|
555
|
-
t.plan(17)
|
|
556
|
-
const fastify = Fastify({
|
|
557
|
-
logger: false
|
|
558
|
-
})
|
|
559
|
-
t.teardown(fastify.close.bind(fastify))
|
|
560
|
-
t.ok(fastify.log)
|
|
561
|
-
t.equal(typeof fastify.log, 'object')
|
|
562
|
-
t.equal(typeof fastify.log.fatal, 'function')
|
|
563
|
-
t.equal(typeof fastify.log.error, 'function')
|
|
564
|
-
t.equal(typeof fastify.log.warn, 'function')
|
|
565
|
-
t.equal(typeof fastify.log.info, 'function')
|
|
566
|
-
t.equal(typeof fastify.log.debug, 'function')
|
|
567
|
-
t.equal(typeof fastify.log.trace, 'function')
|
|
568
|
-
t.equal(typeof fastify.log.child, 'function')
|
|
569
|
-
|
|
570
|
-
const childLog = fastify.log.child()
|
|
571
|
-
|
|
572
|
-
t.equal(typeof childLog, 'object')
|
|
573
|
-
t.equal(typeof childLog.fatal, 'function')
|
|
574
|
-
t.equal(typeof childLog.error, 'function')
|
|
575
|
-
t.equal(typeof childLog.warn, 'function')
|
|
576
|
-
t.equal(typeof childLog.info, 'function')
|
|
577
|
-
t.equal(typeof childLog.debug, 'function')
|
|
578
|
-
t.equal(typeof childLog.trace, 'function')
|
|
579
|
-
t.equal(typeof childLog.child, 'function')
|
|
580
|
-
})
|
|
581
|
-
|
|
582
|
-
t.test('Should set a custom logLevel for a plugin', async (t) => {
|
|
583
|
-
const lines = ['incoming request', 'Hello', 'request completed']
|
|
584
|
-
t.plan(lines.length + 2)
|
|
585
|
-
|
|
586
|
-
const stream = split(JSON.parse)
|
|
587
|
-
|
|
588
|
-
const logger = pino({ level: 'error' }, stream)
|
|
589
|
-
|
|
590
|
-
const fastify = Fastify({
|
|
591
|
-
logger
|
|
592
|
-
})
|
|
593
|
-
t.teardown(fastify.close.bind(fastify))
|
|
594
|
-
|
|
595
|
-
fastify.get('/', (req, reply) => {
|
|
596
|
-
req.log.info('Not Exist') // we should not see this log
|
|
597
|
-
reply.send({ hello: 'world' })
|
|
598
|
-
})
|
|
599
|
-
|
|
600
|
-
fastify.register(function (instance, opts, done) {
|
|
601
|
-
instance.get('/plugin', (req, reply) => {
|
|
602
|
-
req.log.info('Hello') // we should see this log
|
|
603
|
-
reply.send({ hello: 'world' })
|
|
604
|
-
})
|
|
605
|
-
done()
|
|
606
|
-
}, { logLevel: 'info' })
|
|
607
|
-
|
|
608
|
-
await fastify.ready()
|
|
609
|
-
|
|
610
|
-
{
|
|
611
|
-
const response = await fastify.inject({ method: 'GET', url: '/' })
|
|
612
|
-
const body = await response.json()
|
|
613
|
-
t.same(body, { hello: 'world' })
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
{
|
|
617
|
-
const response = await fastify.inject({ method: 'GET', url: '/plugin' })
|
|
618
|
-
const body = await response.json()
|
|
619
|
-
t.same(body, { hello: 'world' })
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
for await (const [line] of on(stream, 'data')) {
|
|
623
|
-
t.same(line.msg, lines.shift())
|
|
624
|
-
if (lines.length === 0) break
|
|
625
|
-
}
|
|
626
|
-
})
|
|
627
|
-
|
|
628
|
-
t.test('Should set a custom logSerializers for a plugin', async (t) => {
|
|
629
|
-
const lines = ['incoming request', 'XHello', 'request completed']
|
|
630
|
-
t.plan(lines.length + 1)
|
|
631
|
-
|
|
632
|
-
const stream = split(JSON.parse)
|
|
633
|
-
|
|
634
|
-
const logger = pino({ level: 'error' }, stream)
|
|
635
|
-
|
|
636
|
-
const fastify = Fastify({
|
|
637
|
-
logger
|
|
638
|
-
})
|
|
639
|
-
t.teardown(fastify.close.bind(fastify))
|
|
640
|
-
|
|
641
|
-
fastify.register(function (instance, opts, done) {
|
|
642
|
-
instance.get('/plugin', (req, reply) => {
|
|
643
|
-
req.log.info({ test: 'Hello' }) // we should see this log
|
|
644
|
-
reply.send({ hello: 'world' })
|
|
645
|
-
})
|
|
646
|
-
done()
|
|
647
|
-
}, { logLevel: 'info', logSerializers: { test: value => 'X' + value } })
|
|
648
|
-
|
|
649
|
-
await fastify.ready()
|
|
650
|
-
|
|
651
|
-
{
|
|
652
|
-
const response = await fastify.inject({ method: 'GET', url: '/plugin' })
|
|
653
|
-
const body = await response.json()
|
|
654
|
-
t.same(body, { hello: 'world' })
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
for await (const [line] of on(stream, 'data')) {
|
|
658
|
-
// either test or msg
|
|
659
|
-
t.equal(line.test || line.msg, lines.shift())
|
|
660
|
-
if (lines.length === 0) break
|
|
661
|
-
}
|
|
662
|
-
})
|
|
663
|
-
|
|
664
|
-
t.test('Should set a custom logLevel for every plugin', async (t) => {
|
|
665
|
-
const lines = ['incoming request', 'info', 'request completed', 'incoming request', 'debug', 'request completed']
|
|
666
|
-
t.plan(lines.length * 2 + 3)
|
|
667
|
-
|
|
668
|
-
const stream = split(JSON.parse)
|
|
669
|
-
|
|
670
|
-
const logger = pino({ level: 'error' }, stream)
|
|
671
|
-
|
|
672
|
-
const fastify = Fastify({
|
|
673
|
-
logger
|
|
674
|
-
})
|
|
675
|
-
t.teardown(fastify.close.bind(fastify))
|
|
676
|
-
|
|
677
|
-
fastify.get('/', (req, reply) => {
|
|
678
|
-
req.log.warn('Hello') // we should not see this log
|
|
679
|
-
reply.send({ hello: 'world' })
|
|
680
|
-
})
|
|
681
|
-
|
|
682
|
-
fastify.register(function (instance, opts, done) {
|
|
683
|
-
instance.get('/info', (req, reply) => {
|
|
684
|
-
req.log.info('info') // we should see this log
|
|
685
|
-
req.log.debug('hidden log')
|
|
686
|
-
reply.send({ hello: 'world' })
|
|
687
|
-
})
|
|
688
|
-
done()
|
|
689
|
-
}, { logLevel: 'info' })
|
|
690
|
-
|
|
691
|
-
fastify.register(function (instance, opts, done) {
|
|
692
|
-
instance.get('/debug', (req, reply) => {
|
|
693
|
-
req.log.debug('debug') // we should see this log
|
|
694
|
-
req.log.trace('hidden log')
|
|
695
|
-
reply.send({ hello: 'world' })
|
|
696
|
-
})
|
|
697
|
-
done()
|
|
698
|
-
}, { logLevel: 'debug' })
|
|
699
|
-
|
|
700
|
-
await fastify.ready()
|
|
701
|
-
|
|
702
|
-
{
|
|
703
|
-
const response = await fastify.inject({ method: 'GET', url: '/' })
|
|
704
|
-
const body = await response.json()
|
|
705
|
-
t.same(body, { hello: 'world' })
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
{
|
|
709
|
-
const response = await fastify.inject({ method: 'GET', url: '/info' })
|
|
710
|
-
const body = await response.json()
|
|
711
|
-
t.same(body, { hello: 'world' })
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
{
|
|
715
|
-
const response = await fastify.inject({ method: 'GET', url: '/debug' })
|
|
716
|
-
const body = await response.json()
|
|
717
|
-
t.same(body, { hello: 'world' })
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
for await (const [line] of on(stream, 'data')) {
|
|
721
|
-
t.ok(line.level === 30 || line.level === 20)
|
|
722
|
-
t.equal(line.msg, lines.shift())
|
|
723
|
-
if (lines.length === 0) break
|
|
724
|
-
}
|
|
725
|
-
})
|
|
726
|
-
|
|
727
|
-
t.test('Should set a custom logSerializers for every plugin', async (t) => {
|
|
728
|
-
const lines = ['incoming request', 'Hello', 'request completed', 'incoming request', 'XHello', 'request completed', 'incoming request', 'ZHello', 'request completed']
|
|
729
|
-
t.plan(lines.length + 3)
|
|
730
|
-
|
|
731
|
-
const stream = split(JSON.parse)
|
|
732
|
-
|
|
733
|
-
const logger = pino({ level: 'info' }, stream)
|
|
734
|
-
const fastify = Fastify({
|
|
735
|
-
logger
|
|
736
|
-
})
|
|
737
|
-
t.teardown(fastify.close.bind(fastify))
|
|
738
|
-
|
|
739
|
-
fastify.get('/', (req, reply) => {
|
|
740
|
-
req.log.warn({ test: 'Hello' })
|
|
741
|
-
reply.send({ hello: 'world' })
|
|
742
|
-
})
|
|
743
|
-
|
|
744
|
-
fastify.register(function (instance, opts, done) {
|
|
745
|
-
instance.get('/test1', (req, reply) => {
|
|
746
|
-
req.log.info({ test: 'Hello' })
|
|
747
|
-
reply.send({ hello: 'world' })
|
|
748
|
-
})
|
|
749
|
-
done()
|
|
750
|
-
}, { logSerializers: { test: value => 'X' + value } })
|
|
751
|
-
|
|
752
|
-
fastify.register(function (instance, opts, done) {
|
|
753
|
-
instance.get('/test2', (req, reply) => {
|
|
754
|
-
req.log.info({ test: 'Hello' })
|
|
755
|
-
reply.send({ hello: 'world' })
|
|
756
|
-
})
|
|
757
|
-
done()
|
|
758
|
-
}, { logSerializers: { test: value => 'Z' + value } })
|
|
759
|
-
|
|
760
|
-
await fastify.ready()
|
|
761
|
-
|
|
762
|
-
{
|
|
763
|
-
const response = await fastify.inject({ method: 'GET', url: '/' })
|
|
764
|
-
const body = await response.json()
|
|
765
|
-
t.same(body, { hello: 'world' })
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
{
|
|
769
|
-
const response = await fastify.inject({ method: 'GET', url: '/test1' })
|
|
770
|
-
const body = await response.json()
|
|
771
|
-
t.same(body, { hello: 'world' })
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
{
|
|
775
|
-
const response = await fastify.inject({ method: 'GET', url: '/test2' })
|
|
776
|
-
const body = await response.json()
|
|
777
|
-
t.same(body, { hello: 'world' })
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
for await (const [line] of on(stream, 'data')) {
|
|
781
|
-
t.equal(line.test || line.msg, lines.shift())
|
|
782
|
-
if (lines.length === 0) break
|
|
783
|
-
}
|
|
784
|
-
})
|
|
785
|
-
|
|
786
|
-
t.test('Should override serializers from route', async (t) => {
|
|
787
|
-
const lines = ['incoming request', 'ZHello', 'request completed']
|
|
788
|
-
t.plan(lines.length + 1)
|
|
789
|
-
|
|
790
|
-
const stream = split(JSON.parse)
|
|
791
|
-
|
|
792
|
-
const logger = pino({ level: 'info' }, stream)
|
|
793
|
-
const fastify = Fastify({
|
|
794
|
-
logger
|
|
795
|
-
})
|
|
796
|
-
t.teardown(fastify.close.bind(fastify))
|
|
797
|
-
|
|
798
|
-
fastify.register(function (instance, opts, done) {
|
|
799
|
-
instance.get('/', {
|
|
800
|
-
logSerializers: {
|
|
801
|
-
test: value => 'Z' + value // should override
|
|
802
|
-
}
|
|
803
|
-
}, (req, reply) => {
|
|
804
|
-
req.log.info({ test: 'Hello' })
|
|
805
|
-
reply.send({ hello: 'world' })
|
|
806
|
-
})
|
|
807
|
-
done()
|
|
808
|
-
}, { logSerializers: { test: value => 'X' + value } })
|
|
809
|
-
|
|
810
|
-
await fastify.ready()
|
|
811
|
-
|
|
812
|
-
{
|
|
813
|
-
const response = await fastify.inject({ method: 'GET', url: '/' })
|
|
814
|
-
const body = await response.json()
|
|
815
|
-
t.same(body, { hello: 'world' })
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
for await (const [line] of on(stream, 'data')) {
|
|
819
|
-
t.equal(line.test || line.msg, lines.shift())
|
|
820
|
-
if (lines.length === 0) break
|
|
821
|
-
}
|
|
822
|
-
})
|
|
823
|
-
|
|
824
|
-
t.test('Should override serializers from plugin', async (t) => {
|
|
825
|
-
const lines = ['incoming request', 'ZHello', 'request completed']
|
|
826
|
-
t.plan(lines.length + 1)
|
|
827
|
-
|
|
828
|
-
const stream = split(JSON.parse)
|
|
829
|
-
|
|
830
|
-
const logger = pino({ level: 'info' }, stream)
|
|
831
|
-
const fastify = Fastify({
|
|
832
|
-
logger
|
|
833
|
-
})
|
|
834
|
-
t.teardown(fastify.close.bind(fastify))
|
|
835
|
-
|
|
836
|
-
fastify.register(function (instance, opts, done) {
|
|
837
|
-
instance.register(context1, {
|
|
838
|
-
logSerializers: {
|
|
839
|
-
test: value => 'Z' + value // should override
|
|
840
|
-
}
|
|
841
|
-
})
|
|
842
|
-
done()
|
|
843
|
-
}, { logSerializers: { test: value => 'X' + value } })
|
|
844
|
-
|
|
845
|
-
function context1 (instance, opts, done) {
|
|
846
|
-
instance.get('/', (req, reply) => {
|
|
847
|
-
req.log.info({ test: 'Hello' })
|
|
848
|
-
reply.send({ hello: 'world' })
|
|
849
|
-
})
|
|
850
|
-
done()
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
await fastify.ready()
|
|
854
|
-
|
|
855
|
-
{
|
|
856
|
-
const response = await fastify.inject({ method: 'GET', url: '/' })
|
|
857
|
-
const body = await response.json()
|
|
858
|
-
t.same(body, { hello: 'world' })
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
for await (const [line] of on(stream, 'data')) {
|
|
862
|
-
t.equal(line.test || line.msg, lines.shift())
|
|
863
|
-
if (lines.length === 0) break
|
|
864
|
-
}
|
|
865
|
-
})
|
|
866
|
-
})
|