azify-logger 1.0.26 → 1.0.28
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/README.md +8 -1
- package/index.js +38 -16
- package/middleware-express.js +218 -367
- package/middleware-restify.js +135 -306
- package/package.json +31 -29
- package/queue/fileQueue.js +100 -0
- package/queue/redisQueue.js +181 -0
- package/queue/workerManager.js +111 -0
- package/register-otel.js +63 -13
- package/register.js +364 -99
- package/sampling.js +79 -0
- package/scripts/redis-worker.js +467 -0
- package/server.js +168 -70
- package/streams/bunyan.d.ts +26 -0
- package/streams/bunyan.js +39 -8
- package/streams/httpQueue.js +357 -0
- package/streams/pino.d.ts +38 -0
- package/streams/pino.js +44 -7
package/middleware-express.js
CHANGED
|
@@ -1,413 +1,264 @@
|
|
|
1
|
-
const
|
|
2
|
-
const {
|
|
1
|
+
const { runWithRequestContext, startRequestContext, getRequestContext } = require('./store')
|
|
2
|
+
const { createHttpLoggerTransport } = require('./streams/httpQueue')
|
|
3
|
+
const { randomUUID } = require('crypto')
|
|
4
|
+
const os = require('os')
|
|
5
|
+
|
|
6
|
+
const HEADER_WHITELIST = new Set([
|
|
7
|
+
'content-type',
|
|
8
|
+
'content-length',
|
|
9
|
+
'accept',
|
|
10
|
+
'accept-encoding',
|
|
11
|
+
'user-agent',
|
|
12
|
+
'host',
|
|
13
|
+
'x-request-id',
|
|
14
|
+
'x-trace-id',
|
|
15
|
+
'x-span-id',
|
|
16
|
+
'x-parent-span-id'
|
|
17
|
+
])
|
|
18
|
+
|
|
19
|
+
function pickHeaders(source) {
|
|
20
|
+
if (!source || typeof source !== 'object') {
|
|
21
|
+
return {}
|
|
22
|
+
}
|
|
23
|
+
const result = {}
|
|
24
|
+
for (const key in source) {
|
|
25
|
+
const lower = key.toLowerCase()
|
|
26
|
+
if (!HEADER_WHITELIST.has(lower)) continue
|
|
27
|
+
|
|
28
|
+
if (!Object.prototype.hasOwnProperty.call(source, key)) continue
|
|
29
|
+
|
|
30
|
+
const value = source[key]
|
|
31
|
+
if (Array.isArray(value)) {
|
|
32
|
+
result[key] = value.map(String)
|
|
33
|
+
} else if (value != null) {
|
|
34
|
+
result[key] = String(value)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return result
|
|
38
|
+
}
|
|
3
39
|
|
|
4
|
-
/**
|
|
5
|
-
* Creates an Express middleware for automatic request/response logging with azify-logger
|
|
6
|
-
* @param {Object} options - Configuration options
|
|
7
|
-
* @param {string} [options.serviceName] - Name of the service (defaults to APP_NAME env var or 'assemble')
|
|
8
|
-
* @param {string} [options.loggerUrl] - URL of the azify-logger service (defaults to AZIFY_LOGGER_URL env var or 'http://localhost:3001')
|
|
9
|
-
* @param {string} [options.environment] - Environment name (defaults to NODE_ENV env var or 'development')
|
|
10
|
-
* @returns {Function} Express middleware function
|
|
11
|
-
* @example
|
|
12
|
-
* const azifyMiddleware = require('azify-logger/middleware-express');
|
|
13
|
-
* app.use(azifyMiddleware({ serviceName: 'my-app' }));
|
|
14
|
-
*/
|
|
15
40
|
function createExpressLoggingMiddleware(options = {}) {
|
|
16
41
|
const config = {
|
|
17
|
-
serviceName: options.serviceName || process.env.APP_NAME
|
|
18
|
-
loggerUrl: options.loggerUrl || process.env.AZIFY_LOGGER_URL || 'http://localhost:3001',
|
|
19
|
-
environment: options.environment || process.env.NODE_ENV
|
|
42
|
+
serviceName: options.serviceName || process.env.APP_NAME,
|
|
43
|
+
loggerUrl: options.loggerUrl || process.env.AZIFY_LOGGER_URL || 'http://localhost:3001/log',
|
|
44
|
+
environment: options.environment || process.env.NODE_ENV,
|
|
45
|
+
captureResponseBody: options.captureResponseBody !== false && process.env.AZIFY_LOGGER_CAPTURE_RESPONSE_BODY !== 'false',
|
|
46
|
+
captureRequestBody: options.captureRequestBody !== false && process.env.AZIFY_LOGGER_CAPTURE_REQUEST_BODY !== 'false',
|
|
47
|
+
logRequest: options.logRequest !== false && process.env.AZIFY_LOGGER_LOG_REQUEST !== 'false',
|
|
48
|
+
captureHeaders: options.captureHeaders !== undefined ? options.captureHeaders : process.env.AZIFY_LOGGER_CAPTURE_HEADERS === 'true'
|
|
20
49
|
}
|
|
21
50
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
level,
|
|
32
|
-
message,
|
|
33
|
-
meta: {
|
|
34
|
-
...meta,
|
|
51
|
+
const transport = createHttpLoggerTransport(config.loggerUrl, {})
|
|
52
|
+
|
|
53
|
+
const hostname = os.hostname()
|
|
54
|
+
|
|
55
|
+
function sendLog(level, message, meta = {}) {
|
|
56
|
+
if (!transport || typeof transport.enqueue !== 'function') return
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const metaObj = {
|
|
35
60
|
service: {
|
|
36
61
|
name: config.serviceName,
|
|
37
62
|
version: '1.0.0'
|
|
38
63
|
},
|
|
39
64
|
environment: config.environment,
|
|
40
65
|
timestamp: new Date().toISOString(),
|
|
41
|
-
hostname:
|
|
66
|
+
hostname: hostname,
|
|
67
|
+
...meta
|
|
42
68
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
})
|
|
49
|
-
} catch (
|
|
50
|
-
console.error('Erro ao enviar log:', error.message)
|
|
51
|
-
}
|
|
69
|
+
|
|
70
|
+
transport.enqueue({
|
|
71
|
+
level,
|
|
72
|
+
message,
|
|
73
|
+
meta: metaObj
|
|
74
|
+
}, { 'content-type': 'application/json' })
|
|
75
|
+
} catch (err) { }
|
|
52
76
|
}
|
|
53
77
|
|
|
54
|
-
/**
|
|
55
|
-
* Express middleware function that logs requests and responses
|
|
56
|
-
* @param {Object} req - Express request object
|
|
57
|
-
* @param {Object} res - Express response object
|
|
58
|
-
* @param {Function} next - Express next function
|
|
59
|
-
* @returns {void}
|
|
60
|
-
*/
|
|
61
78
|
return function azifyExpressLoggingMiddleware(req, res, next) {
|
|
62
79
|
const startTime = Date.now()
|
|
63
|
-
const
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
let existingTraceId = null
|
|
67
|
-
let existingSpanId = null
|
|
68
|
-
let existingParentSpanId = null
|
|
69
|
-
|
|
70
|
-
if (req.headers['x-trace-id']) {
|
|
71
|
-
existingTraceId = req.headers['x-trace-id']
|
|
72
|
-
existingSpanId = req.headers['x-span-id']
|
|
73
|
-
existingParentSpanId = req.headers['x-parent-span-id']
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const currentCtx = getRequestContext()
|
|
77
|
-
if (currentCtx && currentCtx.traceId) {
|
|
78
|
-
existingTraceId = currentCtx.traceId
|
|
79
|
-
existingSpanId = currentCtx.spanId
|
|
80
|
-
existingParentSpanId = currentCtx.parentSpanId
|
|
81
|
-
}
|
|
80
|
+
const method = req.method
|
|
81
|
+
const url = req.url
|
|
82
|
+
const path = req.path || url
|
|
82
83
|
|
|
83
|
-
let
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
traceId: existingTraceId,
|
|
87
|
-
spanId: existingSpanId || require('uuid').v4().substring(0, 16),
|
|
88
|
-
parentSpanId: existingParentSpanId,
|
|
89
|
-
requestId: requestId
|
|
90
|
-
}
|
|
91
|
-
} else {
|
|
92
|
-
reqCtx = startRequestContext({ requestId })
|
|
93
|
-
}
|
|
84
|
+
let responseChunk = null
|
|
85
|
+
let responseChunkCaptured = false
|
|
86
|
+
let logSent = false
|
|
94
87
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const originalConsole = {
|
|
100
|
-
log: console.log,
|
|
101
|
-
info: console.info,
|
|
102
|
-
warn: console.warn,
|
|
103
|
-
error: console.error
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
console.log = (...args) => {
|
|
107
|
-
const message = args.map(String).join(' ')
|
|
108
|
-
sendLog('info', message, {
|
|
109
|
-
traceId: requestTraceId,
|
|
110
|
-
spanId: requestSpanId,
|
|
111
|
-
parentSpanId: requestParentSpanId,
|
|
112
|
-
requestId: requestId
|
|
113
|
-
})
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
console.info = (...args) => {
|
|
117
|
-
const message = args.map(String).join(' ')
|
|
118
|
-
sendLog('info', message, {
|
|
119
|
-
traceId: requestTraceId,
|
|
120
|
-
spanId: requestSpanId,
|
|
121
|
-
parentSpanId: requestParentSpanId,
|
|
122
|
-
requestId: requestId
|
|
123
|
-
})
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
console.warn = (...args) => {
|
|
127
|
-
const message = args.map(String).join(' ')
|
|
128
|
-
sendLog('warn', message, {
|
|
129
|
-
traceId: requestTraceId,
|
|
130
|
-
spanId: requestSpanId,
|
|
131
|
-
parentSpanId: requestParentSpanId,
|
|
132
|
-
requestId: requestId
|
|
133
|
-
})
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
console.error = (...args) => {
|
|
137
|
-
const message = args.map(String).join(' ')
|
|
138
|
-
sendLog('error', message, {
|
|
139
|
-
traceId: requestTraceId,
|
|
140
|
-
spanId: requestSpanId,
|
|
141
|
-
parentSpanId: requestParentSpanId,
|
|
142
|
-
requestId: requestId
|
|
143
|
-
})
|
|
144
|
-
}
|
|
88
|
+
let requestId, traceId, spanId, parentSpanId, reqCtx, clientIp, query, cachedHeaders
|
|
89
|
+
let idsCreated = false
|
|
90
|
+
let headersCached = false
|
|
145
91
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
baseUrl = baseUrl.replace(/\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, '/{id}')
|
|
151
|
-
baseUrl = baseUrl.replace(/\/[0-9]+/g, '/{id}')
|
|
152
|
-
|
|
153
|
-
function sanitizeHeaders(headers) {
|
|
154
|
-
const sanitized = { ...headers }
|
|
155
|
-
const sensitiveHeaders = ['authorization', 'cookie', 'x-api-key', 'x-auth-token', 'x-access-token']
|
|
92
|
+
function ensureIds() {
|
|
93
|
+
if (idsCreated) return
|
|
94
|
+
idsCreated = true
|
|
156
95
|
|
|
157
|
-
|
|
158
|
-
if (sensitiveHeaders.includes(key.toLowerCase())) {
|
|
159
|
-
sanitized[key] = '***'
|
|
160
|
-
}
|
|
161
|
-
}
|
|
96
|
+
query = req.query
|
|
162
97
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
function sanitizeBody(body) {
|
|
167
|
-
if (!body || typeof body !== 'object') return body
|
|
98
|
+
const currentCtx = getRequestContext()
|
|
99
|
+
const headerTraceId = req.headers['x-trace-id']
|
|
100
|
+
const headerParentSpanId = req.headers['x-parent-span-id']
|
|
168
101
|
|
|
169
|
-
|
|
170
|
-
|
|
102
|
+
if (currentCtx?.traceId) {
|
|
103
|
+
traceId = currentCtx.traceId
|
|
104
|
+
} else if (headerTraceId) {
|
|
105
|
+
traceId = headerTraceId
|
|
106
|
+
} else {
|
|
107
|
+
traceId = randomUUID()
|
|
108
|
+
}
|
|
171
109
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
110
|
+
parentSpanId = currentCtx?.spanId || headerParentSpanId || null
|
|
111
|
+
|
|
112
|
+
if (!req.requestId) {
|
|
113
|
+
const singleUUID = randomUUID()
|
|
114
|
+
requestId = singleUUID
|
|
115
|
+
spanId = singleUUID.replace(/-/g, '').substring(0, 16)
|
|
116
|
+
} else {
|
|
117
|
+
requestId = req.requestId
|
|
118
|
+
if (requestId.length >= 16) {
|
|
119
|
+
spanId = requestId.replace(/-/g, '').substring(0, 16)
|
|
120
|
+
} else if (traceId.length >= 16) {
|
|
121
|
+
spanId = traceId.replace(/-/g, '').substring(0, 16)
|
|
122
|
+
} else {
|
|
123
|
+
spanId = randomUUID().replace(/-/g, '').substring(0, 16)
|
|
175
124
|
}
|
|
176
125
|
}
|
|
177
126
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
req._azifyRequestData = {
|
|
182
|
-
requestId,
|
|
183
|
-
method: req.method,
|
|
184
|
-
url: req.url,
|
|
185
|
-
baseUrl: baseUrl,
|
|
186
|
-
path: req.url,
|
|
187
|
-
headers: sanitizeHeaders(req.headers || {}),
|
|
188
|
-
query: req.query || {},
|
|
189
|
-
userAgent: (req.headers && req.headers['user-agent']) || 'unknown',
|
|
190
|
-
ip: (req.connection && req.connection.remoteAddress) || (req.socket && req.socket.remoteAddress) || req.ip || 'unknown',
|
|
191
|
-
traceId: requestTraceId,
|
|
192
|
-
spanId: requestSpanId,
|
|
193
|
-
parentSpanId: requestParentSpanId
|
|
127
|
+
clientIp = req.ip || req.connection?.remoteAddress || req.socket?.remoteAddress || 'unknown'
|
|
128
|
+
|
|
129
|
+
reqCtx = startRequestContext({ requestId, traceId, spanId, parentSpanId })
|
|
194
130
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
req._azifyRequestData.requestBody = sanitizeBody(req.body)
|
|
201
|
-
}
|
|
202
|
-
sendLog('info', `[REQUEST] ${req.method} ${req.url}`, req._azifyRequestData)
|
|
131
|
+
|
|
132
|
+
function ensureHeaders() {
|
|
133
|
+
if (headersCached) return
|
|
134
|
+
headersCached = true
|
|
135
|
+
cachedHeaders = config.captureHeaders ? pickHeaders(req.headers || {}) : {}
|
|
203
136
|
}
|
|
204
|
-
|
|
205
|
-
res.on('finish', () => {
|
|
206
|
-
if (!responseLogged) {
|
|
207
|
-
logResponse()
|
|
208
|
-
responseLogged = true
|
|
209
|
-
}
|
|
210
|
-
console.log = originalConsole.log
|
|
211
|
-
console.info = originalConsole.info
|
|
212
|
-
console.warn = originalConsole.warn
|
|
213
|
-
console.error = originalConsole.error
|
|
214
|
-
})
|
|
215
|
-
|
|
216
|
-
res.on('close', () => {
|
|
217
|
-
if (!responseLogged) {
|
|
218
|
-
logResponse()
|
|
219
|
-
responseLogged = true
|
|
220
|
-
}
|
|
221
|
-
console.log = originalConsole.log
|
|
222
|
-
console.info = originalConsole.info
|
|
223
|
-
console.warn = originalConsole.warn
|
|
224
|
-
console.error = originalConsole.error
|
|
225
|
-
})
|
|
226
|
-
|
|
227
|
-
let sentBody
|
|
228
|
-
let responseLogged = false
|
|
229
137
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
res.send = function patchedSend() {
|
|
138
|
+
if (config.logRequest) {
|
|
139
|
+
setImmediate(() => {
|
|
233
140
|
try {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
141
|
+
ensureIds()
|
|
142
|
+
ensureHeaders()
|
|
143
|
+
const request = {
|
|
144
|
+
id: requestId,
|
|
145
|
+
method,
|
|
146
|
+
url,
|
|
147
|
+
path,
|
|
148
|
+
query: query || {},
|
|
149
|
+
headers: cachedHeaders,
|
|
150
|
+
ip: clientIp
|
|
238
151
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
res.status = function(code) {
|
|
252
|
-
res._actualStatusCode = code
|
|
253
|
-
return originalStatus.call(this, code)
|
|
152
|
+
if (req.body && config.captureRequestBody) {
|
|
153
|
+
request.body = req.body
|
|
154
|
+
}
|
|
155
|
+
sendLog('info', `[REQUEST] ${method} ${url}`, {
|
|
156
|
+
traceId: reqCtx.traceId,
|
|
157
|
+
spanId: reqCtx.spanId,
|
|
158
|
+
parentSpanId: reqCtx.parentSpanId,
|
|
159
|
+
requestId: requestId,
|
|
160
|
+
request: request
|
|
161
|
+
})
|
|
162
|
+
} catch (err) { }
|
|
163
|
+
})
|
|
254
164
|
}
|
|
255
165
|
|
|
256
|
-
const
|
|
257
|
-
res.writeHead = function(statusCode, statusMessage, headers) {
|
|
258
|
-
res._actualStatusCode = statusCode
|
|
259
|
-
if (typeof statusMessage === 'object') {
|
|
260
|
-
headers = statusMessage
|
|
261
|
-
statusMessage = undefined
|
|
262
|
-
}
|
|
263
|
-
return originalWriteHead.call(this, statusCode, statusMessage, headers)
|
|
264
|
-
}
|
|
166
|
+
const originalEnd = res.end.bind(res)
|
|
265
167
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
sentBody = typeof arguments[0] === 'number' ? arguments[1] : (arguments[1] || arguments[0])
|
|
273
|
-
}
|
|
274
|
-
} catch (_) {}
|
|
275
|
-
|
|
276
|
-
if (typeof code === 'number') {
|
|
277
|
-
res._actualStatusCode = code
|
|
278
|
-
} else {
|
|
279
|
-
const errorObj = arguments.length === 1 ? arguments[0] : (typeof arguments[0] === 'number' ? arguments[1] : arguments[0])
|
|
168
|
+
res.end = (chunk, encoding) => {
|
|
169
|
+
const result = originalEnd(chunk, encoding)
|
|
170
|
+
|
|
171
|
+
setImmediate(() => {
|
|
172
|
+
if (logSent) return
|
|
173
|
+
logSent = true
|
|
280
174
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
} else if (errorName.includes('BadRequest') || errorName.includes('BadDigest')) {
|
|
286
|
-
res._actualStatusCode = 400
|
|
287
|
-
} else if (errorName.includes('NotFound')) {
|
|
288
|
-
res._actualStatusCode = 404
|
|
289
|
-
} else if (errorName.includes('Unauthorized')) {
|
|
290
|
-
res._actualStatusCode = 401
|
|
291
|
-
} else if (errorName.includes('Forbidden')) {
|
|
292
|
-
res._actualStatusCode = 403
|
|
293
|
-
} else {
|
|
294
|
-
res._actualStatusCode = 500
|
|
175
|
+
try {
|
|
176
|
+
if (chunk != null && config.captureResponseBody && !responseChunkCaptured) {
|
|
177
|
+
responseChunk = chunk
|
|
178
|
+
responseChunkCaptured = true
|
|
295
179
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
return originalJsonMethod.apply(this, arguments)
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
res.on('finish', function() {
|
|
310
|
-
if (!responseLogged) {
|
|
311
|
-
logResponse()
|
|
312
|
-
responseLogged = true
|
|
313
|
-
}
|
|
314
|
-
})
|
|
315
|
-
|
|
316
|
-
const originalEnd = res.end
|
|
317
|
-
res.end = function(chunk, encoding) {
|
|
318
|
-
const duration = Date.now() - startTime
|
|
319
|
-
|
|
320
|
-
let responseBody = sentBody
|
|
321
|
-
try {
|
|
322
|
-
if (responseBody == null && chunk) {
|
|
323
|
-
if (Buffer.isBuffer(chunk)) {
|
|
324
|
-
responseBody = chunk.toString('utf8')
|
|
325
|
-
} else if (typeof chunk === 'string') {
|
|
326
|
-
responseBody = chunk
|
|
327
|
-
} else {
|
|
328
|
-
responseBody = JSON.stringify(chunk)
|
|
180
|
+
|
|
181
|
+
ensureIds()
|
|
182
|
+
|
|
183
|
+
const statusCode = res.statusCode || 200
|
|
184
|
+
const duration = Date.now() - startTime
|
|
185
|
+
|
|
186
|
+
const response = { statusCode, durationMs: duration }
|
|
187
|
+
if (responseChunk !== null && responseChunkCaptured && config.captureResponseBody) {
|
|
188
|
+
response.body = responseChunk
|
|
329
189
|
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
if (!responseLogged) {
|
|
334
|
-
logResponse()
|
|
335
|
-
responseLogged = true
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
originalEnd.call(this, chunk, encoding)
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
/**
|
|
342
|
-
* Logs the response data to azify-logger
|
|
343
|
-
* @private
|
|
344
|
-
*/
|
|
345
|
-
function logResponse() {
|
|
346
|
-
const duration = Date.now() - startTime
|
|
347
|
-
|
|
348
|
-
let responseBody = sentBody
|
|
349
|
-
|
|
350
|
-
let serializedResponseBody
|
|
351
|
-
try {
|
|
352
|
-
if (typeof responseBody === 'string') {
|
|
353
|
-
serializedResponseBody = responseBody
|
|
354
|
-
} else if (Array.isArray(responseBody)) {
|
|
355
|
-
serializedResponseBody = JSON.stringify(responseBody)
|
|
356
|
-
} else if (responseBody && typeof responseBody === 'object') {
|
|
357
|
-
if (responseBody.toJSON && typeof responseBody.toJSON === 'function') {
|
|
358
|
-
serializedResponseBody = JSON.stringify(responseBody.toJSON())
|
|
359
|
-
} else if (responseBody.toString && typeof responseBody.toString === 'function' && responseBody.toString() !== '[object Object]') {
|
|
360
|
-
serializedResponseBody = responseBody.toString()
|
|
361
|
-
} else {
|
|
362
|
-
serializedResponseBody = JSON.stringify(responseBody, (key, value) => {
|
|
363
|
-
if (typeof value === 'function') {
|
|
364
|
-
return '[Function]'
|
|
365
|
-
}
|
|
366
|
-
if (value instanceof Error) {
|
|
367
|
-
return { name: value.name, message: value.message, stack: value.stack }
|
|
368
|
-
}
|
|
369
|
-
return value
|
|
370
|
-
}, null, 0)
|
|
190
|
+
|
|
191
|
+
if (config.captureHeaders) {
|
|
192
|
+
ensureHeaders()
|
|
371
193
|
}
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
responseTime: duration,
|
|
394
|
-
responseHeaders: res.getHeaders ? res.getHeaders() : {},
|
|
395
|
-
responseBody: serializedResponseBody
|
|
396
|
-
}
|
|
194
|
+
|
|
195
|
+
const meta = {
|
|
196
|
+
traceId: reqCtx.traceId,
|
|
197
|
+
spanId: reqCtx.spanId,
|
|
198
|
+
parentSpanId: reqCtx.parentSpanId,
|
|
199
|
+
requestId: requestId,
|
|
200
|
+
request: {
|
|
201
|
+
id: requestId,
|
|
202
|
+
method,
|
|
203
|
+
url,
|
|
204
|
+
path,
|
|
205
|
+
query: query || {},
|
|
206
|
+
headers: config.captureHeaders ? (cachedHeaders || {}) : {},
|
|
207
|
+
ip: clientIp
|
|
208
|
+
},
|
|
209
|
+
response: response
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
sendLog('info', `[RESPONSE] ${method} ${url}`, meta)
|
|
213
|
+
} catch (err) { }
|
|
214
|
+
})
|
|
397
215
|
|
|
398
|
-
|
|
399
|
-
sendLog('info', responseMessage, responseData)
|
|
216
|
+
return result
|
|
400
217
|
}
|
|
401
218
|
|
|
402
|
-
req._azifyContext = reqCtx
|
|
403
|
-
|
|
404
219
|
try {
|
|
405
|
-
runWithRequestContext(reqCtx, () => {
|
|
406
|
-
next()
|
|
407
|
-
})
|
|
408
|
-
} catch (error) {
|
|
409
|
-
console.error('Error in azify middleware:', error)
|
|
410
220
|
next()
|
|
221
|
+
} catch (err) {
|
|
222
|
+
if (!logSent) {
|
|
223
|
+
logSent = true
|
|
224
|
+
ensureIds()
|
|
225
|
+
runWithRequestContext(reqCtx, () => {
|
|
226
|
+
process.stderr.write(`[azify-logger][middleware] Erro no next(): ${err?.message || String(err)}\n`)
|
|
227
|
+
setImmediate(() => {
|
|
228
|
+
try {
|
|
229
|
+
const statusCode = res.statusCode || 500
|
|
230
|
+
const duration = Date.now() - startTime
|
|
231
|
+
|
|
232
|
+
ensureHeaders()
|
|
233
|
+
|
|
234
|
+
const response = { statusCode, durationMs: duration }
|
|
235
|
+
const meta = {
|
|
236
|
+
traceId: reqCtx.traceId,
|
|
237
|
+
spanId: reqCtx.spanId,
|
|
238
|
+
parentSpanId: reqCtx.parentSpanId,
|
|
239
|
+
requestId: requestId,
|
|
240
|
+
request: {
|
|
241
|
+
id: requestId,
|
|
242
|
+
method,
|
|
243
|
+
url,
|
|
244
|
+
path,
|
|
245
|
+
query: query || {},
|
|
246
|
+
headers: cachedHeaders,
|
|
247
|
+
ip: clientIp
|
|
248
|
+
},
|
|
249
|
+
response: response,
|
|
250
|
+
error: {
|
|
251
|
+
message: err?.message || String(err),
|
|
252
|
+
name: err?.name || 'Error',
|
|
253
|
+
stack: err?.stack
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
sendLog('error', `[RESPONSE] ${method} ${url}`, meta)
|
|
257
|
+
} catch (logErr) { }
|
|
258
|
+
})
|
|
259
|
+
})
|
|
260
|
+
}
|
|
261
|
+
throw err
|
|
411
262
|
}
|
|
412
263
|
}
|
|
413
264
|
}
|