ac-logger 4.0.4 → 4.0.6

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/CHANGELOG.md CHANGED
@@ -1,3 +1,25 @@
1
+ ## [4.0.6](https://github.com/admiralcloud/ac-logger/compare/v4.0.5..v4.0.6) (2026-07-12 07:18:30)
2
+
3
+
4
+ ### Bug Fix
5
+
6
+
7
+ * **App:** Package updates | MP | [ccc958c154836f4ffbd6454500984cb159133e7c](https://github.com/admiralcloud/ac-logger/commit/ccc958c154836f4ffbd6454500984cb159133e7c)
8
+ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
9
+ ## [4.0.5](https://github.com/admiralcloud/ac-logger/compare/v4.0.4..v4.0.5) (2026-06-22 15:08:36)
10
+
11
+
12
+ ### Bug Fix
13
+
14
+
15
+ * **App:** Package updates | MP | [9b9626a67dc39c4cf8196bfd186b592e830cc948](https://github.com/admiralcloud/ac-logger/commit/9b9626a67dc39c4cf8196bfd186b592e830cc948)
16
+ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
17
+ ### Tests
18
+
19
+
20
+ * **App:** Added more test | MP | [692a207e0ec17a688efc2c929d08ac95b2249223](https://github.com/admiralcloud/ac-logger/commit/692a207e0ec17a688efc2c929d08ac95b2249223)
21
+ Improved test coverage
22
+ Related issues:
1
23
  ## [4.0.4](https://github.com/admiralcloud/ac-logger/compare/v4.0.3..v4.0.4) (2026-05-24 05:33:52)
2
24
 
3
25
 
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "author": "Mark Poepping (https://www.admiralcloud.com)",
4
4
  "license": "MIT",
5
5
  "repository": "admiralcloud/ac-logger",
6
- "version": "4.0.4",
6
+ "version": "4.0.6",
7
7
  "dependencies": {
8
8
  "lodash": "^4.18.1",
9
9
  "moment": "^2.30.1",
@@ -13,8 +13,8 @@
13
13
  "devDependencies": {
14
14
  "ac-semantic-release": "^1.0.2",
15
15
  "chai": "^4.5.0",
16
- "eslint": "^10.4.0",
17
- "globals": "^17.6.0",
16
+ "eslint": "^10.7.0",
17
+ "globals": "^17.7.0",
18
18
  "intercept-stdout": "^0.1.2",
19
19
  "mocha": "^11.7.6"
20
20
  },
@@ -27,7 +27,8 @@
27
27
  "resolutions": {
28
28
  "mocha/chokidar/braces": "^3.0.3",
29
29
  "mocha/diff": "^8.0.3",
30
- "mocha/serialize-javascript": "^7.0.5"
30
+ "mocha/serialize-javascript": "^7.0.5",
31
+ "mocha/js-yaml": "^4.2.0"
31
32
  },
32
33
  "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
33
34
  }
package/test/test.js CHANGED
@@ -23,7 +23,29 @@ describe('Tests', () => {
23
23
  expect(lines[9]).to.contain('AppName')
24
24
  expect(lines[9]).to.contain('myApp')
25
25
  })
26
-
26
+
27
+ it('bootstrapInfo without branch', () => {
28
+ captured_text = ''
29
+ aclog().bootstrapInfo({ appName: 'testApp' })
30
+ const lines = captured_text.split('\n')
31
+ expect(lines.some(l => l.includes('AppName'))).to.be.true
32
+ expect(lines.some(l => l.includes('Branch'))).to.be.false
33
+ })
34
+
35
+ it('bootstrapInfo collectOnly', () => {
36
+ const result = aclog().bootstrapInfo({ appName: 'myApp', branch: 'myBranch', collectOnly: true })
37
+ expect(result).to.be.an('array')
38
+ expect(result.some(r => r.field === 'Environment')).to.be.true
39
+ expect(result.some(r => r.field === 'Branch')).to.be.true
40
+ expect(result.some(r => r.field === 'AppName' && r.value === 'myApp')).to.be.true
41
+ expect(result.some(r => r.field === 'BOOTSTRAPPING')).to.be.true
42
+ })
43
+
44
+ it('bootstrapInfo collectOnly without branch', () => {
45
+ const result = aclog().bootstrapInfo({ appName: 'myApp', collectOnly: true })
46
+ expect(result.some(r => r.field === 'Branch')).to.be.false
47
+ expect(result.some(r => r.field === 'AppName')).to.be.true
48
+ })
27
49
 
28
50
  it('Log info', () => {
29
51
  captured_text = ''
@@ -47,6 +69,346 @@ describe('Tests', () => {
47
69
  expect(lines[1]).to.contain('DEBUG')
48
70
  })
49
71
 
72
+ it('headline', () => {
73
+ captured_text = ''
74
+ const loggerSetup = aclog()
75
+ loggerSetup.headline({ headline: 'test headline' })
76
+ expect(captured_text).to.contain('TEST HEADLINE')
77
+ })
78
+
79
+ it('headline with custom fill', () => {
80
+ captured_text = ''
81
+ const loggerSetup = aclog()
82
+ loggerSetup.headline({ headline: 'section', headFill: '=' })
83
+ expect(captured_text).to.contain('SECTION')
84
+ expect(captured_text).to.contain('=')
85
+ })
86
+
87
+ it('functionStartLine', () => {
88
+ captured_text = ''
89
+ const loggerSetup = aclog()
90
+ loggerSetup.functionStartLine({ headline: 'my function' })
91
+ expect(captured_text).to.contain('MY FUNCTION')
92
+ })
93
+
94
+ it('hrLine', () => {
95
+ captured_text = ''
96
+ const loggerSetup = aclog()
97
+ loggerSetup.hrLine()
98
+ expect(captured_text).to.contain('----')
99
+ })
100
+
101
+ it('hrLine with custom length', () => {
102
+ captured_text = ''
103
+ const loggerSetup = aclog()
104
+ loggerSetup.hrLine({ headLength: 20 })
105
+ expect(captured_text).to.contain('----')
106
+ })
107
+
108
+ it('listing', () => {
109
+ captured_text = ''
110
+ const loggerSetup = aclog()
111
+ loggerSetup.listing({ field: 'myField', value: 'myValue' })
112
+ expect(captured_text).to.contain('MyField')
113
+ expect(captured_text).to.contain('myValue')
114
+ })
115
+
116
+ it('listing with status 200', () => {
117
+ captured_text = ''
118
+ const loggerSetup = aclog()
119
+ loggerSetup.listing({ field: 'Status', value: 200 })
120
+ expect(captured_text).to.contain('Successful')
121
+ })
122
+
123
+ it('listing with custom level', () => {
124
+ captured_text = ''
125
+ const loggerSetup = aclog({ level: 'debug' })
126
+ loggerSetup.listing({ field: 'myField', value: 'debugValue', level: 'debug' })
127
+ expect(captured_text).to.contain('debugValue')
128
+ })
129
+
130
+ it('serverInfo', () => {
131
+ captured_text = ''
132
+ const loggerSetup = aclog()
133
+ loggerSetup.serverInfo({ host: 'localhost', port: 3000, db: 'mydb' })
134
+ expect(captured_text).to.contain('Host')
135
+ expect(captured_text).to.contain('3000')
136
+ expect(captured_text).to.contain('Db')
137
+ expect(captured_text).to.contain('Connection')
138
+ })
139
+
140
+ it('serverInfo collectOnly', () => {
141
+ const loggerSetup = aclog()
142
+ const result = loggerSetup.serverInfo({ host: 'localhost', port: 3000, collectOnly: true })
143
+ expect(result).to.be.an('array')
144
+ expect(result.some(r => r.field === 'Host')).to.be.true
145
+ expect(result.some(r => r.field === 'Port')).to.be.true
146
+ expect(result.some(r => r.field === 'Connection')).to.be.true
147
+ })
148
+
149
+ it('acSESnfo', () => {
150
+ captured_text = ''
151
+ const loggerSetup = aclog()
152
+ loggerSetup.acSESnfo({
153
+ aws: { accessKeyId: 'AKIATEST' },
154
+ defaultSender: { address: 'sender@test.com' },
155
+ supportRecipient: { address: 'support@test.com' }
156
+ })
157
+ expect(captured_text).to.contain('AKIATEST')
158
+ expect(captured_text).to.contain('sender@test.com')
159
+ expect(captured_text).to.contain('support@test.com')
160
+ })
161
+
162
+ it('timeEnd', () => {
163
+ captured_text = ''
164
+ const loggerSetup = aclog({ level: 'debug' })
165
+ const start = process.hrtime.bigint()
166
+ loggerSetup.timeEnd('myProfile', start, 1e6)
167
+ expect(captured_text).to.contain('myProfile')
168
+ expect(captured_text).to.contain('ms')
169
+ })
170
+
171
+ it('timeEnd with microseconds', () => {
172
+ captured_text = ''
173
+ const loggerSetup = aclog({ level: 'debug' })
174
+ const start = process.hrtime.bigint()
175
+ loggerSetup.timeEnd('myProfile', start, 1e3)
176
+ expect(captured_text).to.contain('myProfile')
177
+ expect(captured_text).to.contain('µs')
178
+ })
179
+
180
+ it('timeEnd with nanoseconds', () => {
181
+ captured_text = ''
182
+ const loggerSetup = aclog({ level: 'debug' })
183
+ const start = process.hrtime.bigint()
184
+ loggerSetup.timeEnd('myProfile', start, 1)
185
+ expect(captured_text).to.contain('myProfile')
186
+ expect(captured_text).to.contain('ns')
187
+ })
188
+
189
+ it('log with error object', () => {
190
+ captured_text = ''
191
+ const loggerSetup = aclog()
192
+ const log = loggerSetup.acLogger
193
+ const err = new Error('test error')
194
+ log.info('Something failed', { e: err })
195
+ expect(captured_text).to.contain('Something failed')
196
+ })
197
+
198
+ it('log with meta fields', () => {
199
+ captured_text = ''
200
+ const loggerSetup = aclog()
201
+ const log = loggerSetup.acLogger
202
+ log.info('test message', { meta: { fileName: 'myFile.js', functionName: 'myFunc', sub: 'mySub' } })
203
+ expect(captured_text).to.contain('myFile.js')
204
+ expect(captured_text).to.contain('myFunc')
205
+ expect(captured_text).to.contain('mySub')
206
+ })
207
+
208
+ it('log with top-level fileName, functionName, sub', () => {
209
+ captured_text = ''
210
+ const loggerSetup = aclog()
211
+ const log = loggerSetup.acLogger
212
+ log.info('test message', { fileName: 'topFile.js', functionName: 'topFunc', sub: 'topSub' })
213
+ expect(captured_text).to.contain('topFile.js')
214
+ expect(captured_text).to.contain('topFunc')
215
+ expect(captured_text).to.contain('topSub')
216
+ })
217
+
218
+ it('log with functionIdentifier', () => {
219
+ captured_text = ''
220
+ const loggerSetup = aclog()
221
+ const log = loggerSetup.acLogger
222
+ log.info('test message', { functionIdentifier: 'myIdentifier' })
223
+ expect(captured_text).to.contain('myIdentifier')
224
+ })
225
+
226
+ it('splat formatting', () => {
227
+ captured_text = ''
228
+ const loggerSetup = aclog()
229
+ const log = loggerSetup.acLogger
230
+ log.info('Hello %s, you are %d years old', 'World', 42)
231
+ expect(captured_text).to.contain('Hello World, you are 42 years old')
232
+ })
233
+
234
+ it('prefixFields', () => {
235
+ captured_text = ''
236
+ const loggerSetup = aclog({ prefixFields: [{ field: 'customerId', short: 'CID' }] })
237
+ const log = loggerSetup.acLogger
238
+ log.info('test', { meta: { customerId: 'ABC123' } })
239
+ expect(captured_text).to.contain('CID')
240
+ expect(captured_text).to.contain('ABC123')
241
+ })
242
+
243
+ it('applicationLogs enabled', (done) => {
244
+ const fs = require('fs')
245
+ const path = require('path')
246
+ const logDir = path.join(process.cwd(), 'logs-test')
247
+ const loggerSetup = aclog({
248
+ applicationLogs: {
249
+ enabled: true,
250
+ filename: 'test-app.log',
251
+ dirname: logDir
252
+ }
253
+ })
254
+ loggerSetup.acLogger.info('applicationLogs test')
255
+ // Give a moment for the stream to write
256
+ setTimeout(() => {
257
+ // Clean up
258
+ try {
259
+ if (fs.existsSync(logDir)) {
260
+ fs.readdirSync(logDir).forEach(f => fs.unlinkSync(path.join(logDir, f)))
261
+ fs.rmdirSync(logDir)
262
+ }
263
+ const symlinkPath = path.join(process.cwd(), 'test-app.log')
264
+ if (fs.existsSync(symlinkPath)) { fs.unlinkSync(symlinkPath) }
265
+ } catch (e) {}
266
+ done()
267
+ }, 200)
268
+ })
269
+
270
+ it('applicationLogs enabled without .log extension', (done) => {
271
+ const fs = require('fs')
272
+ const path = require('path')
273
+ const logDir = path.join(process.cwd(), 'logs-test2')
274
+ const loggerSetup = aclog({
275
+ applicationLogs: {
276
+ enabled: true,
277
+ filename: 'test-app-noext',
278
+ dirname: logDir
279
+ }
280
+ })
281
+ loggerSetup.acLogger.info('applicationLogs noext test')
282
+ setTimeout(() => {
283
+ try {
284
+ if (fs.existsSync(logDir)) {
285
+ fs.readdirSync(logDir).forEach(f => fs.unlinkSync(path.join(logDir, f)))
286
+ fs.rmdirSync(logDir)
287
+ }
288
+ const symlinkPath = path.join(process.cwd(), 'test-app-noext')
289
+ if (fs.existsSync(symlinkPath)) { fs.unlinkSync(symlinkPath) }
290
+ } catch (e) {}
291
+ done()
292
+ }, 200)
293
+ })
294
+
295
+ it('custom transporters', () => {
296
+ const messages = []
297
+ const { createLogger, format, transports } = require('winston')
298
+ // Use a File transporter via the transporters API
299
+ const loggerSetup = aclog({
300
+ transporters: [
301
+ {
302
+ type: 'Console',
303
+ options: {
304
+ level: 'info',
305
+ format: format.simple()
306
+ }
307
+ }
308
+ ]
309
+ })
310
+ captured_text = ''
311
+ loggerSetup.acLogger.info('custom transporter test')
312
+ expect(captured_text).to.contain('custom transporter test')
313
+ })
314
+
315
+ it('customLevels', () => {
316
+ captured_text = ''
317
+ const loggerSetup = aclog({
318
+ level: 'silly',
319
+ customLevels: {
320
+ levels: { error: 0, warn: 1, info: 2, http: 3, verbose: 4, debug: 5, silly: 6 },
321
+ colors: { silly: 'magenta' }
322
+ }
323
+ })
324
+ loggerSetup.acLogger.info('custom levels test')
325
+ expect(captured_text).to.contain('custom levels test')
326
+ })
327
+
328
+ it('HTTP log format - 2xx', () => {
329
+ captured_text = ''
330
+ const loggerSetup = aclog({ level: 'http' })
331
+ loggerSetup.acLogger.http('GET /api', {
332
+ controller: 'ApiController',
333
+ action: 'index',
334
+ ip: '127.0.0.1',
335
+ statusCode: 200,
336
+ performance: { executionTime: 10 }
337
+ })
338
+ expect(captured_text).to.contain('ApiController')
339
+ expect(captured_text).to.contain('200')
340
+ })
341
+
342
+ it('HTTP log format - 3xx', () => {
343
+ captured_text = ''
344
+ const loggerSetup = aclog({ level: 'http' })
345
+ loggerSetup.acLogger.http('GET /redirect', {
346
+ controller: 'RedirectController',
347
+ action: 'go',
348
+ ip: '127.0.0.1',
349
+ statusCode: 301,
350
+ performance: { executionTime: 5 }
351
+ })
352
+ expect(captured_text).to.contain('RedirectController')
353
+ })
354
+
355
+ it('HTTP log format - 4xx', () => {
356
+ captured_text = ''
357
+ const loggerSetup = aclog({ level: 'http' })
358
+ loggerSetup.acLogger.http('GET /missing', {
359
+ controller: 'PageController',
360
+ action: 'show',
361
+ ip: '127.0.0.1',
362
+ statusCode: 404,
363
+ performance: { executionTime: 3 }
364
+ })
365
+ expect(captured_text).to.contain('PageController')
366
+ })
367
+
368
+ it('HTTP log format - 5xx', () => {
369
+ captured_text = ''
370
+ const loggerSetup = aclog({ level: 'http' })
371
+ loggerSetup.acLogger.http('GET /crash', {
372
+ controller: 'AppController',
373
+ action: 'crash',
374
+ ip: '127.0.0.1',
375
+ statusCode: 500,
376
+ performance: { executionTime: 100 }
377
+ })
378
+ expect(captured_text).to.contain('AppController')
379
+ })
380
+
381
+ it('HTTP log format - with customerId and userId', () => {
382
+ captured_text = ''
383
+ const loggerSetup = aclog({ level: 'http' })
384
+ loggerSetup.acLogger.http('GET /user', {
385
+ controller: 'UserController',
386
+ action: 'show',
387
+ ip: '127.0.0.1',
388
+ customerId: 'cust1',
389
+ userId: 'user1',
390
+ accessKey: 'key123',
391
+ iso2: 'DE',
392
+ message: 'extra info',
393
+ statusCode: 200,
394
+ performance: { executionTime: 8 }
395
+ })
396
+ expect(captured_text).to.contain('UserController')
397
+ expect(captured_text).to.contain('cust1')
398
+ expect(captured_text).to.contain('user1')
399
+ })
400
+
401
+ it('HTTP log format - no statusCode', () => {
402
+ captured_text = ''
403
+ const loggerSetup = aclog({ level: 'http' })
404
+ loggerSetup.acLogger.http('GET /nostatus', {
405
+ controller: 'NoStatusController',
406
+ action: 'index',
407
+ ip: '127.0.0.1',
408
+ performance: { executionTime: 1 }
409
+ })
410
+ expect(captured_text).to.contain('NoStatusController')
411
+ })
50
412
 
51
413
  it('Unhook', () => {
52
414
  unhook_intercept()