azify-logger 1.0.55-test → 1.0.55-test-1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "azify-logger",
3
- "version": "1.0.55-test",
3
+ "version": "1.0.55-test-1",
4
4
  "description": "Azify Logger Client - Centralized logging for OpenSearch",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -111,6 +111,7 @@
111
111
  "queue/",
112
112
  "scripts/redis-worker.js",
113
113
  "streams/",
114
+ "utils/undiciLogBodies.js",
114
115
  "package.json",
115
116
  "README.md"
116
117
  ]
@@ -11,6 +11,11 @@ try {
11
11
  const Module = require('module')
12
12
  const path = require('path')
13
13
  const EARLY_DIR = __dirname
14
+ const {
15
+ resolveUndiciRequestOpts,
16
+ serializeUndiciRequestBody,
17
+ restoreUndiciResponseBodyAfterReadForLog
18
+ } = require(path.join(EARLY_DIR, 'utils/undiciLogBodies'))
14
19
 
15
20
  function getOtelTraceContext() {
16
21
  try {
@@ -199,26 +204,50 @@ try {
199
204
  const traceCtx = ctx || otelCtx
200
205
  const rawTraceId = traceCtx && traceCtx.traceId || (require('crypto').randomUUID && require('crypto').randomUUID())
201
206
  const traceId = typeof rawTraceId === 'string' ? toTraceIdHex(rawTraceId) : rawTraceId
207
+ const reqOpts = resolveUndiciRequestOpts(url, options)
208
+ const requestBodyStr = serializeUndiciRequestBody(reqOpts)
202
209
  const requestMeta = { traceId, spanId: (traceCtx && traceCtx.spanId) || null, parentSpanId: (traceCtx && traceCtx.parentSpanId) || null, requestId: (traceCtx && traceCtx.requestId) || null, method, url: urlStr }
210
+ if (requestBodyStr != null) requestMeta.requestBody = requestBodyStr
203
211
  markSource(requestMeta, 'http-client')
204
212
  const start = require('perf_hooks').performance.now()
205
213
  const skipLog = isLoggerUrl(urlStr)
206
214
  if (HTTP_CLIENT_MODE !== 'off' && !skipLog) send('info', `[REQUEST] ${method} ${urlStr}`, requestMeta)
207
215
  const wrappedCb = callback ? function (err, data) {
208
216
  const duration = Number((require('perf_hooks').performance.now() - start).toFixed(2))
209
- if (HTTP_CLIENT_MODE !== 'off' && !skipLog) {
210
- if (err) send('error', `[RESPONSE] ${method} ${urlStr} ERROR ${duration}ms`, { ...requestMeta, error: err && err.message, responseTimeMs: duration })
211
- else if (data) send('info', `[RESPONSE] ${method} ${urlStr} ${data.statusCode} ${duration}ms`, { ...requestMeta, statusCode: data.statusCode, responseTimeMs: duration })
217
+ if (err) {
218
+ if (HTTP_CLIENT_MODE !== 'off' && !skipLog) {
219
+ send('error', `[RESPONSE] ${method} ${urlStr} ERROR ${duration}ms`, { ...requestMeta, error: err && err.message, responseTimeMs: duration })
220
+ }
221
+ return callback(err, data)
212
222
  }
213
- return callback(err, data)
223
+ if (!data) return callback(err, data)
224
+ restoreUndiciResponseBodyAfterReadForLog(data).then(({ logStr, data: restored }) => {
225
+ if (HTTP_CLIENT_MODE !== 'off' && !skipLog) {
226
+ const meta = { ...requestMeta, statusCode: restored.statusCode, responseTimeMs: duration }
227
+ if (logStr != null) meta.responseBody = logStr
228
+ send('info', `[RESPONSE] ${method} ${urlStr} ${restored.statusCode} ${duration}ms`, meta)
229
+ }
230
+ return callback(null, restored)
231
+ }).catch(() => {
232
+ if (HTTP_CLIENT_MODE !== 'off' && !skipLog) {
233
+ send('info', `[RESPONSE] ${method} ${urlStr} ${data.statusCode} ${duration}ms`, { ...requestMeta, statusCode: data.statusCode, responseTimeMs: duration })
234
+ }
235
+ return callback(null, data)
236
+ })
214
237
  } : undefined
215
238
  if (wrappedCb) return origRequest.call(this, url, options, wrappedCb)
216
239
  const p = origRequest.call(this, url, options)
217
240
  if (p && typeof p.then === 'function') {
218
241
  return p.then(
219
- (data) => {
242
+ async (data) => {
220
243
  const duration = Number((require('perf_hooks').performance.now() - start).toFixed(2))
221
- if (HTTP_CLIENT_MODE !== 'off' && !skipLog && data) send('info', `[RESPONSE] ${method} ${urlStr} ${data.statusCode} ${duration}ms`, { ...requestMeta, statusCode: data.statusCode, responseTimeMs: duration })
244
+ if (HTTP_CLIENT_MODE !== 'off' && !skipLog && data) {
245
+ const { logStr, data: restored } = await restoreUndiciResponseBodyAfterReadForLog(data)
246
+ const meta = { ...requestMeta, statusCode: restored.statusCode, responseTimeMs: duration }
247
+ if (logStr != null) meta.responseBody = logStr
248
+ send('info', `[RESPONSE] ${method} ${urlStr} ${restored.statusCode} ${duration}ms`, meta)
249
+ return restored
250
+ }
222
251
  return data
223
252
  },
224
253
  (err) => {
@@ -244,25 +273,48 @@ try {
244
273
  const traceCtx = ctx || otelCtx
245
274
  const rawTraceId = (traceCtx && traceCtx.traceId) || (require('crypto').randomUUID && require('crypto').randomUUID())
246
275
  const traceId = typeof rawTraceId === 'string' ? toTraceIdHex(rawTraceId) : rawTraceId
276
+ const requestBodyStr = serializeUndiciRequestBody(opts || {})
247
277
  const requestMeta = { traceId, spanId: (traceCtx && traceCtx.spanId) || null, parentSpanId: (traceCtx && traceCtx.parentSpanId) || null, requestId: (traceCtx && traceCtx.requestId) || null, method: methodStr, url: urlStr }
278
+ if (requestBodyStr != null) requestMeta.requestBody = requestBodyStr
248
279
  markSource(requestMeta, 'http-client')
249
280
  const start = require('perf_hooks').performance.now()
250
281
  const skipLog = isLoggerUrl(urlStr)
251
282
  if (HTTP_CLIENT_MODE !== 'off' && !skipLog) send('info', `[REQUEST] ${methodStr} ${urlStr}`, requestMeta)
252
283
  const wrappedCb = typeof callback === 'function' ? function (err, data) {
253
284
  const duration = Number((require('perf_hooks').performance.now() - start).toFixed(2))
254
- if (HTTP_CLIENT_MODE !== 'off' && !skipLog) {
255
- if (err) send('error', `[RESPONSE] ${methodStr} ${urlStr} ERROR ${duration}ms`, { ...requestMeta, error: err && err.message, responseTimeMs: duration })
256
- else if (data) send('info', `[RESPONSE] ${methodStr} ${urlStr} ${data.statusCode} ${duration}ms`, { ...requestMeta, statusCode: data.statusCode, responseTimeMs: duration })
285
+ if (err) {
286
+ if (HTTP_CLIENT_MODE !== 'off' && !skipLog) {
287
+ send('error', `[RESPONSE] ${methodStr} ${urlStr} ERROR ${duration}ms`, { ...requestMeta, error: err && err.message, responseTimeMs: duration })
288
+ }
289
+ return callback(err, data)
257
290
  }
258
- return callback(err, data)
291
+ if (!data) return callback(err, data)
292
+ restoreUndiciResponseBodyAfterReadForLog(data).then(({ logStr, data: restored }) => {
293
+ if (HTTP_CLIENT_MODE !== 'off' && !skipLog) {
294
+ const meta = { ...requestMeta, statusCode: restored.statusCode, responseTimeMs: duration }
295
+ if (logStr != null) meta.responseBody = logStr
296
+ send('info', `[RESPONSE] ${methodStr} ${urlStr} ${restored.statusCode} ${duration}ms`, meta)
297
+ }
298
+ return callback(null, restored)
299
+ }).catch(() => {
300
+ if (HTTP_CLIENT_MODE !== 'off' && !skipLog) {
301
+ send('info', `[RESPONSE] ${methodStr} ${urlStr} ${data.statusCode} ${duration}ms`, { ...requestMeta, statusCode: data.statusCode, responseTimeMs: duration })
302
+ }
303
+ return callback(null, data)
304
+ })
259
305
  } : undefined
260
306
  const ret = wrappedCb ? origDisp.call(this, opts, wrappedCb) : origDisp.call(this, opts)
261
307
  if (ret && typeof ret.then === 'function' && !wrappedCb) {
262
308
  return ret.then(
263
- (data) => {
309
+ async (data) => {
264
310
  const duration = Number((require('perf_hooks').performance.now() - start).toFixed(2))
265
- if (HTTP_CLIENT_MODE !== 'off' && !skipLog && data) send('info', `[RESPONSE] ${methodStr} ${urlStr} ${data.statusCode} ${duration}ms`, { ...requestMeta, statusCode: data.statusCode, responseTimeMs: duration })
311
+ if (HTTP_CLIENT_MODE !== 'off' && !skipLog && data) {
312
+ const { logStr, data: restored } = await restoreUndiciResponseBodyAfterReadForLog(data)
313
+ const meta = { ...requestMeta, statusCode: restored.statusCode, responseTimeMs: duration }
314
+ if (logStr != null) meta.responseBody = logStr
315
+ send('info', `[RESPONSE] ${methodStr} ${urlStr} ${restored.statusCode} ${duration}ms`, meta)
316
+ return restored
317
+ }
266
318
  return data
267
319
  },
268
320
  (err) => {
@@ -323,25 +375,48 @@ try {
323
375
  const traceCtx = ctx || otelCtx
324
376
  const rawTraceId = (traceCtx && traceCtx.traceId) || (require('crypto').randomUUID && require('crypto').randomUUID())
325
377
  const traceId = typeof rawTraceId === 'string' ? (toTraceIdHex ? toTraceIdHex(rawTraceId) : rawTraceId) : rawTraceId
378
+ const requestBodyStr = serializeUndiciRequestBody(opts || {})
326
379
  const requestMeta = { traceId, spanId: (traceCtx && traceCtx.spanId) || null, parentSpanId: (traceCtx && traceCtx.parentSpanId) || null, requestId: (traceCtx && traceCtx.requestId) || null, method: methodStr, url: urlStr }
380
+ if (requestBodyStr != null) requestMeta.requestBody = requestBodyStr
327
381
  if (markSource) markSource(requestMeta, 'http-client')
328
382
  const start = require('perf_hooks').performance.now()
329
383
  const skipLog = isLoggerUrl(urlStr)
330
384
  if (HTTP_CLIENT_MODE !== 'off' && !skipLog) send('info', `[REQUEST] ${methodStr} ${urlStr}`, requestMeta)
331
385
  const wrappedCb = typeof callback === 'function' ? function (err, data) {
332
386
  const duration = Number((require('perf_hooks').performance.now() - start).toFixed(2))
333
- if (HTTP_CLIENT_MODE !== 'off' && !skipLog) {
334
- if (err) send('error', `[RESPONSE] ${methodStr} ${urlStr} ERROR ${duration}ms`, { ...requestMeta, error: err && err.message, responseTimeMs: duration })
335
- else if (data) send('info', `[RESPONSE] ${methodStr} ${urlStr} ${data.statusCode} ${duration}ms`, { ...requestMeta, statusCode: data.statusCode, responseTimeMs: duration })
387
+ if (err) {
388
+ if (HTTP_CLIENT_MODE !== 'off' && !skipLog) {
389
+ send('error', `[RESPONSE] ${methodStr} ${urlStr} ERROR ${duration}ms`, { ...requestMeta, error: err && err.message, responseTimeMs: duration })
390
+ }
391
+ return callback(err, data)
336
392
  }
337
- return callback(err, data)
393
+ if (!data) return callback(err, data)
394
+ restoreUndiciResponseBodyAfterReadForLog(data).then(({ logStr, data: restored }) => {
395
+ if (HTTP_CLIENT_MODE !== 'off' && !skipLog) {
396
+ const meta = { ...requestMeta, statusCode: restored.statusCode, responseTimeMs: duration }
397
+ if (logStr != null) meta.responseBody = logStr
398
+ send('info', `[RESPONSE] ${methodStr} ${urlStr} ${restored.statusCode} ${duration}ms`, meta)
399
+ }
400
+ return callback(null, restored)
401
+ }).catch(() => {
402
+ if (HTTP_CLIENT_MODE !== 'off' && !skipLog) {
403
+ send('info', `[RESPONSE] ${methodStr} ${urlStr} ${data.statusCode} ${duration}ms`, { ...requestMeta, statusCode: data.statusCode, responseTimeMs: duration })
404
+ }
405
+ return callback(null, data)
406
+ })
338
407
  } : undefined
339
408
  const ret = wrappedCb ? origReq.call(this, opts, wrappedCb) : origReq.call(this, opts)
340
409
  if (ret && typeof ret.then === 'function' && !wrappedCb) {
341
410
  return ret.then(
342
- (data) => {
411
+ async (data) => {
343
412
  const duration = Number((require('perf_hooks').performance.now() - start).toFixed(2))
344
- if (HTTP_CLIENT_MODE !== 'off' && !skipLog && data) send('info', `[RESPONSE] ${methodStr} ${urlStr} ${data.statusCode} ${duration}ms`, { ...requestMeta, statusCode: data.statusCode, responseTimeMs: duration })
413
+ if (HTTP_CLIENT_MODE !== 'off' && !skipLog && data) {
414
+ const { logStr, data: restored } = await restoreUndiciResponseBodyAfterReadForLog(data)
415
+ const meta = { ...requestMeta, statusCode: restored.statusCode, responseTimeMs: duration }
416
+ if (logStr != null) meta.responseBody = logStr
417
+ send('info', `[RESPONSE] ${methodStr} ${urlStr} ${restored.statusCode} ${duration}ms`, meta)
418
+ return restored
419
+ }
345
420
  return data
346
421
  },
347
422
  (err) => {
@@ -401,25 +476,48 @@ try {
401
476
  const traceCtx = ctx || otelCtx
402
477
  const rawTraceId = (traceCtx && traceCtx.traceId) || (require('crypto').randomUUID && require('crypto').randomUUID())
403
478
  const traceId = typeof rawTraceId === 'string' ? (toTraceIdHex ? toTraceIdHex(rawTraceId) : rawTraceId) : rawTraceId
479
+ const requestBodyStr = serializeUndiciRequestBody(opts || {})
404
480
  const requestMeta = { traceId, spanId: (traceCtx && traceCtx.spanId) || null, parentSpanId: (traceCtx && traceCtx.parentSpanId) || null, requestId: (traceCtx && traceCtx.requestId) || null, method: methodStr, url: urlStr }
481
+ if (requestBodyStr != null) requestMeta.requestBody = requestBodyStr
405
482
  if (markSource) markSource(requestMeta, 'http-client')
406
483
  const start = require('perf_hooks').performance.now()
407
484
  const skipLog = isLoggerUrl(urlStr)
408
485
  if (HTTP_CLIENT_MODE !== 'off' && !skipLog) send('info', `[REQUEST] ${methodStr} ${urlStr}`, requestMeta)
409
486
  const wrappedCb = typeof callback === 'function' ? function (err, data) {
410
487
  const duration = Number((require('perf_hooks').performance.now() - start).toFixed(2))
411
- if (HTTP_CLIENT_MODE !== 'off' && !skipLog) {
412
- if (err) send('error', `[RESPONSE] ${methodStr} ${urlStr} ERROR ${duration}ms`, { ...requestMeta, error: err && err.message, responseTimeMs: duration })
413
- else if (data) send('info', `[RESPONSE] ${methodStr} ${urlStr} ${data.statusCode} ${duration}ms`, { ...requestMeta, statusCode: data.statusCode, responseTimeMs: duration })
488
+ if (err) {
489
+ if (HTTP_CLIENT_MODE !== 'off' && !skipLog) {
490
+ send('error', `[RESPONSE] ${methodStr} ${urlStr} ERROR ${duration}ms`, { ...requestMeta, error: err && err.message, responseTimeMs: duration })
491
+ }
492
+ return callback(err, data)
414
493
  }
415
- return callback(err, data)
494
+ if (!data) return callback(err, data)
495
+ restoreUndiciResponseBodyAfterReadForLog(data).then(({ logStr, data: restored }) => {
496
+ if (HTTP_CLIENT_MODE !== 'off' && !skipLog) {
497
+ const meta = { ...requestMeta, statusCode: restored.statusCode, responseTimeMs: duration }
498
+ if (logStr != null) meta.responseBody = logStr
499
+ send('info', `[RESPONSE] ${methodStr} ${urlStr} ${restored.statusCode} ${duration}ms`, meta)
500
+ }
501
+ return callback(null, restored)
502
+ }).catch(() => {
503
+ if (HTTP_CLIENT_MODE !== 'off' && !skipLog) {
504
+ send('info', `[RESPONSE] ${methodStr} ${urlStr} ${data.statusCode} ${duration}ms`, { ...requestMeta, statusCode: data.statusCode, responseTimeMs: duration })
505
+ }
506
+ return callback(null, data)
507
+ })
416
508
  } : undefined
417
509
  const ret = wrappedCb ? origReq.call(this, opts, wrappedCb) : origReq.call(this, opts)
418
510
  if (ret && typeof ret.then === 'function' && !wrappedCb) {
419
511
  return ret.then(
420
- (data) => {
512
+ async (data) => {
421
513
  const duration = Number((require('perf_hooks').performance.now() - start).toFixed(2))
422
- if (HTTP_CLIENT_MODE !== 'off' && !skipLog && data) send('info', `[RESPONSE] ${methodStr} ${urlStr} ${data.statusCode} ${duration}ms`, { ...requestMeta, statusCode: data.statusCode, responseTimeMs: duration })
514
+ if (HTTP_CLIENT_MODE !== 'off' && !skipLog && data) {
515
+ const { logStr, data: restored } = await restoreUndiciResponseBodyAfterReadForLog(data)
516
+ const meta = { ...requestMeta, statusCode: restored.statusCode, responseTimeMs: duration }
517
+ if (logStr != null) meta.responseBody = logStr
518
+ send('info', `[RESPONSE] ${methodStr} ${urlStr} ${restored.statusCode} ${duration}ms`, meta)
519
+ return restored
520
+ }
423
521
  return data
424
522
  },
425
523
  (err) => {
package/register.js CHANGED
@@ -445,16 +445,24 @@ try {
445
445
  const { randomBytes } = require('crypto')
446
446
  const { performance } = require('perf_hooks')
447
447
  const { getRequestContext, getLastJobContext, toTraceIdHex } = require('./store')
448
+ const {
449
+ resolveUndiciRequestOpts,
450
+ serializeUndiciRequestBody,
451
+ restoreUndiciResponseBodyAfterReadForLog
452
+ } = require('./utils/undiciLogBodies')
448
453
  const origRequest = exports.request
449
454
  exports.request = function(url, options, callback) {
450
455
  const ctx = getRequestContext() || getLastJobContext()
451
456
  const otelCtx = getOtelTraceContext()
452
457
  const traceCtx = ctx || otelCtx
453
- const method = (options?.method || 'GET').toUpperCase()
458
+ const reqOpts = resolveUndiciRequestOpts(url, options)
459
+ const method = (reqOpts.method || options?.method || 'GET').toUpperCase()
454
460
  const urlString = typeof url === 'string' ? url : (url && url.toString && url.toString()) || 'unknown'
455
461
  const rawTraceId = traceCtx?.traceId || (require('crypto').randomUUID && require('crypto').randomUUID())
456
462
  const traceId = typeof rawTraceId === 'string' ? toTraceIdHex(rawTraceId) : rawTraceId
463
+ const requestBodyStr = serializeUndiciRequestBody(reqOpts)
457
464
  const requestMeta = { traceId, spanId: traceCtx?.spanId || null, parentSpanId: traceCtx?.parentSpanId || null, requestId: traceCtx?.requestId || null, method, url: urlString }
465
+ if (requestBodyStr != null) requestMeta.requestBody = requestBodyStr
458
466
  markSource(requestMeta, 'http-client')
459
467
  const startTime = performance.now()
460
468
  if (HTTP_CLIENT_MODE !== 'off') {
@@ -462,20 +470,39 @@ try {
462
470
  }
463
471
  const wrappedCb = callback ? function(err, data) {
464
472
  const duration = Number((performance.now() - startTime).toFixed(2))
465
- if (HTTP_CLIENT_MODE !== 'off') {
466
- if (err) sendOutboundLog('error', `[RESPONSE] ${method} ${urlString} ERROR ${duration}ms`, { ...requestMeta, error: err && err.message, responseTimeMs: duration })
467
- else if (data) sendOutboundLog('info', `[RESPONSE] ${method} ${urlString} ${data.statusCode} ${duration}ms`, { ...requestMeta, statusCode: data.statusCode, responseTimeMs: duration })
473
+ if (err) {
474
+ if (HTTP_CLIENT_MODE !== 'off') {
475
+ sendOutboundLog('error', `[RESPONSE] ${method} ${urlString} ERROR ${duration}ms`, { ...requestMeta, error: err && err.message, responseTimeMs: duration })
476
+ }
477
+ return callback(err, data)
468
478
  }
469
- return callback(err, data)
479
+ if (!data) return callback(err, data)
480
+ restoreUndiciResponseBodyAfterReadForLog(data).then(({ logStr, data: restored }) => {
481
+ if (HTTP_CLIENT_MODE !== 'off') {
482
+ const meta = { ...requestMeta, statusCode: restored.statusCode, responseTimeMs: duration }
483
+ if (logStr != null) meta.responseBody = logStr
484
+ sendOutboundLog('info', `[RESPONSE] ${method} ${urlString} ${restored.statusCode} ${duration}ms`, meta)
485
+ }
486
+ return callback(null, restored)
487
+ }).catch(() => {
488
+ if (HTTP_CLIENT_MODE !== 'off') {
489
+ sendOutboundLog('info', `[RESPONSE] ${method} ${urlString} ${data.statusCode} ${duration}ms`, { ...requestMeta, statusCode: data.statusCode, responseTimeMs: duration })
490
+ }
491
+ return callback(null, data)
492
+ })
470
493
  } : undefined
471
494
  if (wrappedCb) return origRequest.call(this, url, options, wrappedCb)
472
495
  const promise = origRequest.call(this, url, options)
473
496
  if (promise && typeof promise.then === 'function') {
474
497
  return promise.then(
475
- (data) => {
498
+ async (data) => {
476
499
  const duration = Number((performance.now() - startTime).toFixed(2))
477
500
  if (HTTP_CLIENT_MODE !== 'off' && data) {
478
- sendOutboundLog('info', `[RESPONSE] ${method} ${urlString} ${data.statusCode} ${duration}ms`, { ...requestMeta, statusCode: data.statusCode, responseTimeMs: duration })
501
+ const { logStr, data: restored } = await restoreUndiciResponseBodyAfterReadForLog(data)
502
+ const meta = { ...requestMeta, statusCode: restored.statusCode, responseTimeMs: duration }
503
+ if (logStr != null) meta.responseBody = logStr
504
+ sendOutboundLog('info', `[RESPONSE] ${method} ${urlString} ${restored.statusCode} ${duration}ms`, meta)
505
+ return restored
479
506
  }
480
507
  return data
481
508
  },
@@ -504,7 +531,9 @@ try {
504
531
  const urlString = origin ? (origin + (path.startsWith('/') ? path : '/' + path)) : 'unknown'
505
532
  const rawTraceId = traceCtx?.traceId || (require('crypto').randomUUID && require('crypto').randomUUID())
506
533
  const traceId = typeof rawTraceId === 'string' ? toTraceIdHex(rawTraceId) : rawTraceId
534
+ const requestBodyStr = serializeUndiciRequestBody(opts || {})
507
535
  const requestMeta = { traceId, spanId: traceCtx?.spanId || null, parentSpanId: traceCtx?.parentSpanId || null, requestId: traceCtx?.requestId || null, method: methodStr, url: urlString }
536
+ if (requestBodyStr != null) requestMeta.requestBody = requestBodyStr
508
537
  markSource(requestMeta, 'http-client')
509
538
  const startTime = performance.now()
510
539
  if (HTTP_CLIENT_MODE !== 'off') {
@@ -512,19 +541,38 @@ try {
512
541
  }
513
542
  const wrappedCb = typeof callback === 'function' ? function(err, data) {
514
543
  const duration = Number((performance.now() - startTime).toFixed(2))
515
- if (HTTP_CLIENT_MODE !== 'off') {
516
- if (err) sendOutboundLog('error', `[RESPONSE] ${methodStr} ${urlString} ERROR ${duration}ms`, { ...requestMeta, error: err && err.message, responseTimeMs: duration })
517
- else if (data) sendOutboundLog('info', `[RESPONSE] ${methodStr} ${urlString} ${data.statusCode} ${duration}ms`, { ...requestMeta, statusCode: data.statusCode, responseTimeMs: duration })
544
+ if (err) {
545
+ if (HTTP_CLIENT_MODE !== 'off') {
546
+ sendOutboundLog('error', `[RESPONSE] ${methodStr} ${urlString} ERROR ${duration}ms`, { ...requestMeta, error: err && err.message, responseTimeMs: duration })
547
+ }
548
+ return callback(err, data)
518
549
  }
519
- return callback(err, data)
550
+ if (!data) return callback(err, data)
551
+ restoreUndiciResponseBodyAfterReadForLog(data).then(({ logStr, data: restored }) => {
552
+ if (HTTP_CLIENT_MODE !== 'off') {
553
+ const meta = { ...requestMeta, statusCode: restored.statusCode, responseTimeMs: duration }
554
+ if (logStr != null) meta.responseBody = logStr
555
+ sendOutboundLog('info', `[RESPONSE] ${methodStr} ${urlString} ${restored.statusCode} ${duration}ms`, meta)
556
+ }
557
+ return callback(null, restored)
558
+ }).catch(() => {
559
+ if (HTTP_CLIENT_MODE !== 'off') {
560
+ sendOutboundLog('info', `[RESPONSE] ${methodStr} ${urlString} ${data.statusCode} ${duration}ms`, { ...requestMeta, statusCode: data.statusCode, responseTimeMs: duration })
561
+ }
562
+ return callback(null, data)
563
+ })
520
564
  } : undefined
521
565
  const ret = wrappedCb ? origDispRequest.call(this, opts, wrappedCb) : origDispRequest.call(this, opts)
522
566
  if (ret && typeof ret.then === 'function' && !wrappedCb) {
523
567
  return ret.then(
524
- (data) => {
568
+ async (data) => {
525
569
  const duration = Number((performance.now() - startTime).toFixed(2))
526
570
  if (HTTP_CLIENT_MODE !== 'off' && data) {
527
- sendOutboundLog('info', `[RESPONSE] ${methodStr} ${urlString} ${data.statusCode} ${duration}ms`, { ...requestMeta, statusCode: data.statusCode, responseTimeMs: duration })
571
+ const { logStr, data: restored } = await restoreUndiciResponseBodyAfterReadForLog(data)
572
+ const meta = { ...requestMeta, statusCode: restored.statusCode, responseTimeMs: duration }
573
+ if (logStr != null) meta.responseBody = logStr
574
+ sendOutboundLog('info', `[RESPONSE] ${methodStr} ${urlString} ${restored.statusCode} ${duration}ms`, meta)
575
+ return restored
528
576
  }
529
577
  return data
530
578
  },
@@ -1966,19 +2014,35 @@ try {
1966
2014
  } catch (_) {
1967
2015
  }
1968
2016
 
2017
+ const maxFetchBodyChars = Math.min(
2018
+ Math.max(parseInt(String(process.env.AZIFY_LOGGER_HTTP_BODY_MAX_CHARS || '5000'), 10) || 5000, 100),
2019
+ 100000
2020
+ )
2021
+ const clipFetchBody = (s) => {
2022
+ if (typeof s !== 'string' || !s.length) return null
2023
+ return s.length > maxFetchBodyChars ? s.slice(0, maxFetchBodyChars) : s
2024
+ }
2025
+
1969
2026
  let requestBodyString = null
1970
- if (init && init.body !== null && init.body !== undefined) {
1971
- try {
2027
+ try {
2028
+ if (init && init.body !== null && init.body !== undefined) {
1972
2029
  if (typeof init.body === 'string') {
1973
- requestBodyString = init.body
2030
+ requestBodyString = clipFetchBody(init.body)
1974
2031
  } else if (init.body instanceof FormData || init.body instanceof URLSearchParams) {
1975
2032
  requestBodyString = '[FormData/URLSearchParams]'
1976
- } else if (typeof init.body === 'object' && !(init.body instanceof Blob) && !(init.body instanceof ArrayBuffer)) {
1977
- try {
1978
- requestBodyString = JSON.stringify(init.body)
1979
- } catch (_) {
1980
- requestBodyString = String(init.body)
1981
- }
2033
+ }
2034
+ }
2035
+ } catch (_) {
2036
+ }
2037
+ if (requestBodyString == null && request.body != null && method !== 'GET' && method !== 'HEAD') {
2038
+ try {
2039
+ const clone = request.clone()
2040
+ const text = await Promise.race([
2041
+ clone.text(),
2042
+ new Promise((resolve) => setTimeout(() => resolve(null), 4000))
2043
+ ])
2044
+ if (typeof text === 'string' && text.length) {
2045
+ requestBodyString = clipFetchBody(text)
1982
2046
  }
1983
2047
  } catch (_) {
1984
2048
  }
@@ -2085,10 +2149,15 @@ try {
2085
2149
  }
2086
2150
  }
2087
2151
 
2152
+ const responseReadMs = Math.min(
2153
+ Math.max(parseInt(String(process.env.AZIFY_LOGGER_HTTP_RESPONSE_READ_MS || '4000'), 10) || 4000, 200),
2154
+ 30000
2155
+ )
2156
+
2088
2157
  if (contentType.includes('application/json') || contentType.includes('text/')) {
2089
2158
  try {
2090
2159
  const clonedResponse = response.clone()
2091
- const bodyText = await readBodyWithTimeout(clonedResponse, 200)
2160
+ const bodyText = await readBodyWithTimeout(clonedResponse, responseReadMs)
2092
2161
  if (bodyText) {
2093
2162
  if (contentType.includes('application/json')) {
2094
2163
  try {
@@ -2099,13 +2168,13 @@ try {
2099
2168
  } else {
2100
2169
  responseBodyString = bodyText
2101
2170
  }
2102
- if (typeof responseBodyString === 'string' && responseBodyString.length > 5000) {
2103
- responseBodyString = responseBodyString.slice(0, 5000)
2171
+ if (typeof responseBodyString === 'string' && responseBodyString.length > maxFetchBodyChars) {
2172
+ responseBodyString = responseBodyString.slice(0, maxFetchBodyChars)
2104
2173
  }
2105
2174
  }
2106
2175
  } catch (_) {
2107
2176
  try {
2108
- const bodyText = await readBodyWithTimeout(response, 200)
2177
+ const bodyText = await readBodyWithTimeout(response, responseReadMs)
2109
2178
  if (bodyText) {
2110
2179
  if (contentType.includes('application/json')) {
2111
2180
  try {
@@ -2116,13 +2185,23 @@ try {
2116
2185
  } else {
2117
2186
  responseBodyString = bodyText
2118
2187
  }
2119
- if (typeof responseBodyString === 'string' && responseBodyString.length > 5000) {
2120
- responseBodyString = responseBodyString.slice(0, 5000)
2188
+ if (typeof responseBodyString === 'string' && responseBodyString.length > maxFetchBodyChars) {
2189
+ responseBodyString = responseBodyString.slice(0, maxFetchBodyChars)
2121
2190
  }
2122
2191
  }
2123
2192
  } catch (_) {
2124
2193
  }
2125
2194
  }
2195
+ } else if (response.status !== 204 && response.status !== 205 && response.status !== 304) {
2196
+ try {
2197
+ const clonedResponse = response.clone()
2198
+ const bodyText = await readBodyWithTimeout(clonedResponse, responseReadMs)
2199
+ if (bodyText && bodyText.length) {
2200
+ responseBodyString =
2201
+ bodyText.length > maxFetchBodyChars ? bodyText.slice(0, maxFetchBodyChars) : bodyText
2202
+ }
2203
+ } catch (_) {
2204
+ }
2126
2205
  }
2127
2206
  } catch (_) {
2128
2207
  }
@@ -0,0 +1,83 @@
1
+ 'use strict'
2
+
3
+ function maxBodyChars() {
4
+ return Math.min(
5
+ Math.max(parseInt(String(process.env.AZIFY_LOGGER_HTTP_BODY_MAX_CHARS || '5000'), 10) || 5000, 100),
6
+ 100000
7
+ )
8
+ }
9
+
10
+ function clip(s) {
11
+ const m = maxBodyChars()
12
+ if (typeof s !== 'string' || !s.length) return null
13
+ return s.length > m ? s.slice(0, m) : s
14
+ }
15
+
16
+ /** undici: request(url, opts) ou request(opts) — retorna o objeto de opções com body/method. */
17
+ function resolveUndiciRequestOpts(url, options) {
18
+ if (typeof url === 'object' && url !== null && !(url instanceof URL)) {
19
+ return url
20
+ }
21
+ return options && typeof options === 'object' ? options : {}
22
+ }
23
+
24
+ function serializeUndiciRequestBody(opts) {
25
+ if (!opts || opts.body == null || opts.body === undefined) return null
26
+ try {
27
+ if (typeof opts.body === 'string') return clip(opts.body)
28
+ if (Buffer.isBuffer(opts.body)) return clip(opts.body.toString('utf8'))
29
+ if (opts.body && typeof opts.body.pipe === 'function') return '[Stream]'
30
+ return clip(String(opts.body))
31
+ } catch (_) {
32
+ return null
33
+ }
34
+ }
35
+
36
+ function responseReadTimeoutMs() {
37
+ return Math.min(
38
+ Math.max(parseInt(String(process.env.AZIFY_LOGGER_HTTP_RESPONSE_READ_MS || '4000'), 10) || 4000, 200),
39
+ 30000
40
+ )
41
+ }
42
+
43
+ /**
44
+ * Lê o body da resposta undici para log e substitui `data.body` por um objeto com .text()/.json()
45
+ * compatível com o que o undici expõe, para o chamador ainda conseguir fazer parse.
46
+ */
47
+ async function restoreUndiciResponseBodyAfterReadForLog(data) {
48
+ if (!data || !data.body || typeof data.body.text !== 'function') {
49
+ return { logStr: null, data }
50
+ }
51
+ const timeoutMs = responseReadTimeoutMs()
52
+ try {
53
+ const text = await Promise.race([
54
+ data.body.text(),
55
+ new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), timeoutMs))
56
+ ])
57
+ if (text == null || typeof text !== 'string') {
58
+ return { logStr: null, data }
59
+ }
60
+ const logStr = clip(text)
61
+ data.body = {
62
+ async text() {
63
+ return text
64
+ },
65
+ async json() {
66
+ return JSON.parse(text)
67
+ },
68
+ async arrayBuffer() {
69
+ return Buffer.from(text, 'utf8').buffer
70
+ }
71
+ }
72
+ return { logStr, data }
73
+ } catch (_) {
74
+ return { logStr: null, data }
75
+ }
76
+ }
77
+
78
+ module.exports = {
79
+ resolveUndiciRequestOpts,
80
+ serializeUndiciRequestBody,
81
+ restoreUndiciResponseBodyAfterReadForLog,
82
+ maxBodyChars
83
+ }