azify-logger 1.0.55 → 1.0.57

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",
3
+ "version": "1.0.57",
4
4
  "description": "Azify Logger Client - Centralized logging for OpenSearch",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -41,14 +41,14 @@
41
41
  "dependencies": {
42
42
  "@azure/storage-blob": "^12.17.0",
43
43
  "@opentelemetry/api": "^1.9.0",
44
- "@opentelemetry/core": "1.25.0",
45
- "@opentelemetry/instrumentation-express": "0.52.0",
46
- "@opentelemetry/instrumentation-http": "0.52.0",
47
- "@opentelemetry/instrumentation-restify": "0.52.0",
48
- "@opentelemetry/resources": "1.25.0",
49
- "@opentelemetry/sdk-node": "0.52.0",
50
- "@opentelemetry/sdk-trace-base": "1.25.0",
51
- "@opentelemetry/semantic-conventions": "1.25.0",
44
+ "@opentelemetry/core": "^2.7.1",
45
+ "@opentelemetry/instrumentation-express": "^0.66.0",
46
+ "@opentelemetry/instrumentation-http": "^0.218.0",
47
+ "@opentelemetry/instrumentation-restify": "^0.63.0",
48
+ "@opentelemetry/resources": "^2.7.1",
49
+ "@opentelemetry/sdk-node": "^0.218.0",
50
+ "@opentelemetry/sdk-trace-base": "^2.7.1",
51
+ "@opentelemetry/semantic-conventions": "^1.41.1",
52
52
  "adm-zip": "^0.5.16",
53
53
  "archiver": "^4.0.2",
54
54
  "axios": "^1.7.9",
@@ -63,7 +63,7 @@
63
63
  "openid-client": "^5.7.1",
64
64
  "passport": "^0.7.0",
65
65
  "require-in-the-middle": "^7.4.0",
66
- "uuid": "^9.0.1"
66
+ "uuid": "^11.1.1"
67
67
  },
68
68
  "peerDependencies": {
69
69
  "ioredis": "^5.8.0"
@@ -78,7 +78,8 @@
78
78
  },
79
79
  "overrides": {
80
80
  "semver": "^7.5.2",
81
- "glob": "^13.0.0"
81
+ "glob": "^13.0.0",
82
+ "uuid": "^11.1.1"
82
83
  },
83
84
  "engines": {
84
85
  "node": ">=20 <=22"
@@ -111,6 +112,8 @@
111
112
  "queue/",
112
113
  "scripts/redis-worker.js",
113
114
  "streams/",
115
+ "utils/undiciLogBodies.js",
116
+ "utils/sanitizeSensitiveHttpBody.js",
114
117
  "package.json",
115
118
  "README.md"
116
119
  ]
@@ -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 {
@@ -155,8 +160,19 @@ try {
155
160
  }
156
161
 
157
162
  function patchUndiciExports(exports) {
163
+ if (!exports || typeof exports !== 'object') return
164
+ if (typeof exports.fetch === 'function' && typeof globalThis.fetch === 'function' && globalThis.fetch.__azifyLoggerFetchPatched) {
165
+ if (exports.fetch !== globalThis.fetch) {
166
+ exports.fetch = globalThis.fetch
167
+ httpLog('undici exports.fetch -> globalThis.fetch (body logging)')
168
+ }
169
+ }
158
170
  const hasRequest = exports && typeof exports.request === 'function' && !exports.request.__azifyPatched
159
- const hasFetch = exports && typeof exports.fetch === 'function' && !exports.fetch.__azifyPatched
171
+ const hasFetch =
172
+ exports &&
173
+ typeof exports.fetch === 'function' &&
174
+ !exports.fetch.__azifyPatched &&
175
+ !exports.fetch.__azifyLoggerFetchPatched
160
176
  if (!exports || (!hasRequest && !hasFetch)) return
161
177
  const deps = loadStoreAndSampling()
162
178
  const noDeps = !deps
@@ -188,26 +204,50 @@ try {
188
204
  const traceCtx = ctx || otelCtx
189
205
  const rawTraceId = traceCtx && traceCtx.traceId || (require('crypto').randomUUID && require('crypto').randomUUID())
190
206
  const traceId = typeof rawTraceId === 'string' ? toTraceIdHex(rawTraceId) : rawTraceId
207
+ const reqOpts = resolveUndiciRequestOpts(url, options)
208
+ const requestBodyStr = serializeUndiciRequestBody(reqOpts)
191
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
192
211
  markSource(requestMeta, 'http-client')
193
212
  const start = require('perf_hooks').performance.now()
194
213
  const skipLog = isLoggerUrl(urlStr)
195
214
  if (HTTP_CLIENT_MODE !== 'off' && !skipLog) send('info', `[REQUEST] ${method} ${urlStr}`, requestMeta)
196
215
  const wrappedCb = callback ? function (err, data) {
197
216
  const duration = Number((require('perf_hooks').performance.now() - start).toFixed(2))
198
- if (HTTP_CLIENT_MODE !== 'off' && !skipLog) {
199
- if (err) send('error', `[RESPONSE] ${method} ${urlStr} ERROR ${duration}ms`, { ...requestMeta, error: err && err.message, responseTimeMs: duration })
200
- 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)
201
222
  }
202
- 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
+ })
203
237
  } : undefined
204
238
  if (wrappedCb) return origRequest.call(this, url, options, wrappedCb)
205
239
  const p = origRequest.call(this, url, options)
206
240
  if (p && typeof p.then === 'function') {
207
241
  return p.then(
208
- (data) => {
242
+ async (data) => {
209
243
  const duration = Number((require('perf_hooks').performance.now() - start).toFixed(2))
210
- 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
+ }
211
251
  return data
212
252
  },
213
253
  (err) => {
@@ -233,25 +273,48 @@ try {
233
273
  const traceCtx = ctx || otelCtx
234
274
  const rawTraceId = (traceCtx && traceCtx.traceId) || (require('crypto').randomUUID && require('crypto').randomUUID())
235
275
  const traceId = typeof rawTraceId === 'string' ? toTraceIdHex(rawTraceId) : rawTraceId
276
+ const requestBodyStr = serializeUndiciRequestBody(opts || {})
236
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
237
279
  markSource(requestMeta, 'http-client')
238
280
  const start = require('perf_hooks').performance.now()
239
281
  const skipLog = isLoggerUrl(urlStr)
240
282
  if (HTTP_CLIENT_MODE !== 'off' && !skipLog) send('info', `[REQUEST] ${methodStr} ${urlStr}`, requestMeta)
241
283
  const wrappedCb = typeof callback === 'function' ? function (err, data) {
242
284
  const duration = Number((require('perf_hooks').performance.now() - start).toFixed(2))
243
- if (HTTP_CLIENT_MODE !== 'off' && !skipLog) {
244
- if (err) send('error', `[RESPONSE] ${methodStr} ${urlStr} ERROR ${duration}ms`, { ...requestMeta, error: err && err.message, responseTimeMs: duration })
245
- 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)
246
290
  }
247
- 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
+ })
248
305
  } : undefined
249
306
  const ret = wrappedCb ? origDisp.call(this, opts, wrappedCb) : origDisp.call(this, opts)
250
307
  if (ret && typeof ret.then === 'function' && !wrappedCb) {
251
308
  return ret.then(
252
- (data) => {
309
+ async (data) => {
253
310
  const duration = Number((require('perf_hooks').performance.now() - start).toFixed(2))
254
- 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
+ }
255
318
  return data
256
319
  },
257
320
  (err) => {
@@ -312,25 +375,48 @@ try {
312
375
  const traceCtx = ctx || otelCtx
313
376
  const rawTraceId = (traceCtx && traceCtx.traceId) || (require('crypto').randomUUID && require('crypto').randomUUID())
314
377
  const traceId = typeof rawTraceId === 'string' ? (toTraceIdHex ? toTraceIdHex(rawTraceId) : rawTraceId) : rawTraceId
378
+ const requestBodyStr = serializeUndiciRequestBody(opts || {})
315
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
316
381
  if (markSource) markSource(requestMeta, 'http-client')
317
382
  const start = require('perf_hooks').performance.now()
318
383
  const skipLog = isLoggerUrl(urlStr)
319
384
  if (HTTP_CLIENT_MODE !== 'off' && !skipLog) send('info', `[REQUEST] ${methodStr} ${urlStr}`, requestMeta)
320
385
  const wrappedCb = typeof callback === 'function' ? function (err, data) {
321
386
  const duration = Number((require('perf_hooks').performance.now() - start).toFixed(2))
322
- if (HTTP_CLIENT_MODE !== 'off' && !skipLog) {
323
- if (err) send('error', `[RESPONSE] ${methodStr} ${urlStr} ERROR ${duration}ms`, { ...requestMeta, error: err && err.message, responseTimeMs: duration })
324
- 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)
325
392
  }
326
- 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
+ })
327
407
  } : undefined
328
408
  const ret = wrappedCb ? origReq.call(this, opts, wrappedCb) : origReq.call(this, opts)
329
409
  if (ret && typeof ret.then === 'function' && !wrappedCb) {
330
410
  return ret.then(
331
- (data) => {
411
+ async (data) => {
332
412
  const duration = Number((require('perf_hooks').performance.now() - start).toFixed(2))
333
- 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
+ }
334
420
  return data
335
421
  },
336
422
  (err) => {
@@ -390,25 +476,48 @@ try {
390
476
  const traceCtx = ctx || otelCtx
391
477
  const rawTraceId = (traceCtx && traceCtx.traceId) || (require('crypto').randomUUID && require('crypto').randomUUID())
392
478
  const traceId = typeof rawTraceId === 'string' ? (toTraceIdHex ? toTraceIdHex(rawTraceId) : rawTraceId) : rawTraceId
479
+ const requestBodyStr = serializeUndiciRequestBody(opts || {})
393
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
394
482
  if (markSource) markSource(requestMeta, 'http-client')
395
483
  const start = require('perf_hooks').performance.now()
396
484
  const skipLog = isLoggerUrl(urlStr)
397
485
  if (HTTP_CLIENT_MODE !== 'off' && !skipLog) send('info', `[REQUEST] ${methodStr} ${urlStr}`, requestMeta)
398
486
  const wrappedCb = typeof callback === 'function' ? function (err, data) {
399
487
  const duration = Number((require('perf_hooks').performance.now() - start).toFixed(2))
400
- if (HTTP_CLIENT_MODE !== 'off' && !skipLog) {
401
- if (err) send('error', `[RESPONSE] ${methodStr} ${urlStr} ERROR ${duration}ms`, { ...requestMeta, error: err && err.message, responseTimeMs: duration })
402
- 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)
403
493
  }
404
- 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
+ })
405
508
  } : undefined
406
509
  const ret = wrappedCb ? origReq.call(this, opts, wrappedCb) : origReq.call(this, opts)
407
510
  if (ret && typeof ret.then === 'function' && !wrappedCb) {
408
511
  return ret.then(
409
- (data) => {
512
+ async (data) => {
410
513
  const duration = Number((require('perf_hooks').performance.now() - start).toFixed(2))
411
- 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
+ }
412
521
  return data
413
522
  },
414
523
  (err) => {
@@ -736,6 +845,7 @@ try {
736
845
  function patchGlobalFetch() {
737
846
  try {
738
847
  if (typeof globalThis.fetch !== 'function') return
848
+ if (globalThis.fetch.__azifyLoggerFetchPatched) return
739
849
  if (globalThis.fetch.__azifyPatched) return
740
850
  const deps = loadStoreAndSampling()
741
851
  if (!deps || deps.HTTP_CLIENT_MODE === 'off') return
package/register-otel.js CHANGED
@@ -5,12 +5,12 @@ function normalizeServiceNameForTraces(s) {
5
5
 
6
6
  try {
7
7
  const { NodeSDK } = require('@opentelemetry/sdk-node')
8
- const { AlwaysOnSampler } = require('@opentelemetry/core')
8
+ const { AlwaysOnSampler } = require('@opentelemetry/sdk-trace-base')
9
9
  const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http')
10
10
  const { ExpressInstrumentation } = require('@opentelemetry/instrumentation-express')
11
11
  const { RestifyInstrumentation } = require('@opentelemetry/instrumentation-restify')
12
- const { Resource } = require('@opentelemetry/resources')
13
- const { SEMRESATTRS_SERVICE_NAME, SEMRESATTRS_SERVICE_VERSION } = require('@opentelemetry/semantic-conventions')
12
+ const { resourceFromAttributes } = require('@opentelemetry/resources')
13
+ const { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } = require('@opentelemetry/semantic-conventions')
14
14
 
15
15
  const rawName = process.env.APP_NAME || process.env.OTEL_SERVICE_NAME || process.env.SERVICE_NAME || 'app'
16
16
  const serviceName = normalizeServiceNameForTraces(rawName)
@@ -157,9 +157,9 @@ try {
157
157
  }
158
158
 
159
159
  const sdk = new NodeSDK({
160
- resource: new Resource({
161
- [SEMRESATTRS_SERVICE_NAME]: serviceName,
162
- [SEMRESATTRS_SERVICE_VERSION]: serviceVersion
160
+ resource: resourceFromAttributes({
161
+ [ATTR_SERVICE_NAME]: serviceName,
162
+ [ATTR_SERVICE_VERSION]: serviceVersion
163
163
  }),
164
164
  spanProcessor,
165
165
  sampler: new AlwaysOnSampler(),