-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlogger-spec.js
207 lines (180 loc) · 6.45 KB
/
logger-spec.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
// Dependencies
const Logger = require('../logger')
// Constants
const DEBUG = process.env.DEBUG
// Helpers
class FakeConsole {
constructor () {
this.printed = ''
}
log (x) {
this.printed = x
if (DEBUG) { console.log(x) }
}
}
// Tests
describe('logging', () => {
beforeAll(() => {
this.log = Logger('petshop',
{},
() => '2016-02-15T12:34:56.789Z',
new FakeConsole())
})
it('should throw an error without a message', () => {
expect(() => {
this.log.info()
}).toThrow()
})
it('should log mandatory attributes', () => {
this.log.error({ message: 'Out of pets exception' })
const contents = JSON.parse(this.log.output.printed)
expect(contents['@timestamp']).toBe('2016-02-15T12:34:56.789Z')
expect(contents.service.name).toBe('petshop')
expect(contents.log.level).toBe('error')
expect(contents.ecs.version).toBe(this.log.ECS_VERSION)
expect(contents.message).toBe('Out of pets exception')
})
it('should log the provided message', () => {
this.log.error({ event: { action: 'exception' }, message: 'Emergency! Emergency!' })
const contents = JSON.parse(this.log.output.printed)
expect(contents.event.action).toBe('exception')
expect(contents.message).toBe('Emergency! Emergency!')
})
it('should log a stack trace if provided', () => {
try {
console.thing()
} catch (err) {
this.log.error({ message: 'An error!' }, err)
}
const contents = JSON.parse(this.log.output.printed)
expect(contents.message).toBe('An error!')
expect(contents.error.message).toBe('console.thing is not a function')
expect(contents.error.type).toBe('TypeError')
expect(contents.error.stack_trace[1]).toContain('logger-spec')
})
it('should log scoped properties defined at creation', () => {
const extraProperties = {
trace: {
id: '1c8a5fb2-fecd-44d8-92a4-449eb2ce4dcb'
},
message: 'GET /cats',
request: { method: 'get' },
response: { status_code: 200 }
}
const myLogger = Logger('petshop',
extraProperties,
() => '2016-02-15T12:34:56.789Z',
new FakeConsole())
myLogger.error(extraProperties)
const contents = JSON.parse(myLogger.output.printed)
expect(contents.trace.id).toBe('1c8a5fb2-fecd-44d8-92a4-449eb2ce4dcb')
expect(contents.request.method).toBe('get')
expect(contents.response.status_code).toBe(200)
expect(contents.message).toBe('GET /cats')
})
it("should be able to add properties with '.with'", () => {
// Let's add some context to this customer journey
const purchaseLog = this.log.with({
trace: { id: '1c8a5fb2-fecd-44d8-92a4-449eb2ce4dcb' },
customer: { full_name: 'Freda Bloggs' },
event: { action: 'pet purchase' }
})
// do stuff
purchaseLog.info({
message: 'customer bought a dog',
pet: { name: 'Barker', species: 'dog', breed: 'Bitsa' }
})
const contents = JSON.parse(purchaseLog.output.printed)
expect(contents.trace.id).toBe('1c8a5fb2-fecd-44d8-92a4-449eb2ce4dcb')
expect(contents.customer.full_name).toBe('Freda Bloggs')
expect(contents.event.action).toBe('pet purchase')
expect(contents.message).toBe('customer bought a dog')
expect(contents.pet.name).toBe('Barker')
})
})
describe('logging dotted keys', () => {
it('should be able to convert dotted keys to nested objects', () => {
this.log.debug({
'trace.id': '1c8a5fb2-fecd-44d8-92a4-449eb2ce4dcb',
'customer.full_name': 'Freda Bloggs',
'event.action': 'pet purchase',
message: 'customer bought a dog',
'pet.name': 'Barker',
'pet.species': 'dog',
'pet.breed': 'Bitsa'
})
const contents = JSON.parse(this.log.output.printed)
expect(contents.trace.id).toBe('1c8a5fb2-fecd-44d8-92a4-449eb2ce4dcb')
expect(contents.customer.full_name).toBe('Freda Bloggs')
expect(contents.event.action).toBe('pet purchase')
expect(contents.message).toBe('customer bought a dog')
expect(contents.pet.name).toBe('Barker')
expect(contents.pet.species).toBe('dog')
expect(contents.pet.breed).toBe('Bitsa')
})
it('should be able to mix dotted keys and nested objects', () => {
this.log.debug({
'trace.id': '1c8a5fb2-fecd-44d8-92a4-449eb2ce4dcb',
'customer.full_name': 'Freda Bloggs',
'event.action': 'pet purchase',
message: 'customer bought a dog',
pet: { name: 'Barker', breed: 'Bitsa' },
'pet.species': 'dog'
})
const contents = JSON.parse(this.log.output.printed)
expect(contents.trace.id).toBe('1c8a5fb2-fecd-44d8-92a4-449eb2ce4dcb')
expect(contents.customer.full_name).toBe('Freda Bloggs')
expect(contents.event.action).toBe('pet purchase')
expect(contents.message).toBe('customer bought a dog')
expect(contents.pet.name).toBe('Barker')
expect(contents.pet.species).toBe('dog')
expect(contents.pet.breed).toBe('Bitsa')
})
})
describe('enforcing non-empty message', () => {
it('should throw an error on an empty message', () => {
expect(() => {
this.log.info('')
}).toThrow()
})
it('should throw an error on a message of blank spaces', () => {
expect(() => {
this.log.info(' ')
}).toThrow()
})
it('should throw an error on a null message', () => {
expect(() => {
this.log.info(null)
}).toThrow()
})
it('should throw an error on an undefined message', () => {
expect(() => {
this.log.info(undefined)
}).toThrow()
})
it('should throw an error if message property is missing', () => {
expect(() => {
this.log.debug({ event: { action: 'pet purchase' }})
}).toThrow()
})
it('should throw an error on an undefined message as a property', () => {
expect(() => {
this.log.debug({ event: { action: 'pet purchase' }, message: undefined })
}).toThrow()
})
it('should throw an error on an null message as a property', () => {
expect(() => {
this.log.debug({ event: { action: 'pet purchase' }, message: null })
}).toThrow()
})
it('should throw an error on an empty message as a property', () => {
expect(() => {
this.log.debug({ event: { action: 'pet purchase' }, message: '' })
}).toThrow()
})
it('should throw an error on an message of blank spaces as a property', () => {
expect(() => {
this.log.debug({ event: { action: 'pet purchase' }, message: ' ' })
}).toThrow()
})
})