1 | 'use strict'
|
2 |
|
3 | const Writable = require('stream').Writable
|
4 | const os = require('os')
|
5 | const test = require('tap').test
|
6 | const pino = require('pino')
|
7 | const serializers = pino.stdSerializers
|
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('error like objects 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 |
|
35 | done()
|
36 | })
|
37 |
|
38 | t.test('pino transform prettifies Error', (t) => {
|
39 | t.plan(2)
|
40 | const pretty = prettyFactory()
|
41 | const err = Error('hello world')
|
42 | const expected = err.stack.split('\n')
|
43 | expected.unshift(err.message)
|
44 |
|
45 | const log = pino({}, new Writable({
|
46 | write (chunk, enc, cb) {
|
47 | const formatted = pretty(chunk.toString())
|
48 | const lines = formatted.split('\n')
|
49 | t.is(lines.length, expected.length + 1)
|
50 | t.is(lines[0], `[${epoch}] INFO (${pid} on ${hostname}): hello world`)
|
51 | cb()
|
52 | }
|
53 | }))
|
54 |
|
55 | log.info(err)
|
56 | })
|
57 |
|
58 | t.test('errorProps recognizes user specified properties', (t) => {
|
59 | t.plan(3)
|
60 | const pretty = prettyFactory({ errorProps: 'statusCode,originalStack' })
|
61 | const log = pino({}, new Writable({
|
62 | write (chunk, enc, cb) {
|
63 | const formatted = pretty(chunk.toString())
|
64 | t.match(formatted, /\s{4}error stack/)
|
65 | t.match(formatted, /statusCode: 500/)
|
66 | t.match(formatted, /originalStack: original stack/)
|
67 | cb()
|
68 | }
|
69 | }))
|
70 |
|
71 | const error = Error('error message')
|
72 | error.stack = 'error stack'
|
73 | error.statusCode = 500
|
74 | error.originalStack = 'original stack'
|
75 |
|
76 | log.error(error)
|
77 | })
|
78 |
|
79 | t.test('prettifies ignores undefined errorLikeObject', (t) => {
|
80 | const pretty = prettyFactory()
|
81 | pretty({ err: undefined })
|
82 | pretty({ error: undefined })
|
83 | t.end()
|
84 | })
|
85 |
|
86 | t.test('prettifies Error in property within errorLikeObjectKeys', (t) => {
|
87 | t.plan(8)
|
88 | const pretty = prettyFactory({
|
89 | errorLikeObjectKeys: ['err']
|
90 | })
|
91 |
|
92 | const err = Error('hello world')
|
93 | const expected = err.stack.split('\n')
|
94 | expected.unshift(err.message)
|
95 |
|
96 | const log = pino({ serializers: { err: serializers.err } }, new Writable({
|
97 | write (chunk, enc, cb) {
|
98 | const formatted = pretty(chunk.toString())
|
99 | const lines = formatted.split('\n')
|
100 | t.is(lines.length, expected.length + 6)
|
101 | t.is(lines[0], `[${epoch}] INFO (${pid} on ${hostname}):`)
|
102 | t.match(lines[1], /\s{4}err: {/)
|
103 | t.match(lines[2], /\s{6}"type": "Error",/)
|
104 | t.match(lines[3], /\s{6}"message": "hello world",/)
|
105 | t.match(lines[4], /\s{6}"stack":/)
|
106 | t.match(lines[5], /\s{6}Error: hello world/)
|
107 |
|
108 | t.match(lines[6], /\s{10}(at Test.t.test|at Test.<anonymous>)/)
|
109 | cb()
|
110 | }
|
111 | }))
|
112 |
|
113 | log.info({ err })
|
114 | })
|
115 |
|
116 | t.test('prettifies Error in property within errorLikeObjectKeys when stack has escaped characters', (t) => {
|
117 | t.plan(8)
|
118 | const pretty = prettyFactory({
|
119 | errorLikeObjectKeys: ['err']
|
120 | })
|
121 |
|
122 | const err = Error('hello world')
|
123 | err.stack = 'Error: hello world\n at anonymous (C:\\project\\node_modules\\example\\index.js)'
|
124 | const expected = err.stack.split('\n')
|
125 | expected.unshift(err.message)
|
126 |
|
127 | const log = pino({ serializers: { err: serializers.err } }, new Writable({
|
128 | write (chunk, enc, cb) {
|
129 | const formatted = pretty(chunk.toString())
|
130 | const lines = formatted.split('\n')
|
131 | t.is(lines.length, expected.length + 6)
|
132 | t.is(lines[0], `[${epoch}] INFO (${pid} on ${hostname}):`)
|
133 | t.match(lines[1], /\s{4}err: {$/)
|
134 | t.match(lines[2], /\s{6}"type": "Error",$/)
|
135 | t.match(lines[3], /\s{6}"message": "hello world",$/)
|
136 | t.match(lines[4], /\s{6}"stack":$/)
|
137 | t.match(lines[5], /\s{10}Error: hello world$/)
|
138 | t.match(lines[6], /\s{10}at anonymous \(C:\\project\\node_modules\\example\\index.js\)$/)
|
139 | cb()
|
140 | }
|
141 | }))
|
142 |
|
143 | log.info({ err })
|
144 | })
|
145 |
|
146 | t.test('prettifies Error in property within errorLikeObjectKeys when stack is not the last property', (t) => {
|
147 | t.plan(9)
|
148 | const pretty = prettyFactory({
|
149 | errorLikeObjectKeys: ['err']
|
150 | })
|
151 |
|
152 | const err = Error('hello world')
|
153 | err.anotherField = 'dummy value'
|
154 | const expected = err.stack.split('\n')
|
155 | expected.unshift(err.message)
|
156 |
|
157 | const log = pino({ serializers: { err: serializers.err } }, new Writable({
|
158 | write (chunk, enc, cb) {
|
159 | const formatted = pretty(chunk.toString())
|
160 | const lines = formatted.split('\n')
|
161 | t.is(lines.length, expected.length + 7)
|
162 | t.is(lines[0], `[${epoch}] INFO (${pid} on ${hostname}):`)
|
163 | t.match(lines[1], /\s{4}err: {/)
|
164 | t.match(lines[2], /\s{6}"type": "Error",/)
|
165 | t.match(lines[3], /\s{6}"message": "hello world",/)
|
166 | t.match(lines[4], /\s{6}"stack":/)
|
167 | t.match(lines[5], /\s{6}Error: hello world/)
|
168 |
|
169 | t.match(lines[6], /\s{10}(at Test.t.test|at Test.<anonymous>)/)
|
170 | t.match(lines[lines.length - 3], /\s{6}"anotherField": "dummy value"/)
|
171 | cb()
|
172 | }
|
173 | }))
|
174 |
|
175 | log.info({ err })
|
176 | })
|
177 |
|
178 | t.test('errorProps flag with "*" (print all nested props)', function (t) {
|
179 | t.plan(9)
|
180 | const pretty = prettyFactory({ errorProps: '*' })
|
181 | const expectedLines = [
|
182 | ' error stack',
|
183 | 'statusCode: 500',
|
184 | 'originalStack: original stack',
|
185 | 'dataBaseSpecificError: {',
|
186 | ' erroMessage: "some database error message"',
|
187 | ' evenMoreSpecificStuff: {',
|
188 | ' "someErrorRelatedObject": "error"',
|
189 | ' }',
|
190 | '}'
|
191 | ]
|
192 | const log = pino({}, new Writable({
|
193 | write (chunk, enc, cb) {
|
194 | const formatted = pretty(chunk.toString())
|
195 | const lines = formatted.split('\n')
|
196 | lines.shift(); lines.pop()
|
197 | for (var i = 0; i < lines.length; i += 1) {
|
198 | t.is(lines[i], expectedLines[i])
|
199 | }
|
200 | cb()
|
201 | }
|
202 | }))
|
203 |
|
204 | const error = Error('error message')
|
205 | error.stack = 'error stack'
|
206 | error.statusCode = 500
|
207 | error.originalStack = 'original stack'
|
208 | error.dataBaseSpecificError = {
|
209 | erroMessage: 'some database error message',
|
210 | evenMoreSpecificStuff: {
|
211 | someErrorRelatedObject: 'error'
|
212 | }
|
213 | }
|
214 |
|
215 | log.error(error)
|
216 | })
|
217 |
|
218 | t.test('handles errors with a null stack', (t) => {
|
219 | t.plan(2)
|
220 | const pretty = prettyFactory()
|
221 | const log = pino({}, new Writable({
|
222 | write (chunk, enc, cb) {
|
223 | const formatted = pretty(chunk.toString())
|
224 | t.match(formatted, /\s{4}message: "foo"/)
|
225 | t.match(formatted, /\s{4}stack: null/)
|
226 | cb()
|
227 | }
|
228 | }))
|
229 |
|
230 | const error = { message: 'foo', stack: null }
|
231 | log.error(error)
|
232 | })
|
233 |
|
234 | t.test('handles errors with a null stack for Error object', (t) => {
|
235 | t.plan(3)
|
236 | const pretty = prettyFactory()
|
237 | const expectedLines = [
|
238 | ' some: "property"',
|
239 | ' stack: null',
|
240 | ' type: "Error"'
|
241 | ]
|
242 | const log = pino({}, new Writable({
|
243 | write (chunk, enc, cb) {
|
244 | const formatted = pretty(chunk.toString())
|
245 | const lines = formatted.split('\n')
|
246 | lines.shift(); lines.pop()
|
247 | for (var i = 0; i < lines.length; i += 1) {
|
248 | t.true(expectedLines.includes(lines[i]))
|
249 | }
|
250 | cb()
|
251 | }
|
252 | }))
|
253 |
|
254 | const error = Error('error message')
|
255 | error.stack = null
|
256 | error.some = 'property'
|
257 |
|
258 | log.error(error)
|
259 | })
|
260 |
|
261 | t.end()
|
262 | })
|