azify-logger 1.0.37 → 1.0.38
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/middleware-express.js +82 -163
- package/package.json +2 -1
- package/queue/redisQueue.js +22 -54
- package/register.js +108 -637
- package/scripts/redis-worker.js +8 -30
- package/store.js +1 -17
- package/streams/httpQueue.js +10 -43
package/middleware-express.js
CHANGED
|
@@ -144,29 +144,14 @@ function createExpressLoggingMiddleware(options = {}) {
|
|
|
144
144
|
return worker
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
|
|
148
|
-
if (!transport || typeof transport.enqueue !== 'function')
|
|
149
|
-
try {
|
|
150
|
-
console.log(`[AZIFY-LOGGER-FALLBACK] ${message}`, JSON.stringify(meta, null, 2))
|
|
151
|
-
} catch (_) {
|
|
152
|
-
}
|
|
153
|
-
return
|
|
154
|
-
}
|
|
147
|
+
function sendLog(level, message, meta = {}) {
|
|
148
|
+
if (!transport || typeof transport.enqueue !== 'function') return
|
|
155
149
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
message,
|
|
162
|
-
meta
|
|
163
|
-
}, { 'content-type': 'application/json' })
|
|
164
|
-
} catch (err) {
|
|
165
|
-
try {
|
|
166
|
-
console.log(`[AZIFY-LOGGER-FALLBACK] ${message}`, JSON.stringify(meta, null, 2))
|
|
167
|
-
} catch (_) {
|
|
168
|
-
}
|
|
169
|
-
}
|
|
150
|
+
transport.enqueue({
|
|
151
|
+
level,
|
|
152
|
+
message,
|
|
153
|
+
meta
|
|
154
|
+
}, { 'content-type': 'application/json' })
|
|
170
155
|
}
|
|
171
156
|
|
|
172
157
|
return function azifyExpressLoggingMiddleware(req, res, next) {
|
|
@@ -225,14 +210,14 @@ function createExpressLoggingMiddleware(options = {}) {
|
|
|
225
210
|
|
|
226
211
|
const ctx = ensureRequestContext()
|
|
227
212
|
|
|
228
|
-
const logWithContext =
|
|
213
|
+
const logWithContext = (level, message, meta) => {
|
|
229
214
|
const otelCtx = getOtelTraceContext()
|
|
230
215
|
const ctx = getRequestContext() || ensureRequestContext()
|
|
231
216
|
|
|
232
217
|
meta.traceId = otelCtx?.traceId || meta.traceId || ctx.traceId
|
|
233
218
|
meta.spanId = otelCtx?.spanId || meta.spanId || ctx.spanId
|
|
234
219
|
meta.parentSpanId = otelCtx?.parentSpanId || meta.parentSpanId || ctx.parentSpanId
|
|
235
|
-
|
|
220
|
+
sendLog(level, message, meta)
|
|
236
221
|
}
|
|
237
222
|
|
|
238
223
|
function ensureIds() {
|
|
@@ -270,20 +255,19 @@ function createExpressLoggingMiddleware(options = {}) {
|
|
|
270
255
|
}
|
|
271
256
|
}
|
|
272
257
|
|
|
273
|
-
|
|
258
|
+
function emitResponseLog(meta, chunk) {
|
|
274
259
|
if (!config.captureResponseBody || chunk == null) {
|
|
275
|
-
|
|
260
|
+
logWithContext('info', `[RESPONSE] ${method} ${url}`, meta)
|
|
276
261
|
return
|
|
277
262
|
}
|
|
278
263
|
|
|
279
264
|
if (!meta.response) meta.response = {}
|
|
280
265
|
meta.response.body = safeSerializeBody(chunk)
|
|
281
|
-
|
|
266
|
+
logWithContext('info', `[RESPONSE] ${method} ${url}`, meta)
|
|
282
267
|
}
|
|
283
268
|
|
|
284
269
|
if (config.logRequest) {
|
|
285
|
-
|
|
286
|
-
try {
|
|
270
|
+
process.nextTick(() => {
|
|
287
271
|
ensureIds()
|
|
288
272
|
ensureHeaders()
|
|
289
273
|
|
|
@@ -316,159 +300,94 @@ function createExpressLoggingMiddleware(options = {}) {
|
|
|
316
300
|
if (config.environment) meta.environment = config.environment
|
|
317
301
|
|
|
318
302
|
logWithContext('info', `[REQUEST] ${method} ${url}`, meta)
|
|
319
|
-
|
|
320
|
-
} catch (err) {
|
|
321
|
-
try {
|
|
322
|
-
ensureIds()
|
|
323
|
-
const minimalMeta = {
|
|
324
|
-
traceId: reqCtx?.traceId || traceId,
|
|
325
|
-
spanId: reqCtx?.spanId || spanId,
|
|
326
|
-
parentSpanId: reqCtx?.parentSpanId || parentSpanId || null,
|
|
327
|
-
requestId: requestId || fastUUID(),
|
|
328
|
-
method,
|
|
329
|
-
url,
|
|
330
|
-
path,
|
|
331
|
-
timestamp: Date.now(),
|
|
332
|
-
hostname
|
|
333
|
-
}
|
|
334
|
-
if (serviceObj) minimalMeta.service = serviceObj
|
|
335
|
-
if (config.environment) minimalMeta.environment = config.environment
|
|
336
|
-
logWithContext('info', `[REQUEST] ${method} ${url}`, minimalMeta)
|
|
337
|
-
requestLogEmitted = true
|
|
338
|
-
} catch (_) {
|
|
339
|
-
try {
|
|
340
|
-
sendLog('info', `[REQUEST] ${method} ${url}`, {
|
|
341
|
-
method,
|
|
342
|
-
url,
|
|
343
|
-
path
|
|
344
|
-
})
|
|
345
|
-
requestLogEmitted = true
|
|
346
|
-
} catch (_) {
|
|
347
|
-
try {
|
|
348
|
-
console.log(`[AZIFY-LOGGER-EMERGENCY] [REQUEST] ${method} ${url}`)
|
|
349
|
-
} catch (_) {
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
if (!requestLogEmitted) {
|
|
356
|
-
try {
|
|
357
|
-
console.log(`[AZIFY-LOGGER-EMERGENCY] [REQUEST] ${method} ${url}`)
|
|
358
|
-
} catch (_) {
|
|
359
|
-
}
|
|
360
|
-
}
|
|
303
|
+
})
|
|
361
304
|
}
|
|
362
305
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
306
|
+
const originalEnd = res.end.bind(res)
|
|
307
|
+
|
|
308
|
+
res.end = (chunk, encoding) => {
|
|
309
|
+
const result = originalEnd(chunk, encoding)
|
|
310
|
+
|
|
311
|
+
if (chunk != null && config.captureResponseBody && !responseChunkCaptured) {
|
|
312
|
+
responseChunk = chunk
|
|
313
|
+
responseChunkCaptured = true
|
|
314
|
+
}
|
|
366
315
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
const statusCode = res.statusCode || 200
|
|
371
|
-
const duration = Date.now() - startTime
|
|
372
|
-
const response = { statusCode, durationMs: duration }
|
|
316
|
+
if (!logSent) {
|
|
317
|
+
logSent = true
|
|
373
318
|
|
|
374
|
-
|
|
375
|
-
ensureHeaders()
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
const requestObj = {
|
|
379
|
-
id: requestId,
|
|
380
|
-
method,
|
|
381
|
-
url,
|
|
382
|
-
path,
|
|
383
|
-
ip: clientIp
|
|
384
|
-
}
|
|
385
|
-
if (query) requestObj.query = query
|
|
386
|
-
if (config.captureHeaders && cachedHeaders) requestObj.headers = cachedHeaders
|
|
387
|
-
|
|
388
|
-
const meta = {
|
|
389
|
-
traceId: reqCtx.traceId,
|
|
390
|
-
spanId: reqCtx.spanId,
|
|
391
|
-
parentSpanId: reqCtx.parentSpanId || null,
|
|
392
|
-
requestId,
|
|
393
|
-
request: requestObj,
|
|
394
|
-
response,
|
|
395
|
-
timestamp: Date.now(),
|
|
396
|
-
hostname
|
|
397
|
-
}
|
|
398
|
-
if (serviceObj) meta.service = serviceObj
|
|
399
|
-
if (config.environment) meta.environment = config.environment
|
|
400
|
-
|
|
401
|
-
const chunkToProcess = (responseChunk !== null && responseChunkCaptured) ? responseChunk : null
|
|
402
|
-
await emitResponseLog(meta, chunkToProcess)
|
|
403
|
-
} catch (err) {
|
|
404
|
-
try {
|
|
405
|
-
ensureIds()
|
|
406
|
-
const statusCode = res.statusCode || 200
|
|
407
|
-
const duration = Date.now() - startTime
|
|
408
|
-
const response = { statusCode, durationMs: duration }
|
|
409
|
-
const requestObj = {
|
|
410
|
-
id: requestId,
|
|
411
|
-
method,
|
|
412
|
-
url,
|
|
413
|
-
path,
|
|
414
|
-
ip: clientIp || 'unknown'
|
|
415
|
-
}
|
|
416
|
-
const meta = {
|
|
417
|
-
traceId: reqCtx?.traceId || traceId,
|
|
418
|
-
spanId: reqCtx?.spanId || spanId,
|
|
419
|
-
parentSpanId: reqCtx?.parentSpanId || parentSpanId || null,
|
|
420
|
-
requestId: requestId || fastUUID(),
|
|
421
|
-
request: requestObj,
|
|
422
|
-
response,
|
|
423
|
-
timestamp: Date.now(),
|
|
424
|
-
hostname
|
|
425
|
-
}
|
|
426
|
-
if (serviceObj) meta.service = serviceObj
|
|
427
|
-
if (config.environment) meta.environment = config.environment
|
|
428
|
-
await emitResponseLog(meta, null)
|
|
429
|
-
} catch (fallbackErr) {
|
|
319
|
+
process.nextTick(() => {
|
|
430
320
|
try {
|
|
431
321
|
ensureIds()
|
|
322
|
+
|
|
432
323
|
const statusCode = res.statusCode || 200
|
|
433
324
|
const duration = Date.now() - startTime
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
325
|
+
const response = { statusCode, durationMs: duration }
|
|
326
|
+
|
|
327
|
+
if (config.captureHeaders) {
|
|
328
|
+
ensureHeaders()
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const requestObj = {
|
|
332
|
+
id: requestId,
|
|
439
333
|
method,
|
|
440
334
|
url,
|
|
441
335
|
path,
|
|
442
|
-
|
|
443
|
-
|
|
336
|
+
ip: clientIp
|
|
337
|
+
}
|
|
338
|
+
if (query) requestObj.query = query
|
|
339
|
+
if (config.captureHeaders && cachedHeaders) requestObj.headers = cachedHeaders
|
|
340
|
+
|
|
341
|
+
const meta = {
|
|
342
|
+
traceId: reqCtx.traceId,
|
|
343
|
+
spanId: reqCtx.spanId,
|
|
344
|
+
parentSpanId: reqCtx.parentSpanId || null,
|
|
345
|
+
requestId,
|
|
346
|
+
request: requestObj,
|
|
347
|
+
response,
|
|
444
348
|
timestamp: Date.now(),
|
|
445
349
|
hostname
|
|
446
|
-
}
|
|
447
|
-
|
|
350
|
+
}
|
|
351
|
+
if (serviceObj) meta.service = serviceObj
|
|
352
|
+
if (config.environment) meta.environment = config.environment
|
|
353
|
+
|
|
354
|
+
const chunkToProcess = (responseChunk !== null && responseChunkCaptured) ? responseChunk : null
|
|
355
|
+
emitResponseLog(meta, chunkToProcess)
|
|
356
|
+
} catch (err) {
|
|
357
|
+
try {
|
|
358
|
+
ensureIds()
|
|
359
|
+
const statusCode = res.statusCode || 200
|
|
360
|
+
const duration = Date.now() - startTime
|
|
361
|
+
const response = { statusCode, durationMs: duration }
|
|
362
|
+
const requestObj = {
|
|
363
|
+
id: requestId,
|
|
364
|
+
method,
|
|
365
|
+
url,
|
|
366
|
+
path,
|
|
367
|
+
ip: clientIp || 'unknown'
|
|
368
|
+
}
|
|
369
|
+
const meta = {
|
|
370
|
+
traceId: reqCtx?.traceId || traceId,
|
|
371
|
+
spanId: reqCtx?.spanId || spanId,
|
|
372
|
+
parentSpanId: reqCtx?.parentSpanId || parentSpanId || null,
|
|
373
|
+
requestId: requestId || fastUUID(),
|
|
374
|
+
request: requestObj,
|
|
375
|
+
response,
|
|
376
|
+
timestamp: Date.now(),
|
|
377
|
+
hostname
|
|
378
|
+
}
|
|
379
|
+
if (serviceObj) meta.service = serviceObj
|
|
380
|
+
if (config.environment) meta.environment = config.environment
|
|
381
|
+
emitResponseLog(meta, null)
|
|
382
|
+
} catch (_) {
|
|
383
|
+
}
|
|
448
384
|
}
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
const originalEnd = res.end.bind(res)
|
|
454
|
-
|
|
455
|
-
res.end = (chunk, encoding) => {
|
|
456
|
-
if (chunk != null && config.captureResponseBody && !responseChunkCaptured) {
|
|
457
|
-
responseChunk = chunk
|
|
458
|
-
responseChunkCaptured = true
|
|
385
|
+
})
|
|
459
386
|
}
|
|
460
387
|
|
|
461
|
-
const result = originalEnd(chunk, encoding)
|
|
462
|
-
void emitResponse()
|
|
463
388
|
return result
|
|
464
389
|
}
|
|
465
390
|
|
|
466
|
-
// Também capturar o evento 'finish' para garantir que o RESPONSE seja logado
|
|
467
|
-
// mesmo quando res.json() ou res.send() são usados sem chamar res.end() explicitamente
|
|
468
|
-
res.once('finish', () => {
|
|
469
|
-
void emitResponse()
|
|
470
|
-
})
|
|
471
|
-
|
|
472
391
|
runWithRequestContext(ctx, () => {
|
|
473
392
|
next()
|
|
474
393
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "azify-logger",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.38",
|
|
4
4
|
"description": "Azify Logger Client - Centralized logging for OpenSearch",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"adm-zip": "^0.5.16",
|
|
54
54
|
"archiver": "^6.0.1",
|
|
55
55
|
"axios": "^1.6.0",
|
|
56
|
+
"bull": "^4.16.5",
|
|
56
57
|
"cors": "^2.8.5",
|
|
57
58
|
"express": "^4.18.2",
|
|
58
59
|
"express-session": "^1.17.3",
|
package/queue/redisQueue.js
CHANGED
|
@@ -29,7 +29,6 @@ function createRedisProducer(config = {}) {
|
|
|
29
29
|
const streamKey = config.streamKey || DEFAULT_STREAM_KEY
|
|
30
30
|
const maxLen = Number.isFinite(config.maxLen) ? config.maxLen : DEFAULT_MAXLEN
|
|
31
31
|
const redisOptions = { ...defaultRedisOptions, ...(config.redisOptions || {}) }
|
|
32
|
-
const spool = config.spool || null
|
|
33
32
|
|
|
34
33
|
const client = new Redis(url, redisOptions)
|
|
35
34
|
let lastConnectionErrorLog = 0
|
|
@@ -70,9 +69,8 @@ function createRedisProducer(config = {}) {
|
|
|
70
69
|
const BATCH_SIZE = 1
|
|
71
70
|
const BATCH_TIMEOUT = 0
|
|
72
71
|
let flushing = false
|
|
73
|
-
let currentSpool = spool
|
|
74
72
|
|
|
75
|
-
|
|
73
|
+
function flushBatch() {
|
|
76
74
|
if (flushing || batch.length === 0) return
|
|
77
75
|
flushing = true
|
|
78
76
|
|
|
@@ -82,19 +80,12 @@ function createRedisProducer(config = {}) {
|
|
|
82
80
|
return
|
|
83
81
|
}
|
|
84
82
|
|
|
85
|
-
|
|
83
|
+
setImmediate(() => {
|
|
86
84
|
if (entriesToFlush.length === 1) {
|
|
87
85
|
const entry = entriesToFlush[0]
|
|
88
86
|
if (entry) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
// AGUARDAR o xadd para garantir que o log seja adicionado ao Redis antes de continuar
|
|
92
|
-
await client.xadd(streamKey, 'MAXLEN', '~', maxLen, '*', 'entry', payload)
|
|
93
|
-
} catch (err) {
|
|
94
|
-
if (currentSpool) {
|
|
95
|
-
currentSpool.append(entry).catch(() => {})
|
|
96
|
-
}
|
|
97
|
-
}
|
|
87
|
+
const payload = JSON.stringify(entry)
|
|
88
|
+
client.xadd(streamKey, 'MAXLEN', '~', maxLen, '*', 'entry', payload).catch(() => {})
|
|
98
89
|
}
|
|
99
90
|
} else {
|
|
100
91
|
const pipeline = client.pipeline()
|
|
@@ -103,58 +94,40 @@ function createRedisProducer(config = {}) {
|
|
|
103
94
|
for (let i = 0; i < entriesToFlush.length; i++) {
|
|
104
95
|
const entry = entriesToFlush[i]
|
|
105
96
|
if (!entry) continue
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
validCount++
|
|
110
|
-
} catch (err) {
|
|
111
|
-
if (currentSpool) {
|
|
112
|
-
currentSpool.append(entry).catch(() => {})
|
|
113
|
-
}
|
|
114
|
-
}
|
|
97
|
+
const payload = JSON.stringify(entry)
|
|
98
|
+
pipeline.xadd(streamKey, 'MAXLEN', '~', maxLen, '*', 'entry', payload)
|
|
99
|
+
validCount++
|
|
115
100
|
}
|
|
116
101
|
|
|
117
102
|
if (validCount > 0) {
|
|
118
|
-
|
|
119
|
-
for (const entry of entriesToFlush) {
|
|
120
|
-
if (currentSpool) {
|
|
121
|
-
currentSpool.append(entry).catch(() => {})
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
})
|
|
103
|
+
pipeline.exec().catch(() => {})
|
|
125
104
|
}
|
|
126
105
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
106
|
+
|
|
107
|
+
flushing = false
|
|
108
|
+
if (batch.length >= BATCH_SIZE) {
|
|
109
|
+
flushBatch()
|
|
110
|
+
} else if (batch.length > 0) {
|
|
111
|
+
scheduleFlush()
|
|
132
112
|
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
flushing = false
|
|
136
|
-
if (batch.length >= BATCH_SIZE) {
|
|
137
|
-
setImmediate(() => { void flushBatch() })
|
|
138
|
-
} else if (batch.length > 0) {
|
|
139
|
-
scheduleFlush()
|
|
140
|
-
}
|
|
113
|
+
})
|
|
141
114
|
}
|
|
142
115
|
|
|
143
116
|
function scheduleFlush() {
|
|
144
117
|
if (batchTimer || flushing) return
|
|
145
118
|
|
|
146
119
|
if (batch.length >= BATCH_SIZE) {
|
|
147
|
-
|
|
120
|
+
flushBatch()
|
|
148
121
|
} else if (BATCH_TIMEOUT === 0) {
|
|
149
122
|
setImmediate(() => {
|
|
150
123
|
if (!flushing) {
|
|
151
|
-
|
|
124
|
+
flushBatch()
|
|
152
125
|
}
|
|
153
126
|
})
|
|
154
127
|
} else {
|
|
155
128
|
batchTimer = setTimeout(() => {
|
|
156
129
|
batchTimer = null
|
|
157
|
-
|
|
130
|
+
flushBatch()
|
|
158
131
|
}, BATCH_TIMEOUT)
|
|
159
132
|
|
|
160
133
|
if (typeof batchTimer.unref === 'function') {
|
|
@@ -163,7 +136,7 @@ function createRedisProducer(config = {}) {
|
|
|
163
136
|
}
|
|
164
137
|
}
|
|
165
138
|
|
|
166
|
-
|
|
139
|
+
function enqueue(entry) {
|
|
167
140
|
batch.push(entry)
|
|
168
141
|
|
|
169
142
|
if (batch.length >= BATCH_SIZE) {
|
|
@@ -171,8 +144,7 @@ function createRedisProducer(config = {}) {
|
|
|
171
144
|
clearTimeout(batchTimer)
|
|
172
145
|
batchTimer = null
|
|
173
146
|
}
|
|
174
|
-
|
|
175
|
-
await flushBatch()
|
|
147
|
+
flushBatch()
|
|
176
148
|
} else if (batch.length === 1) {
|
|
177
149
|
scheduleFlush()
|
|
178
150
|
}
|
|
@@ -184,7 +156,7 @@ function createRedisProducer(config = {}) {
|
|
|
184
156
|
batchTimer = null
|
|
185
157
|
}
|
|
186
158
|
while (batch.length > 0) {
|
|
187
|
-
|
|
159
|
+
flushBatch()
|
|
188
160
|
await new Promise(resolve => setTimeout(resolve, 10))
|
|
189
161
|
}
|
|
190
162
|
await client.quit().catch(() => {})
|
|
@@ -195,11 +167,7 @@ function createRedisProducer(config = {}) {
|
|
|
195
167
|
client,
|
|
196
168
|
streamKey,
|
|
197
169
|
close,
|
|
198
|
-
flush: flushBatch
|
|
199
|
-
setSpool(newSpool) {
|
|
200
|
-
currentSpool = newSpool
|
|
201
|
-
},
|
|
202
|
-
_spool: null
|
|
170
|
+
flush: flushBatch
|
|
203
171
|
}
|
|
204
172
|
}
|
|
205
173
|
|