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.
@@ -144,29 +144,14 @@ function createExpressLoggingMiddleware(options = {}) {
144
144
  return worker
145
145
  }
146
146
 
147
- async function sendLog(level, message, meta = {}) {
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
- try {
157
- // AGUARDAR o enqueue para garantir que o log seja adicionado ao Redis antes de continuar
158
- // transport.enqueue agora é assíncrono e sempre retorna uma Promise
159
- await transport.enqueue({
160
- level,
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 = async (level, message, meta) => {
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
- await sendLog(level, message, meta)
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
- async function emitResponseLog(meta, chunk) {
258
+ function emitResponseLog(meta, chunk) {
274
259
  if (!config.captureResponseBody || chunk == null) {
275
- await logWithContext('info', `[RESPONSE] ${method} ${url}`, meta)
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
- await logWithContext('info', `[RESPONSE] ${method} ${url}`, meta)
266
+ logWithContext('info', `[RESPONSE] ${method} ${url}`, meta)
282
267
  }
283
268
 
284
269
  if (config.logRequest) {
285
- let requestLogEmitted = false
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
- requestLogEmitted = true
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
- async function emitResponse() {
364
- if (logSent) return
365
- logSent = true
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
- try {
368
- ensureIds()
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
- if (config.captureHeaders) {
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
- await sendLog('info', `[RESPONSE] ${method} ${url}`, {
435
- traceId: reqCtx?.traceId || traceId,
436
- spanId: reqCtx?.spanId || spanId,
437
- parentSpanId: reqCtx?.parentSpanId || parentSpanId || null,
438
- requestId: requestId || fastUUID(),
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
- statusCode,
443
- durationMs: duration,
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
- } catch (_) {
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.37",
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",
@@ -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
- async function flushBatch() {
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
- try {
83
+ setImmediate(() => {
86
84
  if (entriesToFlush.length === 1) {
87
85
  const entry = entriesToFlush[0]
88
86
  if (entry) {
89
- try {
90
- const payload = JSON.stringify(entry)
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
- try {
107
- const payload = JSON.stringify(entry)
108
- pipeline.xadd(streamKey, 'MAXLEN', '~', maxLen, '*', 'entry', payload)
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
- await pipeline.exec().catch((err) => {
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
- } catch (err) {
128
- for (const entry of entriesToFlush) {
129
- if (currentSpool) {
130
- currentSpool.append(entry).catch(() => {})
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
- void flushBatch()
120
+ flushBatch()
148
121
  } else if (BATCH_TIMEOUT === 0) {
149
122
  setImmediate(() => {
150
123
  if (!flushing) {
151
- void flushBatch()
124
+ flushBatch()
152
125
  }
153
126
  })
154
127
  } else {
155
128
  batchTimer = setTimeout(() => {
156
129
  batchTimer = null
157
- void flushBatch()
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
- async function enqueue(entry) {
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
- // AGUARDAR o flushBatch quando o batch está cheio para garantir que o log seja adicionado ao Redis
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
- await flushBatch()
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