azify-logger 1.0.34 → 1.0.36
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 +78 -55
- package/package.json +2 -2
- package/register.js +231 -347
- package/sampling.js +3 -0
- package/scripts/redis-worker.js +0 -31
- package/server.js +2 -2
package/middleware-express.js
CHANGED
|
@@ -210,10 +210,6 @@ function createExpressLoggingMiddleware(options = {}) {
|
|
|
210
210
|
|
|
211
211
|
const ctx = ensureRequestContext()
|
|
212
212
|
|
|
213
|
-
runWithRequestContext(ctx, () => {
|
|
214
|
-
next()
|
|
215
|
-
})
|
|
216
|
-
|
|
217
213
|
const logWithContext = (level, message, meta) => {
|
|
218
214
|
const otelCtx = getOtelTraceContext()
|
|
219
215
|
const ctx = getRequestContext() || ensureRequestContext()
|
|
@@ -284,8 +280,10 @@ function createExpressLoggingMiddleware(options = {}) {
|
|
|
284
280
|
}
|
|
285
281
|
if (query) request.query = query
|
|
286
282
|
if (config.captureHeaders && cachedHeaders) request.headers = cachedHeaders
|
|
283
|
+
let requestBody = null
|
|
287
284
|
if (config.captureRequestBody && req.body !== undefined && req.body != null) {
|
|
288
|
-
|
|
285
|
+
requestBody = safeSerializeBody(req.body)
|
|
286
|
+
request.body = requestBody
|
|
289
287
|
}
|
|
290
288
|
|
|
291
289
|
const meta = {
|
|
@@ -294,18 +292,10 @@ function createExpressLoggingMiddleware(options = {}) {
|
|
|
294
292
|
parentSpanId: reqCtx.parentSpanId || null,
|
|
295
293
|
requestId,
|
|
296
294
|
request,
|
|
295
|
+
requestBody,
|
|
297
296
|
timestamp: Date.now(),
|
|
298
297
|
hostname
|
|
299
298
|
}
|
|
300
|
-
|
|
301
|
-
if (config.captureRequestBody && req.body !== undefined && req.body != null) {
|
|
302
|
-
const serializedBody = safeSerializeBody(req.body)
|
|
303
|
-
if (typeof serializedBody === 'string') {
|
|
304
|
-
meta.requestBody = serializedBody
|
|
305
|
-
} else {
|
|
306
|
-
meta.requestBody = JSON.stringify(serializedBody)
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
299
|
if (serviceObj) meta.service = serviceObj
|
|
310
300
|
if (config.environment) meta.environment = config.environment
|
|
311
301
|
|
|
@@ -316,11 +306,6 @@ function createExpressLoggingMiddleware(options = {}) {
|
|
|
316
306
|
const originalEnd = res.end.bind(res)
|
|
317
307
|
|
|
318
308
|
res.end = (chunk, encoding) => {
|
|
319
|
-
if (logSent) {
|
|
320
|
-
return originalEnd(chunk, encoding)
|
|
321
|
-
}
|
|
322
|
-
logSent = true
|
|
323
|
-
|
|
324
309
|
const result = originalEnd(chunk, encoding)
|
|
325
310
|
|
|
326
311
|
if (chunk != null && config.captureResponseBody && !responseChunkCaptured) {
|
|
@@ -328,46 +313,84 @@ function createExpressLoggingMiddleware(options = {}) {
|
|
|
328
313
|
responseChunkCaptured = true
|
|
329
314
|
}
|
|
330
315
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
const statusCode = res.statusCode || 200
|
|
335
|
-
const duration = Date.now() - startTime
|
|
336
|
-
const response = { statusCode, durationMs: duration }
|
|
337
|
-
|
|
338
|
-
if (config.captureHeaders) {
|
|
339
|
-
ensureHeaders()
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
const requestObj = {
|
|
343
|
-
id: requestId,
|
|
344
|
-
method,
|
|
345
|
-
url,
|
|
346
|
-
path,
|
|
347
|
-
ip: clientIp
|
|
348
|
-
}
|
|
349
|
-
if (query) requestObj.query = query
|
|
350
|
-
if (config.captureHeaders && cachedHeaders) requestObj.headers = cachedHeaders
|
|
316
|
+
if (!logSent) {
|
|
317
|
+
logSent = true
|
|
351
318
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
319
|
+
process.nextTick(() => {
|
|
320
|
+
try {
|
|
321
|
+
ensureIds()
|
|
322
|
+
|
|
323
|
+
const statusCode = res.statusCode || 200
|
|
324
|
+
const duration = Date.now() - startTime
|
|
325
|
+
const response = { statusCode, durationMs: duration }
|
|
326
|
+
|
|
327
|
+
if (config.captureHeaders) {
|
|
328
|
+
ensureHeaders()
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const requestObj = {
|
|
332
|
+
id: requestId,
|
|
333
|
+
method,
|
|
334
|
+
url,
|
|
335
|
+
path,
|
|
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,
|
|
348
|
+
timestamp: Date.now(),
|
|
349
|
+
hostname
|
|
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
|
+
}
|
|
384
|
+
}
|
|
385
|
+
})
|
|
386
|
+
}
|
|
368
387
|
|
|
369
388
|
return result
|
|
370
389
|
}
|
|
390
|
+
|
|
391
|
+
runWithRequestContext(ctx, () => {
|
|
392
|
+
next()
|
|
393
|
+
})
|
|
371
394
|
}
|
|
372
395
|
}
|
|
373
396
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "azify-logger",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.36",
|
|
4
4
|
"description": "Azify Logger Client - Centralized logging for OpenSearch",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"validate:retention": "node scripts/validate-retention.js",
|
|
22
22
|
"inspect:zip": "node scripts/inspect-zip.js",
|
|
23
23
|
"retention": "node scripts/retention-manager.js",
|
|
24
|
-
"list:blob": "node scripts/list-blob-files.js",
|
|
24
|
+
"list:blob": "bash -c 'set -a && source env/app.env && set +a && node scripts/list-blob-files.js'",
|
|
25
25
|
"list:blob:recent": "node scripts/download-blob-zip.js",
|
|
26
26
|
"check:old-logs": "node scripts/check-old-logs.js",
|
|
27
27
|
"validate:blob": "node scripts/validate-blob-zip.js",
|
package/register.js
CHANGED
|
@@ -79,50 +79,34 @@ try {
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
function sendOutboundLog(level, message, meta) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const metaCopy = { ...meta }
|
|
88
|
-
if (metaCopy.requestBody != null) {
|
|
89
|
-
if (typeof metaCopy.requestBody !== 'string') {
|
|
90
|
-
try {
|
|
91
|
-
metaCopy.requestBody = JSON.stringify(metaCopy.requestBody)
|
|
92
|
-
} catch (_) {
|
|
93
|
-
metaCopy.requestBody = String(metaCopy.requestBody)
|
|
94
|
-
}
|
|
82
|
+
try {
|
|
83
|
+
const source = meta && meta.__source
|
|
84
|
+
if (!shouldSample(level, source)) {
|
|
85
|
+
return
|
|
95
86
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
87
|
+
|
|
88
|
+
const payload = {
|
|
89
|
+
level,
|
|
90
|
+
message,
|
|
91
|
+
meta: {
|
|
92
|
+
...meta,
|
|
93
|
+
service: {
|
|
94
|
+
name: serviceName,
|
|
95
|
+
version: (meta && meta.service && meta.service.version) || '1.0.0'
|
|
96
|
+
},
|
|
97
|
+
environment,
|
|
98
|
+
timestamp: new Date().toISOString(),
|
|
99
|
+
hostname: os.hostname()
|
|
104
100
|
}
|
|
105
101
|
}
|
|
106
|
-
}
|
|
107
102
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
...metaCopy,
|
|
113
|
-
service: {
|
|
114
|
-
name: serviceName,
|
|
115
|
-
version: (meta && meta.service && meta.service.version) || '1.0.0'
|
|
116
|
-
},
|
|
117
|
-
environment,
|
|
118
|
-
timestamp: new Date().toISOString(),
|
|
119
|
-
hostname: os.hostname()
|
|
103
|
+
if (transport && typeof transport.enqueue === 'function') {
|
|
104
|
+
transport.enqueue(payload, {
|
|
105
|
+
'content-type': 'application/json'
|
|
106
|
+
})
|
|
120
107
|
}
|
|
108
|
+
} catch (err) {
|
|
121
109
|
}
|
|
122
|
-
|
|
123
|
-
transport.enqueue(payload, {
|
|
124
|
-
'content-type': 'application/json'
|
|
125
|
-
})
|
|
126
110
|
}
|
|
127
111
|
|
|
128
112
|
function normalizePath(path) {
|
|
@@ -173,6 +157,10 @@ try {
|
|
|
173
157
|
return logger
|
|
174
158
|
}
|
|
175
159
|
|
|
160
|
+
const getOtelTraceContext = () => {
|
|
161
|
+
return null
|
|
162
|
+
}
|
|
163
|
+
|
|
176
164
|
try {
|
|
177
165
|
const Module = require('module')
|
|
178
166
|
const originalRequire = Module.prototype.require
|
|
@@ -590,7 +578,12 @@ try {
|
|
|
590
578
|
const childCtx = { traceId, spanId, parentSpanId, requestId }
|
|
591
579
|
config.__azifyChildCtx = childCtx
|
|
592
580
|
|
|
593
|
-
|
|
581
|
+
const shouldLogRequest =
|
|
582
|
+
HTTP_CLIENT_MODE === 'all' ||
|
|
583
|
+
HTTP_CLIENT_MODE === 'errors' ||
|
|
584
|
+
!!traceId
|
|
585
|
+
|
|
586
|
+
if (shouldLogRequest) {
|
|
594
587
|
sendOutboundLog('info', `[REQUEST] ${method} ${url}`, requestMeta)
|
|
595
588
|
}
|
|
596
589
|
|
|
@@ -626,16 +619,34 @@ try {
|
|
|
626
619
|
if (finalUrl && finalUrl !== 'unknown') {
|
|
627
620
|
let meta
|
|
628
621
|
let duration = 0
|
|
622
|
+
|
|
623
|
+
const stringifyBody = (value) => {
|
|
624
|
+
if (value == null) return null
|
|
625
|
+
if (typeof value === 'string') return value
|
|
626
|
+
try {
|
|
627
|
+
return JSON.stringify(value)
|
|
628
|
+
} catch (_) {
|
|
629
|
+
try {
|
|
630
|
+
return String(value)
|
|
631
|
+
} catch (_) {
|
|
632
|
+
return null
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
}
|
|
629
636
|
|
|
630
637
|
if (marker && marker.meta) {
|
|
631
638
|
duration = Number((performance.now() - marker.start).toFixed(2))
|
|
639
|
+
let responseBodyString = stringifyBody(response.data)
|
|
640
|
+
if (typeof responseBodyString === 'string' && responseBodyString.length > 5000) {
|
|
641
|
+
responseBodyString = responseBodyString.slice(0, 5000)
|
|
642
|
+
}
|
|
632
643
|
meta = {
|
|
633
644
|
...marker.meta,
|
|
634
645
|
url: finalUrl,
|
|
635
646
|
statusCode: response.status,
|
|
636
647
|
responseTimeMs: duration,
|
|
637
648
|
responseHeaders: response.headers,
|
|
638
|
-
responseBody:
|
|
649
|
+
responseBody: responseBodyString
|
|
639
650
|
}
|
|
640
651
|
} else {
|
|
641
652
|
const requestHeaders = response.config?.headers || {}
|
|
@@ -644,6 +655,10 @@ try {
|
|
|
644
655
|
const spanId = requestHeaders['x-span-id'] || requestHeaders['X-Span-ID'] || randomBytes(8).toString('hex')
|
|
645
656
|
const parentSpanId = requestHeaders['x-parent-span-id'] || requestHeaders['X-Parent-Span-ID'] || ctx?.spanId || null
|
|
646
657
|
const requestId = requestHeaders['x-request-id'] || requestHeaders['X-Request-ID'] || ctx?.requestId || randomUUID()
|
|
658
|
+
let responseBodyString = stringifyBody(response.data)
|
|
659
|
+
if (typeof responseBodyString === 'string' && responseBodyString.length > 5000) {
|
|
660
|
+
responseBodyString = responseBodyString.slice(0, 5000)
|
|
661
|
+
}
|
|
647
662
|
|
|
648
663
|
meta = {
|
|
649
664
|
traceId,
|
|
@@ -655,7 +670,7 @@ try {
|
|
|
655
670
|
statusCode: response.status,
|
|
656
671
|
responseTimeMs: duration,
|
|
657
672
|
responseHeaders: response.headers,
|
|
658
|
-
responseBody:
|
|
673
|
+
responseBody: responseBodyString
|
|
659
674
|
}
|
|
660
675
|
}
|
|
661
676
|
|
|
@@ -760,7 +775,6 @@ try {
|
|
|
760
775
|
} catch (_) {}
|
|
761
776
|
|
|
762
777
|
try {
|
|
763
|
-
|
|
764
778
|
if (typeof globalThis.fetch === 'function') {
|
|
765
779
|
const g = globalThis
|
|
766
780
|
if (!g.__azifyLoggerFetchPatched) {
|
|
@@ -771,10 +785,24 @@ try {
|
|
|
771
785
|
const originalFetch = globalThis.fetch.bind(globalThis)
|
|
772
786
|
|
|
773
787
|
function ensureRequest(input, init) {
|
|
774
|
-
|
|
775
|
-
|
|
788
|
+
try {
|
|
789
|
+
if (typeof Request !== 'undefined' && input instanceof Request) {
|
|
790
|
+
if (init) {
|
|
791
|
+
return new Request(input, init)
|
|
792
|
+
}
|
|
793
|
+
return input
|
|
794
|
+
}
|
|
795
|
+
if (init) {
|
|
796
|
+
return new Request(input, init)
|
|
797
|
+
}
|
|
798
|
+
return new Request(input, {})
|
|
799
|
+
} catch (err) {
|
|
800
|
+
try {
|
|
801
|
+
return new Request(input, init || {})
|
|
802
|
+
} catch (err2) {
|
|
803
|
+
return new Request(String(input), {})
|
|
804
|
+
}
|
|
776
805
|
}
|
|
777
|
-
return new Request(input, init)
|
|
778
806
|
}
|
|
779
807
|
|
|
780
808
|
globalThis.fetch = async function patchedFetch(input, init) {
|
|
@@ -782,60 +810,35 @@ try {
|
|
|
782
810
|
return originalFetch(input, init)
|
|
783
811
|
}
|
|
784
812
|
|
|
785
|
-
let
|
|
786
|
-
let method = '
|
|
813
|
+
let request
|
|
814
|
+
let method = 'UNKNOWN'
|
|
815
|
+
let url = String(input)
|
|
787
816
|
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
method =
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
method = (init?.method || 'GET').toUpperCase()
|
|
794
|
-
} else if (typeof Request !== 'undefined' && input instanceof Request) {
|
|
795
|
-
url = input.url
|
|
796
|
-
method = input.method.toUpperCase()
|
|
797
|
-
} else {
|
|
817
|
+
try {
|
|
818
|
+
request = ensureRequest(input, init)
|
|
819
|
+
method = request.method.toUpperCase()
|
|
820
|
+
url = request.url
|
|
821
|
+
} catch (err) {
|
|
798
822
|
try {
|
|
799
|
-
|
|
800
|
-
|
|
823
|
+
const basicMeta = {
|
|
824
|
+
traceId: randomUUID(),
|
|
825
|
+
spanId: randomBytes(8).toString('hex'),
|
|
826
|
+
parentSpanId: null,
|
|
827
|
+
requestId: randomUUID(),
|
|
828
|
+
method: (init && init.method) ? String(init.method).toUpperCase() : 'UNKNOWN',
|
|
829
|
+
url: String(input),
|
|
830
|
+
headers: {}
|
|
831
|
+
}
|
|
832
|
+
markSource(basicMeta, 'http-client')
|
|
833
|
+
sendOutboundLog('info', `[REQUEST] ${basicMeta.method} ${basicMeta.url}`, basicMeta)
|
|
801
834
|
} catch (_) {
|
|
802
|
-
return originalFetch(input, init)
|
|
803
835
|
}
|
|
836
|
+
return originalFetch(input, init)
|
|
804
837
|
}
|
|
805
|
-
|
|
838
|
+
|
|
806
839
|
const testMeta = { url }
|
|
807
840
|
if (isLoggerApiCall(testMeta)) {
|
|
808
|
-
return originalFetch(
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
let requestBody = null
|
|
812
|
-
if (init && init.body != null) {
|
|
813
|
-
try {
|
|
814
|
-
const body = init.body
|
|
815
|
-
if (typeof body === 'string') {
|
|
816
|
-
requestBody = body
|
|
817
|
-
} else if (Buffer.isBuffer(body)) {
|
|
818
|
-
requestBody = body.toString('utf8')
|
|
819
|
-
} else if (body instanceof FormData) {
|
|
820
|
-
requestBody = '[FormData]'
|
|
821
|
-
} else if (body instanceof URLSearchParams) {
|
|
822
|
-
requestBody = body.toString()
|
|
823
|
-
} else if (typeof body === 'object' && body !== null) {
|
|
824
|
-
requestBody = JSON.stringify(body)
|
|
825
|
-
} else {
|
|
826
|
-
requestBody = String(body)
|
|
827
|
-
}
|
|
828
|
-
} catch (error) {
|
|
829
|
-
requestBody = null
|
|
830
|
-
}
|
|
831
|
-
} else if (typeof Request !== 'undefined' && input instanceof Request && input.body && !input.bodyUsed) {
|
|
832
|
-
try {
|
|
833
|
-
const cloned = input.clone()
|
|
834
|
-
const text = await cloned.text()
|
|
835
|
-
requestBody = text
|
|
836
|
-
} catch (_) {
|
|
837
|
-
requestBody = null
|
|
838
|
-
}
|
|
841
|
+
return originalFetch(request)
|
|
839
842
|
}
|
|
840
843
|
|
|
841
844
|
const ctx = getRequestContext()
|
|
@@ -844,6 +847,32 @@ try {
|
|
|
844
847
|
const requestId = (ctx?.requestId) || randomUUID()
|
|
845
848
|
const spanId = randomBytes(8).toString('hex')
|
|
846
849
|
|
|
850
|
+
try {
|
|
851
|
+
request.headers.set('x-trace-id', traceId)
|
|
852
|
+
request.headers.set('x-span-id', spanId)
|
|
853
|
+
request.headers.set('x-parent-span-id', parentSpanId || '')
|
|
854
|
+
request.headers.set('x-request-id', requestId)
|
|
855
|
+
} catch (_) {
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
let requestBodyString = null
|
|
859
|
+
if (init && init.body !== null && init.body !== undefined) {
|
|
860
|
+
try {
|
|
861
|
+
if (typeof init.body === 'string') {
|
|
862
|
+
requestBodyString = init.body
|
|
863
|
+
} else if (init.body instanceof FormData || init.body instanceof URLSearchParams) {
|
|
864
|
+
requestBodyString = '[FormData/URLSearchParams]'
|
|
865
|
+
} else if (typeof init.body === 'object' && !(init.body instanceof Blob) && !(init.body instanceof ArrayBuffer)) {
|
|
866
|
+
try {
|
|
867
|
+
requestBodyString = JSON.stringify(init.body)
|
|
868
|
+
} catch (_) {
|
|
869
|
+
requestBodyString = String(init.body)
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
} catch (_) {
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
|
|
847
876
|
const requestMeta = {
|
|
848
877
|
traceId,
|
|
849
878
|
spanId,
|
|
@@ -854,95 +883,18 @@ try {
|
|
|
854
883
|
headers: {}
|
|
855
884
|
}
|
|
856
885
|
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
try {
|
|
861
|
-
finalRequestBody = JSON.stringify(requestBody)
|
|
862
|
-
} catch (_) {
|
|
863
|
-
finalRequestBody = String(requestBody)
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
requestMeta.requestBody = finalRequestBody
|
|
886
|
+
try {
|
|
887
|
+
requestMeta.headers = Object.fromEntries(request.headers.entries())
|
|
888
|
+
} catch (_) {
|
|
867
889
|
}
|
|
868
890
|
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
let headers
|
|
872
|
-
if (init?.headers instanceof Headers) {
|
|
873
|
-
headers = new Headers(init.headers)
|
|
874
|
-
} else if (init?.headers) {
|
|
875
|
-
headers = new Headers(init.headers)
|
|
876
|
-
} else {
|
|
877
|
-
headers = new Headers()
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
headers.set('x-trace-id', traceId)
|
|
881
|
-
headers.set('x-span-id', spanId)
|
|
882
|
-
headers.set('x-parent-span-id', parentSpanId || '')
|
|
883
|
-
headers.set('x-request-id', requestId)
|
|
884
|
-
|
|
885
|
-
requestMeta.headers = Object.fromEntries(headers.entries())
|
|
886
|
-
|
|
887
|
-
request = ensureRequest(input, {
|
|
888
|
-
...init,
|
|
889
|
-
headers: headers
|
|
890
|
-
})
|
|
891
|
-
} catch (error) {
|
|
892
|
-
if (init?.headers) {
|
|
893
|
-
try {
|
|
894
|
-
requestMeta.headers = typeof init.headers === 'object' && !(init.headers instanceof Headers)
|
|
895
|
-
? init.headers
|
|
896
|
-
: Object.fromEntries(new Headers(init.headers).entries())
|
|
897
|
-
} catch (_) {
|
|
898
|
-
requestMeta.headers = {}
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
request = ensureRequest(input, init)
|
|
891
|
+
if (requestBodyString !== null) {
|
|
892
|
+
requestMeta.requestBody = requestBodyString
|
|
903
893
|
}
|
|
904
894
|
|
|
905
895
|
markSource(requestMeta, 'http-client')
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
HTTP_CLIENT_MODE === 'all' ||
|
|
909
|
-
HTTP_CLIENT_MODE === 'errors' ||
|
|
910
|
-
hasTraceHeaders
|
|
911
|
-
|
|
912
|
-
let requestWasLogged = false
|
|
913
|
-
|
|
914
|
-
if (shouldLogRequest) {
|
|
915
|
-
const metaCopy = { ...requestMeta }
|
|
916
|
-
if (metaCopy.requestBody != null && typeof metaCopy.requestBody !== 'string') {
|
|
917
|
-
try {
|
|
918
|
-
metaCopy.requestBody = JSON.stringify(metaCopy.requestBody)
|
|
919
|
-
} catch (_) {
|
|
920
|
-
metaCopy.requestBody = String(metaCopy.requestBody)
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
const payload = {
|
|
924
|
-
level: 'info',
|
|
925
|
-
message: `[REQUEST] ${method} ${url}`,
|
|
926
|
-
meta: {
|
|
927
|
-
...metaCopy,
|
|
928
|
-
service: {
|
|
929
|
-
name: serviceName,
|
|
930
|
-
version: '1.0.0'
|
|
931
|
-
},
|
|
932
|
-
environment,
|
|
933
|
-
timestamp: new Date().toISOString(),
|
|
934
|
-
hostname: os.hostname()
|
|
935
|
-
}
|
|
936
|
-
}
|
|
937
|
-
try {
|
|
938
|
-
transport.enqueue(payload, {
|
|
939
|
-
'content-type': 'application/json'
|
|
940
|
-
})
|
|
941
|
-
requestWasLogged = true
|
|
942
|
-
} catch (enqueueErr) {
|
|
943
|
-
sendOutboundLog('info', `[REQUEST] ${method} ${url}`, requestMeta)
|
|
944
|
-
requestWasLogged = true
|
|
945
|
-
}
|
|
896
|
+
if (HTTP_CLIENT_MODE !== 'off') {
|
|
897
|
+
sendOutboundLog('info', `[REQUEST] ${method} ${url}`, requestMeta)
|
|
946
898
|
}
|
|
947
899
|
|
|
948
900
|
const childCtx = {
|
|
@@ -954,202 +906,134 @@ try {
|
|
|
954
906
|
|
|
955
907
|
const start = performance.now()
|
|
956
908
|
|
|
909
|
+
let response
|
|
957
910
|
try {
|
|
958
|
-
|
|
911
|
+
response = await runWithRequestContext(childCtx, function() {
|
|
959
912
|
return originalFetch(request)
|
|
960
913
|
})
|
|
961
|
-
|
|
914
|
+
} catch (error) {
|
|
962
915
|
const duration = Number((performance.now() - start).toFixed(2))
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
916
|
+
try {
|
|
917
|
+
const errorMeta = {
|
|
918
|
+
...requestMeta,
|
|
919
|
+
responseTimeMs: duration
|
|
920
|
+
}
|
|
921
|
+
markSource(errorMeta, 'http-client')
|
|
922
|
+
const err = error instanceof Error ? error : new Error(String(error))
|
|
923
|
+
errorMeta.error = {
|
|
924
|
+
name: err.name,
|
|
925
|
+
message: err.message,
|
|
926
|
+
stack: err.stack
|
|
927
|
+
}
|
|
928
|
+
sendOutboundLog('error', `[ERROR] ${method} ${url}`, errorMeta)
|
|
929
|
+
} catch (_) {
|
|
930
|
+
}
|
|
931
|
+
throw error
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
const duration = Number((performance.now() - start).toFixed(2))
|
|
935
|
+
const shouldLogResponse = HTTP_CLIENT_MODE !== 'off'
|
|
970
936
|
|
|
971
|
-
|
|
972
|
-
|
|
937
|
+
if (shouldLogResponse && response) {
|
|
938
|
+
const headersToObject = (headers) => {
|
|
973
939
|
try {
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
940
|
+
if (!headers) return {}
|
|
941
|
+
if (typeof headers.entries === 'function') {
|
|
942
|
+
return Object.fromEntries(headers.entries())
|
|
943
|
+
}
|
|
944
|
+
if (typeof headers.forEach === 'function') {
|
|
945
|
+
const out = {}
|
|
946
|
+
headers.forEach((value, key) => {
|
|
947
|
+
out[key] = value
|
|
948
|
+
})
|
|
949
|
+
return out
|
|
950
|
+
}
|
|
951
|
+
if (typeof headers === 'object') {
|
|
952
|
+
return { ...headers }
|
|
953
|
+
}
|
|
954
|
+
} catch (_) {
|
|
977
955
|
}
|
|
956
|
+
return {}
|
|
978
957
|
}
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
}
|
|
996
|
-
} else {
|
|
997
|
-
responseBody = bodyText
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
} catch (cloneError) {
|
|
1001
|
-
try {
|
|
1002
|
-
if (contentType.includes('application/json') || contentType.includes('text/')) {
|
|
1003
|
-
const bodyText = await response.text()
|
|
1004
|
-
if (contentType.includes('application/json')) {
|
|
1005
|
-
try {
|
|
1006
|
-
responseBody = JSON.parse(bodyText)
|
|
1007
|
-
} catch (_) {
|
|
1008
|
-
responseBody = bodyText
|
|
1009
|
-
}
|
|
1010
|
-
} else {
|
|
1011
|
-
responseBody = bodyText
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1014
|
-
} catch (_) {
|
|
1015
|
-
responseBody = null
|
|
1016
|
-
}
|
|
1017
|
-
}
|
|
1018
|
-
} else {
|
|
1019
|
-
responseBody = null
|
|
958
|
+
|
|
959
|
+
let responseBodyString = null
|
|
960
|
+
let responseHeaders = {}
|
|
961
|
+
|
|
962
|
+
try {
|
|
963
|
+
responseHeaders = headersToObject(response.headers)
|
|
964
|
+
const contentType = response.headers.get('content-type') || ''
|
|
965
|
+
const readBodyWithTimeout = async (resp, timeoutMs) => {
|
|
966
|
+
try {
|
|
967
|
+
const timed = await Promise.race([
|
|
968
|
+
resp.text(),
|
|
969
|
+
new Promise((resolve) => setTimeout(() => resolve(null), timeoutMs))
|
|
970
|
+
])
|
|
971
|
+
return typeof timed === 'string' ? timed : null
|
|
972
|
+
} catch (_) {
|
|
973
|
+
return null
|
|
1020
974
|
}
|
|
1021
|
-
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
if (contentType.includes('application/json') || contentType.includes('text/')) {
|
|
1022
978
|
try {
|
|
1023
|
-
const
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
const level = response.status >= 500 ? 'error' : response.status >= 400 ? 'warn' : 'info'
|
|
1035
|
-
|
|
1036
|
-
const metaCopy = { ...responseMeta }
|
|
1037
|
-
if (metaCopy.responseBody != null && typeof metaCopy.responseBody !== 'string') {
|
|
1038
|
-
try {
|
|
1039
|
-
metaCopy.responseBody = JSON.stringify(metaCopy.responseBody)
|
|
1040
|
-
} catch (_) {
|
|
1041
|
-
metaCopy.responseBody = String(metaCopy.responseBody)
|
|
979
|
+
const clonedResponse = response.clone()
|
|
980
|
+
const bodyText = await readBodyWithTimeout(clonedResponse, 200)
|
|
981
|
+
if (bodyText) {
|
|
982
|
+
if (contentType.includes('application/json')) {
|
|
983
|
+
try {
|
|
984
|
+
responseBodyString = JSON.stringify(JSON.parse(bodyText))
|
|
985
|
+
} catch (_) {
|
|
986
|
+
responseBodyString = bodyText
|
|
987
|
+
}
|
|
988
|
+
} else {
|
|
989
|
+
responseBodyString = bodyText
|
|
1042
990
|
}
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
const payload = {
|
|
1046
|
-
level,
|
|
1047
|
-
message,
|
|
1048
|
-
meta: {
|
|
1049
|
-
...metaCopy,
|
|
1050
|
-
service: {
|
|
1051
|
-
name: serviceName,
|
|
1052
|
-
version: '1.0.0'
|
|
1053
|
-
},
|
|
1054
|
-
environment,
|
|
1055
|
-
timestamp: new Date().toISOString(),
|
|
1056
|
-
hostname: os.hostname()
|
|
991
|
+
if (typeof responseBodyString === 'string' && responseBodyString.length > 5000) {
|
|
992
|
+
responseBodyString = responseBodyString.slice(0, 5000)
|
|
1057
993
|
}
|
|
1058
994
|
}
|
|
995
|
+
} catch (_) {
|
|
1059
996
|
try {
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
statusCode: response.status,
|
|
1071
|
-
responseTimeMs: duration,
|
|
1072
|
-
responseHeaders: Object.fromEntries(response.headers.entries()),
|
|
1073
|
-
responseBody: responseBody != null ? String(responseBody) : null
|
|
1074
|
-
}
|
|
1075
|
-
|
|
1076
|
-
markSource(responseMeta, 'http-client')
|
|
1077
|
-
const message = `[RESPONSE] ${method} ${url} ${response.status} ${duration}ms`
|
|
1078
|
-
|
|
1079
|
-
const level = response.status >= 500 ? 'error' : response.status >= 400 ? 'warn' : 'info'
|
|
1080
|
-
|
|
1081
|
-
const metaCopy = { ...responseMeta }
|
|
1082
|
-
if (metaCopy.responseBody != null && typeof metaCopy.responseBody !== 'string') {
|
|
1083
|
-
try {
|
|
1084
|
-
metaCopy.responseBody = JSON.stringify(metaCopy.responseBody)
|
|
1085
|
-
} catch (_) {
|
|
1086
|
-
metaCopy.responseBody = String(metaCopy.responseBody)
|
|
997
|
+
const bodyText = await readBodyWithTimeout(response, 200)
|
|
998
|
+
if (bodyText) {
|
|
999
|
+
if (contentType.includes('application/json')) {
|
|
1000
|
+
try {
|
|
1001
|
+
responseBodyString = JSON.stringify(JSON.parse(bodyText))
|
|
1002
|
+
} catch (_) {
|
|
1003
|
+
responseBodyString = bodyText
|
|
1004
|
+
}
|
|
1005
|
+
} else {
|
|
1006
|
+
responseBodyString = bodyText
|
|
1087
1007
|
}
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
level,
|
|
1091
|
-
message,
|
|
1092
|
-
meta: {
|
|
1093
|
-
...metaCopy,
|
|
1094
|
-
service: {
|
|
1095
|
-
name: serviceName,
|
|
1096
|
-
version: '1.0.0'
|
|
1097
|
-
},
|
|
1098
|
-
environment,
|
|
1099
|
-
timestamp: new Date().toISOString(),
|
|
1100
|
-
hostname: os.hostname()
|
|
1008
|
+
if (typeof responseBodyString === 'string' && responseBodyString.length > 5000) {
|
|
1009
|
+
responseBodyString = responseBodyString.slice(0, 5000)
|
|
1101
1010
|
}
|
|
1102
1011
|
}
|
|
1103
|
-
|
|
1104
|
-
transport.enqueue(payload, {
|
|
1105
|
-
'content-type': 'application/json'
|
|
1106
|
-
})
|
|
1107
|
-
} catch (enqueueErr) {
|
|
1108
|
-
sendOutboundLog(level, message, responseMeta)
|
|
1109
|
-
}
|
|
1110
|
-
} catch (innerErr) {
|
|
1111
|
-
console.error('[azify-logger] Erro ao logar resposta (fallback):', innerErr)
|
|
1012
|
+
} catch (_) {
|
|
1112
1013
|
}
|
|
1113
1014
|
}
|
|
1114
1015
|
}
|
|
1115
|
-
|
|
1116
|
-
logResponse().catch((err) => {
|
|
1117
|
-
console.error('[azify-logger] Erro ao executar logResponse para', method, url, ':', err)
|
|
1118
|
-
const responseMeta = {
|
|
1119
|
-
...requestMeta,
|
|
1120
|
-
statusCode: response.status,
|
|
1121
|
-
responseTimeMs: duration,
|
|
1122
|
-
responseHeaders: Object.fromEntries(response.headers.entries()),
|
|
1123
|
-
responseBody: null
|
|
1124
|
-
}
|
|
1125
|
-
markSource(responseMeta, 'http-client')
|
|
1126
|
-
const message = `[RESPONSE] ${method} ${url} ${response.status} ${duration}ms`
|
|
1127
|
-
const level = response.status >= 500 ? 'error' : response.status >= 400 ? 'warn' : 'info'
|
|
1128
|
-
try {
|
|
1129
|
-
sendOutboundLog(level, message, responseMeta)
|
|
1130
|
-
} catch (fallbackErr) {
|
|
1131
|
-
console.error('[azify-logger] Erro ao enviar log de fallback:', fallbackErr)
|
|
1132
|
-
}
|
|
1133
|
-
})
|
|
1016
|
+
} catch (_) {
|
|
1134
1017
|
}
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
} catch (error) {
|
|
1138
|
-
const duration = Number((performance.now() - start).toFixed(2))
|
|
1139
|
-
const errorMeta = {
|
|
1018
|
+
|
|
1019
|
+
const responseMeta = {
|
|
1140
1020
|
...requestMeta,
|
|
1141
|
-
|
|
1021
|
+
statusCode: response.status,
|
|
1022
|
+
responseTimeMs: duration,
|
|
1023
|
+
responseHeaders
|
|
1142
1024
|
}
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
name: err.name,
|
|
1147
|
-
message: err.message,
|
|
1148
|
-
stack: err.stack
|
|
1025
|
+
|
|
1026
|
+
if (responseBodyString !== null) {
|
|
1027
|
+
responseMeta.responseBody = responseBodyString
|
|
1149
1028
|
}
|
|
1150
|
-
|
|
1151
|
-
|
|
1029
|
+
|
|
1030
|
+
markSource(responseMeta, 'http-client')
|
|
1031
|
+
const message = `[RESPONSE] ${method} ${url} ${response.status} ${duration}ms`
|
|
1032
|
+
const level = response.status >= 500 ? 'error' : response.status >= 400 ? 'warn' : 'info'
|
|
1033
|
+
sendOutboundLog(level, message, responseMeta)
|
|
1152
1034
|
}
|
|
1035
|
+
|
|
1036
|
+
return response
|
|
1153
1037
|
}
|
|
1154
1038
|
}
|
|
1155
1039
|
}
|
package/sampling.js
CHANGED
|
@@ -45,6 +45,9 @@ const sourceSampleRates = {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
const shouldSample = (level, source) => {
|
|
48
|
+
if (source === 'http-client') {
|
|
49
|
+
return true
|
|
50
|
+
}
|
|
48
51
|
const key = typeof level === 'string' ? level.toLowerCase() : 'info'
|
|
49
52
|
let rate = levelSampleRates[key] ?? levelSampleRates.default
|
|
50
53
|
if (source && sourceSampleRates[source] !== undefined) {
|
package/scripts/redis-worker.js
CHANGED
|
@@ -226,15 +226,6 @@ function sanitizePayload(payload) {
|
|
|
226
226
|
if (sanitized.meta.responseBody) {
|
|
227
227
|
sanitized.meta.responseBody = sanitizeBody(sanitized.meta.responseBody)
|
|
228
228
|
}
|
|
229
|
-
if (sanitized.meta.requestBody != null) {
|
|
230
|
-
if (typeof sanitized.meta.requestBody !== 'string') {
|
|
231
|
-
try {
|
|
232
|
-
sanitized.meta.requestBody = JSON.stringify(sanitized.meta.requestBody)
|
|
233
|
-
} catch (_) {
|
|
234
|
-
sanitized.meta.requestBody = String(sanitized.meta.requestBody)
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
229
|
}
|
|
239
230
|
|
|
240
231
|
return sanitized
|
|
@@ -257,18 +248,6 @@ async function deliver(entry) {
|
|
|
257
248
|
sanitizedPayload = entry.payload
|
|
258
249
|
}
|
|
259
250
|
}
|
|
260
|
-
|
|
261
|
-
if (sanitizedPayload && typeof sanitizedPayload === 'object' && sanitizedPayload.meta) {
|
|
262
|
-
if (sanitizedPayload.meta.requestBody != null) {
|
|
263
|
-
if (typeof sanitizedPayload.meta.requestBody !== 'string') {
|
|
264
|
-
try {
|
|
265
|
-
sanitizedPayload.meta.requestBody = JSON.stringify(sanitizedPayload.meta.requestBody)
|
|
266
|
-
} catch (_) {
|
|
267
|
-
sanitizedPayload.meta.requestBody = String(sanitizedPayload.meta.requestBody)
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
251
|
|
|
273
252
|
await axios.post(target, sanitizedPayload, {
|
|
274
253
|
headers: entry.headers || {},
|
|
@@ -346,16 +325,6 @@ async function processEntry(raw) {
|
|
|
346
325
|
return
|
|
347
326
|
}
|
|
348
327
|
|
|
349
|
-
if (entry && entry.payload && entry.payload.meta && entry.payload.meta.requestBody != null) {
|
|
350
|
-
if (typeof entry.payload.meta.requestBody !== 'string') {
|
|
351
|
-
try {
|
|
352
|
-
entry.payload.meta.requestBody = JSON.stringify(entry.payload.meta.requestBody)
|
|
353
|
-
} catch (_) {
|
|
354
|
-
entry.payload.meta.requestBody = String(entry.payload.meta.requestBody)
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
328
|
const attempts = Number(entry.attempts || 0)
|
|
360
329
|
try {
|
|
361
330
|
await deliver(entry)
|
package/server.js
CHANGED
|
@@ -154,7 +154,6 @@ async function ensureIndexTemplate() {
|
|
|
154
154
|
userAgent: { type: 'text' },
|
|
155
155
|
environment: { type: 'keyword' },
|
|
156
156
|
hostname: { type: 'keyword' },
|
|
157
|
-
requestBody: { type: 'text' },
|
|
158
157
|
responseBody: { type: 'text' },
|
|
159
158
|
error: {
|
|
160
159
|
properties: {
|
|
@@ -1701,7 +1700,8 @@ async function handleLog(req, res) {
|
|
|
1701
1700
|
}
|
|
1702
1701
|
} else if (Buffer.isBuffer(bodyValue)) {
|
|
1703
1702
|
try {
|
|
1704
|
-
|
|
1703
|
+
let str = bodyValue.toString('utf8')
|
|
1704
|
+
return str
|
|
1705
1705
|
} catch (_) {
|
|
1706
1706
|
return '[Unable to serialize Buffer]'
|
|
1707
1707
|
}
|