azify-logger 1.0.34 → 1.0.35
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 +8 -14
- package/package.json +2 -2
- package/register.js +251 -342
- 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
|
|
|
@@ -368,6 +358,10 @@ function createExpressLoggingMiddleware(options = {}) {
|
|
|
368
358
|
|
|
369
359
|
return result
|
|
370
360
|
}
|
|
361
|
+
|
|
362
|
+
runWithRequestContext(ctx, () => {
|
|
363
|
+
next()
|
|
364
|
+
})
|
|
371
365
|
}
|
|
372
366
|
}
|
|
373
367
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "azify-logger",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.35",
|
|
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,94 +883,20 @@ 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
|
-
const shouldLogRequest =
|
|
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
|
-
}
|
|
896
|
+
if (HTTP_CLIENT_MODE !== 'off') {
|
|
937
897
|
try {
|
|
938
|
-
transport.enqueue(payload, {
|
|
939
|
-
'content-type': 'application/json'
|
|
940
|
-
})
|
|
941
|
-
requestWasLogged = true
|
|
942
|
-
} catch (enqueueErr) {
|
|
943
898
|
sendOutboundLog('info', `[REQUEST] ${method} ${url}`, requestMeta)
|
|
944
|
-
|
|
899
|
+
} catch (_) {
|
|
945
900
|
}
|
|
946
901
|
}
|
|
947
902
|
|
|
@@ -954,202 +909,156 @@ try {
|
|
|
954
909
|
|
|
955
910
|
const start = performance.now()
|
|
956
911
|
|
|
912
|
+
let response
|
|
957
913
|
try {
|
|
958
|
-
|
|
914
|
+
response = await runWithRequestContext(childCtx, function() {
|
|
959
915
|
return originalFetch(request)
|
|
960
916
|
})
|
|
961
|
-
|
|
917
|
+
} catch (error) {
|
|
962
918
|
const duration = Number((performance.now() - start).toFixed(2))
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
919
|
+
try {
|
|
920
|
+
const errorMeta = {
|
|
921
|
+
...requestMeta,
|
|
922
|
+
responseTimeMs: duration
|
|
923
|
+
}
|
|
924
|
+
markSource(errorMeta, 'http-client')
|
|
925
|
+
const err = error instanceof Error ? error : new Error(String(error))
|
|
926
|
+
errorMeta.error = {
|
|
927
|
+
name: err.name,
|
|
928
|
+
message: err.message,
|
|
929
|
+
stack: err.stack
|
|
930
|
+
}
|
|
931
|
+
sendOutboundLog('error', `[ERROR] ${method} ${url}`, errorMeta)
|
|
932
|
+
} catch (_) {
|
|
933
|
+
}
|
|
934
|
+
throw error
|
|
935
|
+
}
|
|
970
936
|
|
|
971
|
-
|
|
972
|
-
|
|
937
|
+
const duration = Number((performance.now() - start).toFixed(2))
|
|
938
|
+
const shouldLogResponse = HTTP_CLIENT_MODE !== 'off'
|
|
939
|
+
|
|
940
|
+
if (shouldLogResponse) {
|
|
941
|
+
const headersToObject = (headers) => {
|
|
973
942
|
try {
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
943
|
+
if (!headers) return {}
|
|
944
|
+
if (typeof headers.entries === 'function') {
|
|
945
|
+
return Object.fromEntries(headers.entries())
|
|
946
|
+
}
|
|
947
|
+
if (typeof headers.forEach === 'function') {
|
|
948
|
+
const out = {}
|
|
949
|
+
headers.forEach((value, key) => {
|
|
950
|
+
out[key] = value
|
|
951
|
+
})
|
|
952
|
+
return out
|
|
953
|
+
}
|
|
954
|
+
if (typeof headers === 'object') {
|
|
955
|
+
return { ...headers }
|
|
956
|
+
}
|
|
957
|
+
} catch (_) {
|
|
977
958
|
}
|
|
959
|
+
return {}
|
|
978
960
|
}
|
|
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
|
|
961
|
+
|
|
962
|
+
let responseBodyString = null
|
|
963
|
+
let responseHeaders = {}
|
|
964
|
+
|
|
965
|
+
try {
|
|
966
|
+
responseHeaders = headersToObject(response.headers)
|
|
967
|
+
const contentType = response.headers.get('content-type') || ''
|
|
968
|
+
const readBodyWithTimeout = async (resp, timeoutMs) => {
|
|
969
|
+
try {
|
|
970
|
+
const timed = await Promise.race([
|
|
971
|
+
resp.text(),
|
|
972
|
+
new Promise((resolve) => setTimeout(() => resolve(null), timeoutMs))
|
|
973
|
+
])
|
|
974
|
+
return typeof timed === 'string' ? timed : null
|
|
975
|
+
} catch (_) {
|
|
976
|
+
return null
|
|
1020
977
|
}
|
|
1021
|
-
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
if (contentType.includes('application/json') || contentType.includes('text/')) {
|
|
1022
981
|
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)
|
|
982
|
+
const clonedResponse = response.clone()
|
|
983
|
+
const bodyText = await readBodyWithTimeout(clonedResponse, 200)
|
|
984
|
+
if (bodyText) {
|
|
985
|
+
if (contentType.includes('application/json')) {
|
|
986
|
+
try {
|
|
987
|
+
responseBodyString = JSON.stringify(JSON.parse(bodyText))
|
|
988
|
+
} catch (_) {
|
|
989
|
+
responseBodyString = bodyText
|
|
990
|
+
}
|
|
991
|
+
} else {
|
|
992
|
+
responseBodyString = bodyText
|
|
1042
993
|
}
|
|
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()
|
|
994
|
+
if (typeof responseBodyString === 'string' && responseBodyString.length > 5000) {
|
|
995
|
+
responseBodyString = responseBodyString.slice(0, 5000)
|
|
1057
996
|
}
|
|
1058
997
|
}
|
|
998
|
+
} catch (_) {
|
|
1059
999
|
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)
|
|
1000
|
+
const bodyText = await readBodyWithTimeout(response, 200)
|
|
1001
|
+
if (bodyText) {
|
|
1002
|
+
if (contentType.includes('application/json')) {
|
|
1003
|
+
try {
|
|
1004
|
+
responseBodyString = JSON.stringify(JSON.parse(bodyText))
|
|
1005
|
+
} catch (_) {
|
|
1006
|
+
responseBodyString = bodyText
|
|
1007
|
+
}
|
|
1008
|
+
} else {
|
|
1009
|
+
responseBodyString = bodyText
|
|
1087
1010
|
}
|
|
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()
|
|
1011
|
+
if (typeof responseBodyString === 'string' && responseBodyString.length > 5000) {
|
|
1012
|
+
responseBodyString = responseBodyString.slice(0, 5000)
|
|
1101
1013
|
}
|
|
1102
1014
|
}
|
|
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)
|
|
1015
|
+
} catch (_) {
|
|
1112
1016
|
}
|
|
1113
1017
|
}
|
|
1114
1018
|
}
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1019
|
+
} catch (_) {
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
const responseMeta = {
|
|
1023
|
+
...requestMeta,
|
|
1024
|
+
statusCode: response.status,
|
|
1025
|
+
responseTimeMs: duration,
|
|
1026
|
+
responseHeaders
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
if (responseBodyString !== null) {
|
|
1030
|
+
responseMeta.responseBody = responseBodyString
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
try {
|
|
1034
|
+
markSource(responseMeta, 'http-client')
|
|
1035
|
+
const message = `[RESPONSE] ${method} ${url} ${response.status} ${duration}ms`
|
|
1036
|
+
const level = response.status >= 500 ? 'error' : response.status >= 400 ? 'warn' : 'info'
|
|
1037
|
+
sendOutboundLog(level, message, responseMeta)
|
|
1038
|
+
} catch (err) {
|
|
1039
|
+
try {
|
|
1040
|
+
const fallbackMeta = {
|
|
1041
|
+
traceId: requestMeta.traceId || randomUUID(),
|
|
1042
|
+
spanId: requestMeta.spanId || randomBytes(8).toString('hex'),
|
|
1043
|
+
parentSpanId: requestMeta.parentSpanId || null,
|
|
1044
|
+
requestId: requestMeta.requestId || randomUUID(),
|
|
1045
|
+
method,
|
|
1046
|
+
url,
|
|
1120
1047
|
statusCode: response.status,
|
|
1121
1048
|
responseTimeMs: duration,
|
|
1122
|
-
|
|
1123
|
-
|
|
1049
|
+
headers: requestMeta.headers || {},
|
|
1050
|
+
responseHeaders: {}
|
|
1124
1051
|
}
|
|
1125
|
-
markSource(
|
|
1052
|
+
markSource(fallbackMeta, 'http-client')
|
|
1126
1053
|
const message = `[RESPONSE] ${method} ${url} ${response.status} ${duration}ms`
|
|
1127
1054
|
const level = response.status >= 500 ? 'error' : response.status >= 400 ? 'warn' : 'info'
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
console.error('[azify-logger] Erro ao enviar log de fallback:', fallbackErr)
|
|
1132
|
-
}
|
|
1133
|
-
})
|
|
1134
|
-
}
|
|
1135
|
-
|
|
1136
|
-
return response
|
|
1137
|
-
} catch (error) {
|
|
1138
|
-
const duration = Number((performance.now() - start).toFixed(2))
|
|
1139
|
-
const errorMeta = {
|
|
1140
|
-
...requestMeta,
|
|
1141
|
-
responseTimeMs: duration
|
|
1142
|
-
}
|
|
1143
|
-
markSource(errorMeta, 'http-client')
|
|
1144
|
-
const err = error instanceof Error ? error : new Error(String(error))
|
|
1145
|
-
errorMeta.error = {
|
|
1146
|
-
name: err.name,
|
|
1147
|
-
message: err.message,
|
|
1148
|
-
stack: err.stack
|
|
1055
|
+
sendOutboundLog(level, message, fallbackMeta)
|
|
1056
|
+
} catch (_) {
|
|
1057
|
+
}
|
|
1149
1058
|
}
|
|
1150
|
-
void sendOutboundLog('error', `[ERROR] ${method} ${url}`, errorMeta)
|
|
1151
|
-
throw error
|
|
1152
1059
|
}
|
|
1060
|
+
|
|
1061
|
+
return response
|
|
1153
1062
|
}
|
|
1154
1063
|
}
|
|
1155
1064
|
}
|
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
|
}
|