azify-logger 1.0.33 → 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.
@@ -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
- request.body = safeSerializeBody(req.body)
285
+ requestBody = safeSerializeBody(req.body)
286
+ request.body = requestBody
289
287
  }
290
288
 
291
289
  const meta = {
@@ -294,6 +292,7 @@ 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
  }
@@ -359,6 +358,10 @@ function createExpressLoggingMiddleware(options = {}) {
359
358
 
360
359
  return result
361
360
  }
361
+
362
+ runWithRequestContext(ctx, () => {
363
+ next()
364
+ })
362
365
  }
363
366
  }
364
367
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "azify-logger",
3
- "version": "1.0.33",
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
- const source = meta && meta.__source
83
- if (!shouldSample(level, source)) {
84
- return
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
- if (metaCopy.meta && metaCopy.meta.requestBody != null) {
99
- if (typeof metaCopy.meta.requestBody !== 'string') {
100
- try {
101
- metaCopy.meta.requestBody = JSON.stringify(metaCopy.meta.requestBody)
102
- } catch (_) {
103
- metaCopy.meta.requestBody = String(metaCopy.meta.requestBody)
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
- const payload = {
109
- level,
110
- message,
111
- meta: {
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
- if (HTTP_CLIENT_MODE === 'all') {
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: response.data
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: response.data
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
- if (typeof Request !== 'undefined' && input instanceof Request) {
775
- return init ? new Request(input, init) : input
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 url = 'unknown'
786
- let method = 'GET'
813
+ let request
814
+ let method = 'UNKNOWN'
815
+ let url = String(input)
787
816
 
788
- if (typeof input === 'string') {
789
- url = input
790
- method = (init?.method || 'GET').toUpperCase()
791
- } else if (input instanceof URL) {
792
- url = input.toString()
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
- url = String(input)
800
- method = (init?.method || 'GET').toUpperCase()
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(input, init)
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,127 +883,20 @@ try {
854
883
  headers: {}
855
884
  }
856
885
 
857
- if (requestBody != null) {
858
- let finalRequestBody = requestBody
859
- if (typeof requestBody !== 'string') {
860
- try {
861
- finalRequestBody = JSON.stringify(requestBody)
862
- } catch (_) {
863
- finalRequestBody = String(requestBody)
864
- }
865
- }
866
- requestMeta.requestBody = finalRequestBody
867
- }
868
-
869
- let request
870
886
  try {
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
- markSource(requestMeta, 'http-client')
903
- const hasTraceHeaders = !!(requestMeta.traceId && requestMeta.spanId)
904
- const shouldLogRequest =
905
- HTTP_CLIENT_MODE === 'all' ||
906
- hasTraceHeaders
887
+ requestMeta.headers = Object.fromEntries(request.headers.entries())
888
+ } catch (_) {
889
+ }
907
890
 
908
- if (shouldLogRequest) {
909
- if (hasTraceHeaders) {
910
- const metaCopy = { ...requestMeta }
911
- if (metaCopy.requestBody != null && typeof metaCopy.requestBody !== 'string') {
912
- try {
913
- metaCopy.requestBody = JSON.stringify(metaCopy.requestBody)
914
- } catch (_) {
915
- metaCopy.requestBody = String(metaCopy.requestBody)
916
- }
917
- }
918
- const payload = {
919
- level: 'info',
920
- message: `[REQUEST] ${method} ${url}`,
921
- meta: {
922
- ...metaCopy,
923
- service: {
924
- name: serviceName,
925
- version: '1.0.0'
926
- },
927
- environment,
928
- timestamp: new Date().toISOString(),
929
- hostname: os.hostname()
930
- }
931
- }
932
- transport.enqueue(payload, {
933
- 'content-type': 'application/json'
934
- })
935
- } else {
936
- sendOutboundLog('info', `[REQUEST] ${method} ${url}`, requestMeta)
937
- }
938
- }
939
-
940
- return originalFetch(input, init)
891
+ if (requestBodyString !== null) {
892
+ requestMeta.requestBody = requestBodyString
941
893
  }
942
894
 
943
895
  markSource(requestMeta, 'http-client')
944
- const hasTraceHeaders = !!(requestMeta.traceId && requestMeta.spanId)
945
- const shouldLogRequest =
946
- HTTP_CLIENT_MODE === 'all' ||
947
- hasTraceHeaders
948
-
949
- if (shouldLogRequest) {
950
- if (hasTraceHeaders) {
951
- const metaCopy = { ...requestMeta }
952
- if (metaCopy.requestBody != null && typeof metaCopy.requestBody !== 'string') {
953
- try {
954
- metaCopy.requestBody = JSON.stringify(metaCopy.requestBody)
955
- } catch (_) {
956
- metaCopy.requestBody = String(metaCopy.requestBody)
957
- }
958
- }
959
- const payload = {
960
- level: 'info',
961
- message: `[REQUEST] ${method} ${url}`,
962
- meta: {
963
- ...metaCopy,
964
- service: {
965
- name: serviceName,
966
- version: '1.0.0'
967
- },
968
- environment,
969
- timestamp: new Date().toISOString(),
970
- hostname: os.hostname()
971
- }
972
- }
973
- transport.enqueue(payload, {
974
- 'content-type': 'application/json'
975
- })
976
- } else {
896
+ if (HTTP_CLIENT_MODE !== 'off') {
897
+ try {
977
898
  sendOutboundLog('info', `[REQUEST] ${method} ${url}`, requestMeta)
899
+ } catch (_) {
978
900
  }
979
901
  }
980
902
 
@@ -987,110 +909,156 @@ try {
987
909
 
988
910
  const start = performance.now()
989
911
 
912
+ let response
990
913
  try {
991
- const response = await runWithRequestContext(childCtx, function() {
914
+ response = await runWithRequestContext(childCtx, function() {
992
915
  return originalFetch(request)
993
916
  })
994
-
917
+ } catch (error) {
995
918
  const duration = Number((performance.now() - start).toFixed(2))
996
- const hasTraceHeaders = !!(requestMeta.traceId && requestMeta.spanId)
997
- const shouldLogResponse =
998
- HTTP_CLIENT_MODE === 'all' ||
999
- (HTTP_CLIENT_MODE === 'errors' && response.status >= 400) ||
1000
- hasTraceHeaders
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
+ }
1001
936
 
1002
- if (shouldLogResponse) {
1003
- const logResponse = async () => {
1004
- let responseBody = null
1005
- const contentType = response.headers.get('content-type') || ''
1006
-
937
+ const duration = Number((performance.now() - start).toFixed(2))
938
+ const shouldLogResponse = HTTP_CLIENT_MODE !== 'off'
939
+
940
+ if (shouldLogResponse) {
941
+ const headersToObject = (headers) => {
942
+ try {
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 (_) {
958
+ }
959
+ return {}
960
+ }
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
977
+ }
978
+ }
979
+
980
+ if (contentType.includes('application/json') || contentType.includes('text/')) {
1007
981
  try {
1008
982
  const clonedResponse = response.clone()
1009
- if (contentType.includes('application/json') || contentType.includes('text/')) {
1010
- const bodyText = await clonedResponse.text()
983
+ const bodyText = await readBodyWithTimeout(clonedResponse, 200)
984
+ if (bodyText) {
1011
985
  if (contentType.includes('application/json')) {
1012
986
  try {
1013
- responseBody = JSON.parse(bodyText)
987
+ responseBodyString = JSON.stringify(JSON.parse(bodyText))
1014
988
  } catch (_) {
1015
- responseBody = bodyText
989
+ responseBodyString = bodyText
1016
990
  }
1017
991
  } else {
1018
- responseBody = bodyText
992
+ responseBodyString = bodyText
993
+ }
994
+ if (typeof responseBodyString === 'string' && responseBodyString.length > 5000) {
995
+ responseBodyString = responseBodyString.slice(0, 5000)
1019
996
  }
1020
997
  }
1021
- } catch (cloneError) {
998
+ } catch (_) {
1022
999
  try {
1023
- if (contentType.includes('application/json') || contentType.includes('text/')) {
1024
- const bodyText = await response.text()
1000
+ const bodyText = await readBodyWithTimeout(response, 200)
1001
+ if (bodyText) {
1025
1002
  if (contentType.includes('application/json')) {
1026
1003
  try {
1027
- responseBody = JSON.parse(bodyText)
1004
+ responseBodyString = JSON.stringify(JSON.parse(bodyText))
1028
1005
  } catch (_) {
1029
- responseBody = bodyText
1006
+ responseBodyString = bodyText
1030
1007
  }
1031
1008
  } else {
1032
- responseBody = bodyText
1009
+ responseBodyString = bodyText
1010
+ }
1011
+ if (typeof responseBodyString === 'string' && responseBodyString.length > 5000) {
1012
+ responseBodyString = responseBodyString.slice(0, 5000)
1033
1013
  }
1034
1014
  }
1035
- } catch (_) {
1036
- responseBody = null
1037
- }
1038
- }
1039
-
1040
- try {
1041
- const responseMeta = {
1042
- ...requestMeta,
1043
- statusCode: response.status,
1044
- responseTimeMs: duration,
1045
- responseHeaders: Object.fromEntries(response.headers.entries()),
1046
- responseBody: responseBody
1047
- }
1048
-
1049
- markSource(responseMeta, 'http-client')
1050
- const message = `[RESPONSE] ${method} ${url} ${response.status} ${duration}ms`
1051
-
1052
- const level = response.status >= 500 ? 'error' : response.status >= 400 ? 'warn' : 'info'
1053
- sendOutboundLog(level, message, responseMeta)
1054
- } catch (err) {
1055
- try {
1056
- const responseMeta = {
1057
- ...requestMeta,
1058
- statusCode: response.status,
1059
- responseTimeMs: duration,
1060
- responseHeaders: Object.fromEntries(response.headers.entries()),
1061
- responseBody: null
1062
- }
1063
-
1064
- markSource(responseMeta, 'http-client')
1065
- const message = `[RESPONSE] ${method} ${url} ${response.status} ${duration}ms`
1066
-
1067
- const level = response.status >= 500 ? 'error' : response.status >= 400 ? 'warn' : 'info'
1068
- sendOutboundLog(level, message, responseMeta)
1069
1015
  } catch (_) {
1070
1016
  }
1071
1017
  }
1072
1018
  }
1073
-
1074
- logResponse().catch(() => {})
1019
+ } catch (_) {
1075
1020
  }
1076
-
1077
- return response
1078
- } catch (error) {
1079
- const duration = Number((performance.now() - start).toFixed(2))
1080
- const errorMeta = {
1021
+
1022
+ const responseMeta = {
1081
1023
  ...requestMeta,
1082
- responseTimeMs: duration
1024
+ statusCode: response.status,
1025
+ responseTimeMs: duration,
1026
+ responseHeaders
1083
1027
  }
1084
- markSource(errorMeta, 'http-client')
1085
- const err = error instanceof Error ? error : new Error(String(error))
1086
- errorMeta.error = {
1087
- name: err.name,
1088
- message: err.message,
1089
- stack: err.stack
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,
1047
+ statusCode: response.status,
1048
+ responseTimeMs: duration,
1049
+ headers: requestMeta.headers || {},
1050
+ responseHeaders: {}
1051
+ }
1052
+ markSource(fallbackMeta, 'http-client')
1053
+ const message = `[RESPONSE] ${method} ${url} ${response.status} ${duration}ms`
1054
+ const level = response.status >= 500 ? 'error' : response.status >= 400 ? 'warn' : 'info'
1055
+ sendOutboundLog(level, message, fallbackMeta)
1056
+ } catch (_) {
1057
+ }
1090
1058
  }
1091
- void sendOutboundLog('error', `[ERROR] ${method} ${url}`, errorMeta)
1092
- throw error
1093
1059
  }
1060
+
1061
+ return response
1094
1062
  }
1095
1063
  }
1096
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) {
@@ -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
- return bodyValue.toString('utf8')
1703
+ let str = bodyValue.toString('utf8')
1704
+ return str
1705
1705
  } catch (_) {
1706
1706
  return '[Unable to serialize Buffer]'
1707
1707
  }