1 | 'use strict'
|
2 |
|
3 | const { Writable } = require('readable-stream')
|
4 | const os = require('os')
|
5 | const test = require('tap').test
|
6 | const pino = require('pino')
|
7 | const dateformat = require('dateformat')
|
8 | const _prettyFactory = require('../')
|
9 |
|
10 | function prettyFactory (opts) {
|
11 | if (!opts) {
|
12 | opts = { colorize: false }
|
13 | } else if (!Object.prototype.hasOwnProperty.call(opts, 'colorize')) {
|
14 | opts.colorize = false
|
15 | }
|
16 | return _prettyFactory(opts)
|
17 | }
|
18 |
|
19 |
|
20 | const epoch = 1522431328992
|
21 | const pid = process.pid
|
22 | const hostname = os.hostname()
|
23 |
|
24 | test('basic prettifier tests', (t) => {
|
25 | t.beforeEach((done) => {
|
26 | Date.originalNow = Date.now
|
27 | Date.now = () => epoch
|
28 |
|
29 | done()
|
30 | })
|
31 | t.afterEach((done) => {
|
32 | Date.now = Date.originalNow
|
33 | delete Date.originalNow
|
34 | done()
|
35 | })
|
36 |
|
37 | t.test('preserves output if not valid JSON', (t) => {
|
38 | t.plan(1)
|
39 | const pretty = prettyFactory()
|
40 | const formatted = pretty('this is not json\nit\'s just regular output\n')
|
41 | t.is(formatted, 'this is not json\nit\'s just regular output\n\n')
|
42 | })
|
43 |
|
44 | t.test('formats a line without any extra options', (t) => {
|
45 | t.plan(1)
|
46 | const pretty = prettyFactory()
|
47 | const log = pino({}, new Writable({
|
48 | write (chunk, enc, cb) {
|
49 | const formatted = pretty(chunk.toString())
|
50 | t.is(
|
51 | formatted,
|
52 | `[${epoch}] INFO (${pid} on ${hostname}): foo\n`
|
53 | )
|
54 | cb()
|
55 | }
|
56 | }))
|
57 | log.info('foo')
|
58 | })
|
59 |
|
60 | t.test('will add color codes', (t) => {
|
61 | t.plan(1)
|
62 | const pretty = prettyFactory({ colorize: true })
|
63 | const log = pino({}, new Writable({
|
64 | write (chunk, enc, cb) {
|
65 | const formatted = pretty(chunk.toString())
|
66 | t.is(
|
67 | formatted,
|
68 | `[${epoch}] \u001B[32mINFO\u001B[39m (${pid} on ${hostname}): \u001B[36mfoo\u001B[39m\n`
|
69 | )
|
70 | cb()
|
71 | }
|
72 | }))
|
73 | log.info('foo')
|
74 | })
|
75 |
|
76 | t.test('can swap date and level position', (t) => {
|
77 | t.plan(1)
|
78 | const pretty = prettyFactory({ levelFirst: true })
|
79 | const log = pino({}, new Writable({
|
80 | write (chunk, enc, cb) {
|
81 | const formatted = pretty(chunk.toString())
|
82 | t.is(
|
83 | formatted,
|
84 | `INFO [${epoch}] (${pid} on ${hostname}): foo\n`
|
85 | )
|
86 | cb()
|
87 | }
|
88 | }))
|
89 | log.info('foo')
|
90 | })
|
91 |
|
92 | t.test('can use different message keys', (t) => {
|
93 | t.plan(1)
|
94 | const pretty = prettyFactory({ messageKey: 'bar' })
|
95 | const log = pino({}, new Writable({
|
96 | write (chunk, enc, cb) {
|
97 | const formatted = pretty(chunk.toString())
|
98 | t.is(
|
99 | formatted,
|
100 | `[${epoch}] INFO (${pid} on ${hostname}): baz\n`
|
101 | )
|
102 | cb()
|
103 | }
|
104 | }))
|
105 | log.info({ bar: 'baz' })
|
106 | })
|
107 |
|
108 | t.test('can use different level keys', (t) => {
|
109 | t.plan(1)
|
110 | const pretty = prettyFactory({ levelKey: 'bar' })
|
111 | const log = pino({}, new Writable({
|
112 | write (chunk, enc, cb) {
|
113 | const formatted = pretty(chunk.toString())
|
114 | t.is(
|
115 | formatted,
|
116 | `[${epoch}] WARN (${pid} on ${hostname}): foo\n`
|
117 | )
|
118 | cb()
|
119 | }
|
120 | }))
|
121 | log.info({ msg: 'foo', bar: 'warn' })
|
122 | })
|
123 |
|
124 | t.test('will format time to UTC', (t) => {
|
125 | t.plan(1)
|
126 | const pretty = prettyFactory({ translateTime: true })
|
127 | const log = pino({}, new Writable({
|
128 | write (chunk, enc, cb) {
|
129 | const formatted = pretty(chunk.toString())
|
130 | t.is(
|
131 | formatted,
|
132 | `[2018-03-30 17:35:28.992 +0000] INFO (${pid} on ${hostname}): foo\n`
|
133 | )
|
134 | cb()
|
135 | }
|
136 | }))
|
137 | log.info('foo')
|
138 | })
|
139 |
|
140 | t.test('will format time to UTC in custom format', (t) => {
|
141 | t.plan(1)
|
142 | const pretty = prettyFactory({ translateTime: 'HH:MM:ss o' })
|
143 | const log = pino({}, new Writable({
|
144 | write (chunk, enc, cb) {
|
145 | const formatted = pretty(chunk.toString())
|
146 | const utcHour = dateformat(epoch, 'UTC:' + 'HH')
|
147 | const offset = dateformat(epoch, 'UTC:' + 'o')
|
148 | t.is(
|
149 | formatted,
|
150 | `[${utcHour}:35:28 ${offset}] INFO (${pid} on ${hostname}): foo\n`
|
151 | )
|
152 | cb()
|
153 | }
|
154 | }))
|
155 | log.info('foo')
|
156 | })
|
157 |
|
158 | t.test('will format time to local systemzone in ISO 8601 format', (t) => {
|
159 | t.plan(1)
|
160 | const pretty = prettyFactory({ translateTime: 'sys:standard' })
|
161 | const log = pino({}, new Writable({
|
162 | write (chunk, enc, cb) {
|
163 | const formatted = pretty(chunk.toString())
|
164 | const localHour = dateformat(epoch, 'HH')
|
165 | const localDate = dateformat(epoch, 'yyyy-mm-dd')
|
166 | const offset = dateformat(epoch, 'o')
|
167 | t.is(
|
168 | formatted,
|
169 | `[${localDate} ${localHour}:35:28.992 ${offset}] INFO (${pid} on ${hostname}): foo\n`
|
170 | )
|
171 | cb()
|
172 | }
|
173 | }))
|
174 | log.info('foo')
|
175 | })
|
176 |
|
177 | t.test('will format time to local systemzone in custom format', (t) => {
|
178 | t.plan(1)
|
179 | const pretty = prettyFactory({
|
180 | translateTime: 'SYS:yyyy/mm/dd HH:MM:ss o'
|
181 | })
|
182 | const log = pino({}, new Writable({
|
183 | write (chunk, enc, cb) {
|
184 | const formatted = pretty(chunk.toString())
|
185 | const localHour = dateformat(epoch, 'HH')
|
186 | const localDate = dateformat(epoch, 'yyyy/mm/dd')
|
187 | const offset = dateformat(epoch, 'o')
|
188 | t.is(
|
189 | formatted,
|
190 | `[${localDate} ${localHour}:35:28 ${offset}] INFO (${pid} on ${hostname}): foo\n`
|
191 | )
|
192 | cb()
|
193 | }
|
194 | }))
|
195 | log.info('foo')
|
196 | })
|
197 |
|
198 |
|
199 | t.test('handles missing time', (t) => {
|
200 | t.plan(1)
|
201 | const pretty = prettyFactory()
|
202 | const formatted = pretty('{"hello":"world"}')
|
203 | t.is(formatted, ' hello: "world"\n')
|
204 | })
|
205 |
|
206 | t.test('handles missing pid, hostname and name', (t) => {
|
207 | t.plan(1)
|
208 | const pretty = prettyFactory()
|
209 | const log = pino({ base: null }, new Writable({
|
210 | write (chunk, enc, cb) {
|
211 | const formatted = pretty(chunk.toString())
|
212 | t.match(formatted, /\[.*\] INFO: hello world/)
|
213 | cb()
|
214 | }
|
215 | }))
|
216 | log.info('hello world')
|
217 | })
|
218 |
|
219 | t.test('handles missing pid', (t) => {
|
220 | t.plan(1)
|
221 | const pretty = prettyFactory()
|
222 | const name = 'test'
|
223 | const msg = 'hello world'
|
224 | const regex = new RegExp('\\[.*\\] INFO \\(' + name + ' on ' + hostname + '\\): ' + msg)
|
225 |
|
226 | const opts = {
|
227 | base: {
|
228 | name: name,
|
229 | hostname: hostname
|
230 | }
|
231 | }
|
232 | const log = pino(opts, new Writable({
|
233 | write (chunk, enc, cb) {
|
234 | const formatted = pretty(chunk.toString())
|
235 | t.match(formatted, regex)
|
236 | cb()
|
237 | }
|
238 | }))
|
239 |
|
240 | log.info(msg)
|
241 | })
|
242 |
|
243 | t.test('handles missing hostname', (t) => {
|
244 | t.plan(1)
|
245 | const pretty = prettyFactory()
|
246 | const name = 'test'
|
247 | const msg = 'hello world'
|
248 | const regex = new RegExp('\\[.*\\] INFO \\(' + name + '/' + pid + '\\): ' + msg)
|
249 |
|
250 | const opts = {
|
251 | base: {
|
252 | name: name,
|
253 | pid: process.pid
|
254 | }
|
255 | }
|
256 | const log = pino(opts, new Writable({
|
257 | write (chunk, enc, cb) {
|
258 | const formatted = pretty(chunk.toString())
|
259 | t.match(formatted, regex)
|
260 | cb()
|
261 | }
|
262 | }))
|
263 |
|
264 | log.info(msg)
|
265 | })
|
266 |
|
267 | t.test('handles missing name', (t) => {
|
268 | t.plan(1)
|
269 | const pretty = prettyFactory()
|
270 | const msg = 'hello world'
|
271 | const regex = new RegExp('\\[.*\\] INFO \\(' + process.pid + ' on ' + hostname + '\\): ' + msg)
|
272 |
|
273 | const opts = {
|
274 | base: {
|
275 | hostname: hostname,
|
276 | pid: process.pid
|
277 | }
|
278 | }
|
279 | const log = pino(opts, new Writable({
|
280 | write (chunk, enc, cb) {
|
281 | const formatted = pretty(chunk.toString())
|
282 | t.match(formatted, regex)
|
283 | cb()
|
284 | }
|
285 | }))
|
286 |
|
287 | log.info(msg)
|
288 | })
|
289 |
|
290 | t.test('works without time', (t) => {
|
291 | t.plan(1)
|
292 | const pretty = prettyFactory()
|
293 | const log = pino({ timestamp: null }, new Writable({
|
294 | write (chunk, enc, cb) {
|
295 | const formatted = pretty(chunk.toString())
|
296 | t.is(formatted, `INFO (${pid} on ${hostname}): hello world\n`)
|
297 | cb()
|
298 | }
|
299 | }))
|
300 | log.info('hello world')
|
301 | })
|
302 |
|
303 | t.test('prettifies properties', (t) => {
|
304 | t.plan(1)
|
305 | const pretty = prettyFactory()
|
306 | const log = pino({}, new Writable({
|
307 | write (chunk, enc, cb) {
|
308 | const formatted = pretty(chunk.toString())
|
309 | t.match(formatted, ' a: "b"')
|
310 | cb()
|
311 | }
|
312 | }))
|
313 | log.info({ a: 'b' }, 'hello world')
|
314 | })
|
315 |
|
316 | t.test('prettifies nested properties', (t) => {
|
317 | t.plan(6)
|
318 | const expectedLines = [
|
319 | ' a: {',
|
320 | ' "b": {',
|
321 | ' "c": "d"',
|
322 | ' }',
|
323 | ' }'
|
324 | ]
|
325 | const pretty = prettyFactory()
|
326 | const log = pino({}, new Writable({
|
327 | write (chunk, enc, cb) {
|
328 | const formatted = pretty(chunk.toString())
|
329 | const lines = formatted.split('\n')
|
330 | t.is(lines.length, expectedLines.length + 2)
|
331 | lines.shift(); lines.pop()
|
332 | for (let i = 0; i < lines.length; i += 1) {
|
333 | t.is(lines[i], expectedLines[i])
|
334 | }
|
335 | cb()
|
336 | }
|
337 | }))
|
338 | log.info({ a: { b: { c: 'd' } } }, 'hello world')
|
339 | })
|
340 |
|
341 | t.test('treats the name with care', (t) => {
|
342 | t.plan(1)
|
343 | const pretty = prettyFactory()
|
344 | const log = pino({ name: 'matteo' }, new Writable({
|
345 | write (chunk, enc, cb) {
|
346 | const formatted = pretty(chunk.toString())
|
347 | t.is(formatted, `[${epoch}] INFO (matteo/${pid} on ${hostname}): hello world\n`)
|
348 | cb()
|
349 | }
|
350 | }))
|
351 | log.info('hello world')
|
352 | })
|
353 |
|
354 | t.test('handles spec allowed primitives', (t) => {
|
355 | const pretty = prettyFactory()
|
356 | let formatted = pretty(null)
|
357 | t.is(formatted, 'null\n')
|
358 |
|
359 | formatted = pretty(true)
|
360 | t.is(formatted, 'true\n')
|
361 |
|
362 | formatted = pretty(false)
|
363 | t.is(formatted, 'false\n')
|
364 |
|
365 | t.end()
|
366 | })
|
367 |
|
368 | t.test('handles numbers', (t) => {
|
369 | const pretty = prettyFactory()
|
370 | let formatted = pretty(2)
|
371 | t.is(formatted, '2\n')
|
372 |
|
373 | formatted = pretty(-2)
|
374 | t.is(formatted, '-2\n')
|
375 |
|
376 | formatted = pretty(0.2)
|
377 | t.is(formatted, '0.2\n')
|
378 |
|
379 | formatted = pretty(Infinity)
|
380 | t.is(formatted, 'Infinity\n')
|
381 |
|
382 | formatted = pretty(NaN)
|
383 | t.is(formatted, 'NaN\n')
|
384 |
|
385 | t.end()
|
386 | })
|
387 |
|
388 | t.test('handles `undefined` input', (t) => {
|
389 | t.plan(1)
|
390 | const pretty = prettyFactory()
|
391 | const formatted = pretty(undefined)
|
392 | t.is(formatted, 'undefined\n')
|
393 | })
|
394 |
|
395 | t.test('handles customLogLevel', (t) => {
|
396 | t.plan(1)
|
397 | const pretty = prettyFactory()
|
398 | const log = pino({ customLevels: { testCustom: 35 } }, new Writable({
|
399 | write (chunk, enc, cb) {
|
400 | const formatted = pretty(chunk.toString())
|
401 | t.match(formatted, /USERLVL/)
|
402 | cb()
|
403 | }
|
404 | }))
|
405 | log.testCustom('test message')
|
406 | })
|
407 |
|
408 | t.test('supports pino metadata API', (t) => {
|
409 | t.plan(1)
|
410 | const dest = new Writable({
|
411 | write (chunk, enc, cb) {
|
412 | t.is(
|
413 | chunk.toString(),
|
414 | `[${epoch}] INFO (${pid} on ${hostname}): foo\n`
|
415 | )
|
416 | cb()
|
417 | }
|
418 | })
|
419 | const log = pino({
|
420 | prettifier: prettyFactory,
|
421 | prettyPrint: true
|
422 | }, dest)
|
423 | log.info('foo')
|
424 | })
|
425 |
|
426 | t.test('can swap date and level position through meta stream', (t) => {
|
427 | t.plan(1)
|
428 |
|
429 | const dest = new Writable({
|
430 | objectMode: true,
|
431 | write (formatted, enc, cb) {
|
432 | t.is(
|
433 | formatted,
|
434 | `INFO [${epoch}] (${pid} on ${hostname}): foo\n`
|
435 | )
|
436 | cb()
|
437 | }
|
438 | })
|
439 | const log = pino({
|
440 | prettifier: prettyFactory,
|
441 | prettyPrint: {
|
442 | levelFirst: true
|
443 | }
|
444 | }, dest)
|
445 | log.info('foo')
|
446 | })
|
447 |
|
448 | t.test('filter some lines based on jmespath', (t) => {
|
449 | t.plan(3)
|
450 | const pretty = prettyFactory({ search: 'foo.bar' })
|
451 | const expected = [
|
452 | undefined,
|
453 | undefined,
|
454 | `[${epoch}] INFO (${pid} on ${hostname}): foo\n foo: {\n "bar": true\n }\n`
|
455 | ]
|
456 | const log = pino({}, new Writable({
|
457 | write (chunk, enc, cb) {
|
458 | const formatted = pretty(chunk.toString())
|
459 | t.is(
|
460 | formatted,
|
461 | expected.shift()
|
462 | )
|
463 | cb()
|
464 | }
|
465 | }))
|
466 | log.info('foo')
|
467 | log.info({ something: 'else' }, 'foo')
|
468 |
|
469 | log.info({ foo: { bar: true } }, 'foo')
|
470 | })
|
471 |
|
472 | t.test('handles `undefined` return values', (t) => {
|
473 | t.plan(2)
|
474 | const pretty = prettyFactory({ search: 'msg == \'hello world\'' })
|
475 | let formatted = pretty(`{"msg":"nope", "time":${epoch}, "level":30}`)
|
476 | t.is(formatted, undefined)
|
477 | formatted = pretty(`{"msg":"hello world", "time":${epoch}, "level":30}`)
|
478 | t.is(formatted, `[${epoch}] INFO: hello world\n`)
|
479 | })
|
480 |
|
481 | t.test('formats a line with an undefined field', (t) => {
|
482 | t.plan(1)
|
483 | const pretty = prettyFactory()
|
484 | const log = pino({}, new Writable({
|
485 | write (chunk, enc, cb) {
|
486 | const obj = JSON.parse(chunk.toString())
|
487 |
|
488 | obj.a = undefined
|
489 | const formatted = pretty(obj)
|
490 | t.is(
|
491 | formatted,
|
492 | `[${epoch}] INFO (${pid} on ${hostname}): foo\n`
|
493 | )
|
494 | cb()
|
495 | }
|
496 | }))
|
497 | log.info('foo')
|
498 | })
|
499 |
|
500 | t.test('prettifies msg object', (t) => {
|
501 | t.plan(6)
|
502 | const expectedLines = [
|
503 | ' msg: {',
|
504 | ' "b": {',
|
505 | ' "c": "d"',
|
506 | ' }',
|
507 | ' }'
|
508 | ]
|
509 | const pretty = prettyFactory()
|
510 | const log = pino({}, new Writable({
|
511 | write (chunk, enc, cb) {
|
512 | const formatted = pretty(chunk.toString())
|
513 | const lines = formatted.split('\n')
|
514 | t.is(lines.length, expectedLines.length + 2)
|
515 | lines.shift(); lines.pop()
|
516 | for (let i = 0; i < lines.length; i += 1) {
|
517 | t.is(lines[i], expectedLines[i])
|
518 | }
|
519 | cb()
|
520 | }
|
521 | }))
|
522 | log.info({ msg: { b: { c: 'd' } } })
|
523 | })
|
524 |
|
525 | t.test('prettifies msg object with circular references', (t) => {
|
526 | t.plan(7)
|
527 | const expectedLines = [
|
528 | ' msg: {',
|
529 | ' "b": {',
|
530 | ' "c": "d"',
|
531 | ' },',
|
532 | ' "a": "[Circular]"',
|
533 | ' }'
|
534 | ]
|
535 | const pretty = prettyFactory()
|
536 | const log = pino({}, new Writable({
|
537 | write (chunk, enc, cb) {
|
538 | const formatted = pretty(chunk.toString())
|
539 | const lines = formatted.split('\n')
|
540 | t.is(lines.length, expectedLines.length + 2)
|
541 | lines.shift(); lines.pop()
|
542 | for (let i = 0; i < lines.length; i += 1) {
|
543 | t.is(lines[i], expectedLines[i])
|
544 | }
|
545 | cb()
|
546 | }
|
547 | }))
|
548 |
|
549 | const msg = { b: { c: 'd' } }
|
550 | msg.a = msg
|
551 | log.info({ msg })
|
552 | })
|
553 |
|
554 | t.test('prettifies custom key', (t) => {
|
555 | t.plan(1)
|
556 | const pretty = prettyFactory({
|
557 | customPrettifiers: {
|
558 | foo: val => `${val}_baz\nmultiline`,
|
559 | cow: val => val.toUpperCase()
|
560 | }
|
561 | })
|
562 | const arst = pretty('{"msg":"hello world", "foo": "bar", "cow": "moo", "level":30}')
|
563 | t.is(arst, 'INFO: hello world\n foo: bar_baz\n multiline\n cow: MOO\n')
|
564 | })
|
565 |
|
566 | t.test('does not prettify custom key that does not exists', (t) => {
|
567 | t.plan(1)
|
568 | const pretty = prettyFactory({
|
569 | customPrettifiers: {
|
570 | foo: val => `${val}_baz`,
|
571 | cow: val => val.toUpperCase()
|
572 | }
|
573 | })
|
574 | const arst = pretty('{"msg":"hello world", "foo": "bar", "level":30}')
|
575 | t.is(arst, 'INFO: hello world\n foo: bar_baz\n')
|
576 | })
|
577 |
|
578 | t.test('prettifies object with some undefined values', (t) => {
|
579 | t.plan(1)
|
580 | const dest = new Writable({
|
581 | write (chunk, _, cb) {
|
582 | t.is(
|
583 | chunk + '',
|
584 | `[${epoch}] INFO (${pid} on ${hostname}):\n a: {\n "b": "c"\n }\n n: null\n`
|
585 | )
|
586 | cb()
|
587 | }
|
588 | })
|
589 | const log = pino({
|
590 | prettifier: prettyFactory,
|
591 | prettyPrint: true
|
592 | }, dest)
|
593 | log.info({
|
594 | a: { b: 'c' },
|
595 | s: Symbol.for('s'),
|
596 | f: f => f,
|
597 | c: class C {},
|
598 | n: null,
|
599 | err: { toJSON () {} }
|
600 | })
|
601 | })
|
602 |
|
603 | t.test('ignores multiple keys', (t) => {
|
604 | t.plan(1)
|
605 | const pretty = prettyFactory({ ignore: 'pid,hostname' })
|
606 | const arst = pretty(`{"msg":"hello world", "pid":"${pid}", "hostname":"${hostname}", "time":${epoch}, "level":30}`)
|
607 | t.is(arst, `[${epoch}] INFO: hello world\n`)
|
608 | })
|
609 |
|
610 | t.test('ignores a single key', (t) => {
|
611 | t.plan(1)
|
612 | const pretty = prettyFactory({ ignore: 'pid' })
|
613 | const arst = pretty(`{"msg":"hello world", "pid":"${pid}", "hostname":"${hostname}", "time":${epoch}, "level":30}`)
|
614 | t.is(arst, `[${epoch}] INFO (on ${hostname}): hello world\n`)
|
615 | })
|
616 |
|
617 | t.test('ignores time', (t) => {
|
618 | t.plan(1)
|
619 | const pretty = prettyFactory({ ignore: 'time' })
|
620 | const arst = pretty(`{"msg":"hello world", "pid":"${pid}", "hostname":"${hostname}", "time":${epoch}, "level":30}`)
|
621 | t.is(arst, `INFO (${pid} on ${hostname}): hello world\n`)
|
622 | })
|
623 |
|
624 | t.test('ignores time and level', (t) => {
|
625 | t.plan(1)
|
626 | const pretty = prettyFactory({ ignore: 'time,level' })
|
627 | const arst = pretty(`{"msg":"hello world", "pid":"${pid}", "hostname":"${hostname}", "time":${epoch}, "level":30}`)
|
628 | t.is(arst, `(${pid} on ${hostname}): hello world\n`)
|
629 | })
|
630 |
|
631 | t.test('ignores all keys but message', (t) => {
|
632 | t.plan(1)
|
633 | const pretty = prettyFactory({ ignore: 'time,level,name,pid,hostname' })
|
634 | const arst = pretty(`{"msg":"hello world", "pid":"${pid}", "hostname":"${hostname}", "time":${epoch}, "level":30}`)
|
635 | t.is(arst, 'hello world\n')
|
636 | })
|
637 |
|
638 | t.test('prettifies trace caller', (t) => {
|
639 | t.plan(1)
|
640 | const traceCaller = (instance) => {
|
641 | const { symbols: { asJsonSym } } = pino
|
642 | const get = (target, name) => name === asJsonSym ? asJson : target[name]
|
643 |
|
644 | function asJson (...args) {
|
645 | args[0] = args[0] || {}
|
646 | args[0].caller = '/tmp/script.js'
|
647 | return instance[asJsonSym].apply(this, args)
|
648 | }
|
649 |
|
650 | return new Proxy(instance, { get })
|
651 | }
|
652 |
|
653 | const pretty = prettyFactory()
|
654 | const log = traceCaller(pino({}, new Writable({
|
655 | write (chunk, enc, cb) {
|
656 | const formatted = pretty(chunk.toString())
|
657 | t.is(
|
658 | formatted,
|
659 | `[${epoch}] INFO (${pid} on ${hostname}) </tmp/script.js>: foo\n`
|
660 | )
|
661 | cb()
|
662 | }
|
663 | })))
|
664 | log.info('foo')
|
665 | })
|
666 |
|
667 | t.test('handles specified timestampKey', (t) => {
|
668 | t.plan(1)
|
669 | const pretty = prettyFactory({ timestampKey: '@timestamp' })
|
670 | const arst = pretty(`{"msg":"hello world", "@timestamp":${epoch}, "level":30}`)
|
671 | t.is(arst, `[${epoch}] INFO: hello world\n`)
|
672 | })
|
673 |
|
674 | t.test('keeps "v" key in log', (t) => {
|
675 | t.plan(1)
|
676 | const pretty = prettyFactory({ ignore: 'time' })
|
677 | const log = pino({}, new Writable({
|
678 | write (chunk, enc, cb) {
|
679 | const formatted = pretty(chunk.toString())
|
680 | t.is(formatted, `INFO (${pid} on ${hostname}):\n v: 1\n`)
|
681 | cb()
|
682 | }
|
683 | }))
|
684 | log.info({ v: 1 })
|
685 | })
|
686 |
|
687 | t.test('Hide object `{ key: "value" }` from output when flag `hideObject` is set', (t) => {
|
688 | t.plan(1)
|
689 | const pretty = prettyFactory({ hideObject: true })
|
690 | const log = pino({}, new Writable({
|
691 | write (chunk, enc, cb) {
|
692 | const formatted = pretty(chunk.toString())
|
693 | t.is(formatted, `[${epoch}] INFO (${pid} on ${hostname}): hello world\n`)
|
694 | cb()
|
695 | }
|
696 | }))
|
697 | log.info({ key: 'value' }, 'hello world')
|
698 | })
|
699 |
|
700 | t.test('Prints extra objects on one line with singleLine=true', (t) => {
|
701 | t.plan(1)
|
702 | const pretty = prettyFactory({
|
703 | singleLine: true,
|
704 | colorize: false,
|
705 | customPrettifiers: {
|
706 | upper: val => val.toUpperCase(),
|
707 | undef: () => undefined
|
708 | }
|
709 | })
|
710 | const log = pino({}, new Writable({
|
711 | write (chunk, enc, cb) {
|
712 | const formatted = pretty(chunk.toString())
|
713 | t.is(formatted, `[${epoch}] INFO (${pid} on ${hostname}): message {"extra":{"foo":"bar","number":42},"upper":"FOOBAR"}\n`)
|
714 |
|
715 | cb()
|
716 | }
|
717 | }))
|
718 | log.info({ msg: 'message', extra: { foo: 'bar', number: 42 }, upper: 'foobar', undef: 'this will not show up' })
|
719 | })
|
720 |
|
721 | t.test('Does not print empty object with singleLine=true', (t) => {
|
722 | t.plan(1)
|
723 | const pretty = prettyFactory({ singleLine: true, colorize: false })
|
724 | const log = pino({}, new Writable({
|
725 | write (chunk, enc, cb) {
|
726 | const formatted = pretty(chunk.toString())
|
727 | t.is(formatted, `[${epoch}] INFO (${pid} on ${hostname}): message\n`)
|
728 | cb()
|
729 | }
|
730 | }))
|
731 | log.info({ msg: 'message' })
|
732 | })
|
733 |
|
734 | t.end()
|
735 | })
|