azify-logger 1.0.28 → 1.0.29
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 +18 -4
- package/index.js +2 -1
- package/middleware-express.js +213 -163
- package/middleware-fastify.js +348 -0
- package/middleware-restify.js +74 -59
- package/package.json +16 -17
- package/queue/redisQueue.js +42 -44
- package/sampling.js +1 -1
- package/scripts/redis-worker.js +25 -53
- package/server.js +44 -47
- package/store.js +10 -4
- package/streams/httpQueue.js +65 -80
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
const { startRequestContext } = require('./store')
|
|
2
|
+
const { createHttpLoggerTransport } = require('./streams/httpQueue')
|
|
3
|
+
const os = require('os')
|
|
4
|
+
|
|
5
|
+
function fastUUID() {
|
|
6
|
+
const timestamp = Date.now().toString(36)
|
|
7
|
+
const randomPart = Math.random().toString(36).substring(2, 15)
|
|
8
|
+
const randomPart2 = Math.random().toString(36).substring(2, 15)
|
|
9
|
+
return `${timestamp}-${randomPart}-${randomPart2}`.substring(0, 36)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function sanitizeTraceHex(value) {
|
|
13
|
+
if (!value || typeof value !== 'string') return null
|
|
14
|
+
const hex = value.replace(/[^0-9a-fA-F]/g, '').toLowerCase()
|
|
15
|
+
if (!hex) return null
|
|
16
|
+
return hex.padEnd(32, '0').slice(0, 32)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function safeSerializeBody(payload) {
|
|
20
|
+
if (payload == null) return ''
|
|
21
|
+
if (typeof payload === 'string') return payload
|
|
22
|
+
if (Buffer.isBuffer(payload)) return payload.toString('utf8')
|
|
23
|
+
try {
|
|
24
|
+
return JSON.stringify(payload)
|
|
25
|
+
} catch (err) {
|
|
26
|
+
try {
|
|
27
|
+
return String(payload)
|
|
28
|
+
} catch {
|
|
29
|
+
return ''
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const HEADER_WHITELIST = new Set([
|
|
35
|
+
'content-type',
|
|
36
|
+
'content-length',
|
|
37
|
+
'accept',
|
|
38
|
+
'accept-encoding',
|
|
39
|
+
'user-agent',
|
|
40
|
+
'host',
|
|
41
|
+
'x-request-id',
|
|
42
|
+
'x-trace-id',
|
|
43
|
+
'x-span-id',
|
|
44
|
+
'x-parent-span-id'
|
|
45
|
+
])
|
|
46
|
+
|
|
47
|
+
function pickHeaders(source) {
|
|
48
|
+
if (!source || typeof source !== 'object') {
|
|
49
|
+
return {}
|
|
50
|
+
}
|
|
51
|
+
const result = {}
|
|
52
|
+
for (const key in source) {
|
|
53
|
+
const lower = key.toLowerCase()
|
|
54
|
+
if (!HEADER_WHITELIST.has(lower)) continue
|
|
55
|
+
|
|
56
|
+
if (!Object.prototype.hasOwnProperty.call(source, key)) continue
|
|
57
|
+
|
|
58
|
+
const value = source[key]
|
|
59
|
+
if (Array.isArray(value)) {
|
|
60
|
+
result[key] = value.map(String)
|
|
61
|
+
} else if (value != null) {
|
|
62
|
+
result[key] = String(value)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return result
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function createFastifyLoggingPlugin(options = {}) {
|
|
69
|
+
const config = {
|
|
70
|
+
serviceName: options.serviceName || process.env.APP_NAME,
|
|
71
|
+
loggerUrl: options.loggerUrl || process.env.AZIFY_LOGGER_URL || 'http://localhost:3001/log',
|
|
72
|
+
environment: options.environment || process.env.NODE_ENV,
|
|
73
|
+
captureResponseBody: options.captureResponseBody !== false && process.env.AZIFY_LOGGER_CAPTURE_RESPONSE_BODY !== 'false',
|
|
74
|
+
captureRequestBody: options.captureRequestBody !== false && process.env.AZIFY_LOGGER_CAPTURE_REQUEST_BODY !== 'false',
|
|
75
|
+
logRequest: options.logRequest !== false && process.env.AZIFY_LOGGER_LOG_REQUEST !== 'false',
|
|
76
|
+
captureHeaders: options.captureHeaders !== undefined ? options.captureHeaders : process.env.AZIFY_LOGGER_CAPTURE_HEADERS === 'true'
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const transport = createHttpLoggerTransport(config.loggerUrl, {})
|
|
80
|
+
const hostname = os.hostname()
|
|
81
|
+
const serviceObj = config.serviceName ? { name: config.serviceName, version: '1.0.0' } : null
|
|
82
|
+
|
|
83
|
+
function sendLog(level, message, meta = {}) {
|
|
84
|
+
if (!transport || typeof transport.enqueue !== 'function') return
|
|
85
|
+
|
|
86
|
+
transport.enqueue({
|
|
87
|
+
level,
|
|
88
|
+
message,
|
|
89
|
+
meta
|
|
90
|
+
}, { 'content-type': 'application/json' })
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return async function azifyFastifyPlugin(fastify, opts) {
|
|
94
|
+
fastify.addHook('onRequest', async (request, reply) => {
|
|
95
|
+
const startTime = Date.now()
|
|
96
|
+
const method = request.method
|
|
97
|
+
const url = request.url
|
|
98
|
+
const path = request.routerPath || url
|
|
99
|
+
|
|
100
|
+
let responseChunk = null
|
|
101
|
+
let responseChunkCaptured = false
|
|
102
|
+
let logSent = false
|
|
103
|
+
|
|
104
|
+
let requestId, traceId, spanId, parentSpanId, clientIp, query, cachedHeaders
|
|
105
|
+
let idsCreated = false
|
|
106
|
+
let headersCached = false
|
|
107
|
+
let reqCtx = null
|
|
108
|
+
|
|
109
|
+
const logWithContext = (level, message, meta) => {
|
|
110
|
+
if (!reqCtx) {
|
|
111
|
+
const traceHex = sanitizeTraceHex(request.headers['x-trace-id'])
|
|
112
|
+
reqCtx = startRequestContext({
|
|
113
|
+
requestId: requestId || request.requestId || fastUUID(),
|
|
114
|
+
traceHex,
|
|
115
|
+
parentSpanId: request.headers['x-parent-span-id'] || null
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
meta.traceId = meta.traceId || reqCtx.traceId
|
|
119
|
+
meta.spanId = meta.spanId || reqCtx.spanId
|
|
120
|
+
meta.parentSpanId = meta.parentSpanId || reqCtx.parentSpanId
|
|
121
|
+
sendLog(level, message, meta)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function ensureIds() {
|
|
125
|
+
if (idsCreated) return
|
|
126
|
+
idsCreated = true
|
|
127
|
+
|
|
128
|
+
query = request.query || null
|
|
129
|
+
|
|
130
|
+
if (!reqCtx) {
|
|
131
|
+
const traceHex = sanitizeTraceHex(request.headers['x-trace-id'])
|
|
132
|
+
reqCtx = startRequestContext({
|
|
133
|
+
requestId: request.requestId || fastUUID(),
|
|
134
|
+
traceHex,
|
|
135
|
+
parentSpanId: request.headers['x-parent-span-id'] || null
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
requestId = reqCtx.requestId || request.requestId || fastUUID()
|
|
140
|
+
traceId = reqCtx.traceId
|
|
141
|
+
spanId = reqCtx.spanId
|
|
142
|
+
parentSpanId = reqCtx.parentSpanId || request.headers['x-parent-span-id'] || null
|
|
143
|
+
|
|
144
|
+
clientIp = request.ip || request.socket?.remoteAddress || 'unknown'
|
|
145
|
+
request.requestId = requestId
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function ensureHeaders() {
|
|
149
|
+
if (headersCached) return
|
|
150
|
+
headersCached = true
|
|
151
|
+
if (config.captureHeaders) {
|
|
152
|
+
cachedHeaders = pickHeaders(request.headers || {})
|
|
153
|
+
} else {
|
|
154
|
+
cachedHeaders = {}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function emitResponseLog(meta, chunk) {
|
|
159
|
+
if (!config.captureResponseBody || chunk == null) {
|
|
160
|
+
logWithContext('info', `[RESPONSE] ${method} ${url}`, meta)
|
|
161
|
+
return
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (!meta.response) meta.response = {}
|
|
165
|
+
meta.response.body = safeSerializeBody(chunk)
|
|
166
|
+
logWithContext('info', `[RESPONSE] ${method} ${url}`, meta)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
request.azifyLogger = {
|
|
170
|
+
startTime,
|
|
171
|
+
method,
|
|
172
|
+
url,
|
|
173
|
+
path,
|
|
174
|
+
responseChunk: null,
|
|
175
|
+
responseChunkCaptured: false,
|
|
176
|
+
logSent: false,
|
|
177
|
+
requestId: null,
|
|
178
|
+
traceId: null,
|
|
179
|
+
spanId: null,
|
|
180
|
+
parentSpanId: null,
|
|
181
|
+
clientIp: null,
|
|
182
|
+
query: null,
|
|
183
|
+
cachedHeaders: null,
|
|
184
|
+
idsCreated: false,
|
|
185
|
+
headersCached: false,
|
|
186
|
+
reqCtx: null
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (config.logRequest) {
|
|
190
|
+
process.nextTick(() => {
|
|
191
|
+
ensureIds()
|
|
192
|
+
ensureHeaders()
|
|
193
|
+
|
|
194
|
+
const requestObj = {
|
|
195
|
+
id: requestId,
|
|
196
|
+
method,
|
|
197
|
+
url,
|
|
198
|
+
path,
|
|
199
|
+
ip: clientIp
|
|
200
|
+
}
|
|
201
|
+
if (query) requestObj.query = query
|
|
202
|
+
if (config.captureHeaders && cachedHeaders) requestObj.headers = cachedHeaders
|
|
203
|
+
if (config.captureRequestBody && request.body !== undefined && request.body != null) {
|
|
204
|
+
requestObj.body = safeSerializeBody(request.body)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const meta = {
|
|
208
|
+
traceId: reqCtx.traceId,
|
|
209
|
+
spanId: reqCtx.spanId,
|
|
210
|
+
parentSpanId: reqCtx.parentSpanId || null,
|
|
211
|
+
requestId,
|
|
212
|
+
request: requestObj,
|
|
213
|
+
timestamp: Date.now(),
|
|
214
|
+
hostname
|
|
215
|
+
}
|
|
216
|
+
if (serviceObj) meta.service = serviceObj
|
|
217
|
+
if (config.environment) meta.environment = config.environment
|
|
218
|
+
|
|
219
|
+
logWithContext('info', `[REQUEST] ${method} ${url}`, meta)
|
|
220
|
+
})
|
|
221
|
+
}
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
fastify.addHook('onSend', async (request, reply, payload) => {
|
|
225
|
+
const logger = request.azifyLogger
|
|
226
|
+
if (!logger || logger.logSent) return payload
|
|
227
|
+
|
|
228
|
+
logger.logSent = true
|
|
229
|
+
|
|
230
|
+
if (config.captureResponseBody && payload != null && !logger.responseChunkCaptured) {
|
|
231
|
+
logger.responseChunk = payload
|
|
232
|
+
logger.responseChunkCaptured = true
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const startTime = logger.startTime
|
|
236
|
+
const method = logger.method
|
|
237
|
+
const url = logger.url
|
|
238
|
+
const path = logger.path
|
|
239
|
+
|
|
240
|
+
let requestId, traceId, spanId, parentSpanId, clientIp, query, cachedHeaders
|
|
241
|
+
let idsCreated = false
|
|
242
|
+
let headersCached = false
|
|
243
|
+
let reqCtx = null
|
|
244
|
+
|
|
245
|
+
const logWithContext = (level, message, meta) => {
|
|
246
|
+
if (!reqCtx) {
|
|
247
|
+
const traceHex = sanitizeTraceHex(request.headers['x-trace-id'])
|
|
248
|
+
reqCtx = startRequestContext({
|
|
249
|
+
requestId: requestId || request.requestId || fastUUID(),
|
|
250
|
+
traceHex,
|
|
251
|
+
parentSpanId: request.headers['x-parent-span-id'] || null
|
|
252
|
+
})
|
|
253
|
+
}
|
|
254
|
+
meta.traceId = meta.traceId || reqCtx.traceId
|
|
255
|
+
meta.spanId = meta.spanId || reqCtx.spanId
|
|
256
|
+
meta.parentSpanId = meta.parentSpanId || reqCtx.parentSpanId
|
|
257
|
+
sendLog(level, message, meta)
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function ensureIds() {
|
|
261
|
+
if (idsCreated) return
|
|
262
|
+
idsCreated = true
|
|
263
|
+
|
|
264
|
+
query = request.query || null
|
|
265
|
+
|
|
266
|
+
if (!reqCtx) {
|
|
267
|
+
const traceHex = sanitizeTraceHex(request.headers['x-trace-id'])
|
|
268
|
+
reqCtx = startRequestContext({
|
|
269
|
+
requestId: request.requestId || fastUUID(),
|
|
270
|
+
traceHex,
|
|
271
|
+
parentSpanId: request.headers['x-parent-span-id'] || null
|
|
272
|
+
})
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
requestId = reqCtx.requestId || request.requestId || fastUUID()
|
|
276
|
+
traceId = reqCtx.traceId
|
|
277
|
+
spanId = reqCtx.spanId
|
|
278
|
+
parentSpanId = reqCtx.parentSpanId || request.headers['x-parent-span-id'] || null
|
|
279
|
+
|
|
280
|
+
clientIp = request.ip || request.socket?.remoteAddress || 'unknown'
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function ensureHeaders() {
|
|
284
|
+
if (headersCached) return
|
|
285
|
+
headersCached = true
|
|
286
|
+
if (config.captureHeaders) {
|
|
287
|
+
cachedHeaders = pickHeaders(request.headers || {})
|
|
288
|
+
} else {
|
|
289
|
+
cachedHeaders = {}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function emitResponseLog(meta, chunk) {
|
|
294
|
+
if (!config.captureResponseBody || chunk == null) {
|
|
295
|
+
logWithContext('info', `[RESPONSE] ${method} ${url}`, meta)
|
|
296
|
+
return
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (!meta.response) meta.response = {}
|
|
300
|
+
meta.response.body = safeSerializeBody(chunk)
|
|
301
|
+
logWithContext('info', `[RESPONSE] ${method} ${url}`, meta)
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
process.nextTick(() => {
|
|
305
|
+
ensureIds()
|
|
306
|
+
|
|
307
|
+
const statusCode = reply.statusCode || 200
|
|
308
|
+
const duration = Date.now() - startTime
|
|
309
|
+
const response = { statusCode, durationMs: duration }
|
|
310
|
+
|
|
311
|
+
if (config.captureHeaders) {
|
|
312
|
+
ensureHeaders()
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const requestObj = {
|
|
316
|
+
id: requestId,
|
|
317
|
+
method,
|
|
318
|
+
url,
|
|
319
|
+
path,
|
|
320
|
+
ip: clientIp
|
|
321
|
+
}
|
|
322
|
+
if (query) requestObj.query = query
|
|
323
|
+
if (config.captureHeaders && cachedHeaders) requestObj.headers = cachedHeaders
|
|
324
|
+
|
|
325
|
+
const meta = {
|
|
326
|
+
traceId: reqCtx.traceId,
|
|
327
|
+
spanId: reqCtx.spanId,
|
|
328
|
+
parentSpanId: reqCtx.parentSpanId || null,
|
|
329
|
+
requestId,
|
|
330
|
+
request: requestObj,
|
|
331
|
+
response,
|
|
332
|
+
timestamp: Date.now(),
|
|
333
|
+
hostname
|
|
334
|
+
}
|
|
335
|
+
if (serviceObj) meta.service = serviceObj
|
|
336
|
+
if (config.environment) meta.environment = config.environment
|
|
337
|
+
|
|
338
|
+
const chunkToProcess = (logger.responseChunk !== null && logger.responseChunkCaptured) ? logger.responseChunk : null
|
|
339
|
+
emitResponseLog(meta, chunkToProcess)
|
|
340
|
+
})
|
|
341
|
+
|
|
342
|
+
return payload
|
|
343
|
+
})
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
module.exports = createFastifyLoggingPlugin
|
|
348
|
+
|
package/middleware-restify.js
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const { startRequestContext } = require('./store')
|
|
2
2
|
const { createHttpLoggerTransport } = require('./streams/httpQueue')
|
|
3
|
-
const { randomUUID } = require('crypto')
|
|
4
3
|
const os = require('os')
|
|
5
4
|
|
|
5
|
+
function fastUUID() {
|
|
6
|
+
const timestamp = Date.now().toString(36)
|
|
7
|
+
const randomPart = Math.random().toString(36).substring(2, 15)
|
|
8
|
+
const randomPart2 = Math.random().toString(36).substring(2, 15)
|
|
9
|
+
return `${timestamp}-${randomPart}-${randomPart2}`.substring(0, 36)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function sanitizeTraceHex(value) {
|
|
13
|
+
if (!value || typeof value !== 'string') return null
|
|
14
|
+
const hex = value.replace(/[^0-9a-fA-F]/g, '').toLowerCase()
|
|
15
|
+
if (!hex) return null
|
|
16
|
+
return hex.padEnd(32, '0').slice(0, 32)
|
|
17
|
+
}
|
|
18
|
+
|
|
6
19
|
const HEADER_WHITELIST = new Set([
|
|
7
20
|
'content-type',
|
|
8
21
|
'content-length',
|
|
@@ -21,10 +34,17 @@ function pickHeaders (source) {
|
|
|
21
34
|
return {}
|
|
22
35
|
}
|
|
23
36
|
const result = {}
|
|
24
|
-
for (const
|
|
37
|
+
for (const key in source) {
|
|
25
38
|
const lower = key.toLowerCase()
|
|
26
|
-
if (HEADER_WHITELIST.has(lower))
|
|
27
|
-
|
|
39
|
+
if (!HEADER_WHITELIST.has(lower)) continue
|
|
40
|
+
|
|
41
|
+
if (!Object.prototype.hasOwnProperty.call(source, key)) continue
|
|
42
|
+
|
|
43
|
+
const value = source[key]
|
|
44
|
+
if (Array.isArray(value)) {
|
|
45
|
+
result[key] = value.map(String)
|
|
46
|
+
} else if (value != null) {
|
|
47
|
+
result[key] = String(value)
|
|
28
48
|
}
|
|
29
49
|
}
|
|
30
50
|
return result
|
|
@@ -37,42 +57,40 @@ function createRestifyLoggingMiddleware (options = {}) {
|
|
|
37
57
|
environment: options.environment || process.env.NODE_ENV
|
|
38
58
|
}
|
|
39
59
|
|
|
40
|
-
const transport = createHttpLoggerTransport(config.loggerUrl)
|
|
60
|
+
const transport = createHttpLoggerTransport(config.loggerUrl, {})
|
|
61
|
+
const hostname = os.hostname()
|
|
62
|
+
const serviceObj = config.serviceName ? { name: config.serviceName, version: '1.0.0' } : null
|
|
41
63
|
|
|
42
64
|
function sendLog (level, message, meta = {}) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
hostname: os.hostname()
|
|
56
|
-
}
|
|
57
|
-
}, { 'content-type': 'application/json' })
|
|
58
|
-
} catch (err) { }
|
|
65
|
+
if (!transport || typeof transport.enqueue !== 'function') return
|
|
66
|
+
|
|
67
|
+
if (serviceObj) meta.service = serviceObj
|
|
68
|
+
if (config.environment) meta.environment = config.environment
|
|
69
|
+
meta.timestamp = Date.now()
|
|
70
|
+
meta.hostname = hostname
|
|
71
|
+
|
|
72
|
+
transport.enqueue({
|
|
73
|
+
level,
|
|
74
|
+
message,
|
|
75
|
+
meta
|
|
76
|
+
}, { 'content-type': 'application/json' })
|
|
59
77
|
}
|
|
60
78
|
|
|
61
79
|
return function azifyLoggingMiddleware (req, res, next) {
|
|
62
80
|
const startTime = Date.now()
|
|
63
|
-
const requestId = req.requestId ||
|
|
81
|
+
const requestId = req.requestId || fastUUID()
|
|
64
82
|
|
|
65
83
|
if (res._azifySetup) {
|
|
66
84
|
return next()
|
|
67
85
|
}
|
|
68
86
|
res._azifySetup = true
|
|
69
87
|
|
|
70
|
-
const
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
88
|
+
const traceHex = sanitizeTraceHex(req.headers['x-trace-id'])
|
|
89
|
+
const reqCtx = startRequestContext({
|
|
90
|
+
requestId,
|
|
91
|
+
traceHex,
|
|
92
|
+
parentSpanId: req.headers['x-parent-span-id'] || null
|
|
93
|
+
})
|
|
76
94
|
|
|
77
95
|
let normalizedPath = req.url
|
|
78
96
|
if (normalizedPath.includes('?')) {
|
|
@@ -115,29 +133,37 @@ function createRestifyLoggingMiddleware (options = {}) {
|
|
|
115
133
|
}
|
|
116
134
|
}
|
|
117
135
|
|
|
136
|
+
let logSent = false
|
|
137
|
+
|
|
118
138
|
function emitLog (level, message, extraMeta = {}) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
139
|
+
if (logSent) return
|
|
140
|
+
logSent = true
|
|
141
|
+
|
|
142
|
+
process.nextTick(() => {
|
|
143
|
+
const duration = Date.now() - startTime
|
|
144
|
+
const statusCode = responseStatus || res.statusCode || 200
|
|
145
|
+
const responseHeaders = typeof res.getHeaders === 'function' ? res.getHeaders() : {}
|
|
146
|
+
|
|
147
|
+
const meta = {
|
|
148
|
+
traceId: reqCtx.traceId,
|
|
149
|
+
spanId: reqCtx.spanId,
|
|
150
|
+
parentSpanId: reqCtx.parentSpanId || null,
|
|
151
|
+
requestId,
|
|
152
|
+
request: requestSnapshot,
|
|
153
|
+
response: {
|
|
154
|
+
statusCode,
|
|
155
|
+
headers: pickHeaders(responseHeaders),
|
|
156
|
+
durationMs: duration
|
|
157
|
+
},
|
|
158
|
+
...extraMeta
|
|
159
|
+
}
|
|
136
160
|
|
|
137
|
-
|
|
161
|
+
sendLog(level, message, meta)
|
|
162
|
+
})
|
|
138
163
|
}
|
|
139
164
|
|
|
140
165
|
function finalize (level = 'info', errorMeta) {
|
|
166
|
+
if (logSent) return
|
|
141
167
|
const message = `${req.method} ${req.url}`
|
|
142
168
|
const meta = errorMeta ? { error: errorMeta } : {}
|
|
143
169
|
emitLog(level, message, meta)
|
|
@@ -159,18 +185,7 @@ function createRestifyLoggingMiddleware (options = {}) {
|
|
|
159
185
|
})
|
|
160
186
|
})
|
|
161
187
|
|
|
162
|
-
|
|
163
|
-
try {
|
|
164
|
-
next()
|
|
165
|
-
} catch (err) {
|
|
166
|
-
finalize('error', {
|
|
167
|
-
message: err && err.message ? err.message : String(err),
|
|
168
|
-
name: err && err.name ? err.name : 'Error',
|
|
169
|
-
stack: err && err.stack ? err.stack : undefined
|
|
170
|
-
})
|
|
171
|
-
throw err
|
|
172
|
-
}
|
|
173
|
-
})
|
|
188
|
+
next()
|
|
174
189
|
}
|
|
175
190
|
}
|
|
176
191
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "azify-logger",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.29",
|
|
4
4
|
"description": "Azify Logger Client - Centralized logging for OpenSearch",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"test": "echo \"No tests specified\" && exit 0",
|
|
10
10
|
"start": "node server.js",
|
|
11
11
|
"dev": "node server.js",
|
|
12
|
-
"dev:full": "docker
|
|
12
|
+
"dev:full": "docker compose up -d && sleep 10 && npm start",
|
|
13
13
|
"pm2:start": "pm2 start ecosystem.config.js",
|
|
14
14
|
"pm2:stop": "pm2 stop ecosystem.config.js",
|
|
15
15
|
"pm2:restart": "pm2 restart ecosystem.config.js",
|
|
@@ -28,27 +28,26 @@
|
|
|
28
28
|
"author": "Azify",
|
|
29
29
|
"license": "MIT",
|
|
30
30
|
"dependencies": {
|
|
31
|
+
"@opentelemetry/api": "1.0.4",
|
|
32
|
+
"@opentelemetry/auto-instrumentations-node": "0.27.0",
|
|
33
|
+
"@opentelemetry/core": "1.0.1",
|
|
34
|
+
"@opentelemetry/exporter-trace-otlp-http": "0.27.0",
|
|
35
|
+
"@opentelemetry/instrumentation-express": "0.27.0",
|
|
36
|
+
"@opentelemetry/instrumentation-http": "0.27.0",
|
|
37
|
+
"@opentelemetry/instrumentation-restify": "0.27.0",
|
|
38
|
+
"@opentelemetry/resources": "1.0.1",
|
|
39
|
+
"@opentelemetry/sdk-node": "0.27.0",
|
|
40
|
+
"@opentelemetry/semantic-conventions": "1.0.1",
|
|
31
41
|
"axios": "^1.6.0",
|
|
32
|
-
"ioredis": "^5.4.1",
|
|
33
42
|
"cors": "^2.8.5",
|
|
34
43
|
"express": "^4.18.2",
|
|
35
44
|
"express-session": "^1.17.3",
|
|
45
|
+
"ioredis": "^5.8.2",
|
|
46
|
+
"js-yaml": "^4.1.0",
|
|
36
47
|
"passport": "^0.6.0",
|
|
37
48
|
"passport-azure-ad": "^4.3.5",
|
|
38
|
-
"js-yaml": "^4.1.0",
|
|
39
49
|
"require-in-the-middle": "^7.4.0",
|
|
40
|
-
"uuid": "^9.0.1"
|
|
41
|
-
"@opentelemetry/instrumentation-http": "0.27.0",
|
|
42
|
-
"@opentelemetry/instrumentation-express": "0.27.0",
|
|
43
|
-
"@opentelemetry/instrumentation-restify": "0.27.0",
|
|
44
|
-
|
|
45
|
-
"@opentelemetry/api": "1.0.4",
|
|
46
|
-
"@opentelemetry/core": "1.0.1",
|
|
47
|
-
"@opentelemetry/resources": "1.0.1",
|
|
48
|
-
"@opentelemetry/semantic-conventions": "1.0.1",
|
|
49
|
-
"@opentelemetry/sdk-node": "0.27.0",
|
|
50
|
-
"@opentelemetry/exporter-trace-otlp-http": "0.27.0",
|
|
51
|
-
"@opentelemetry/auto-instrumentations-node": "0.27.0"
|
|
50
|
+
"uuid": "^9.0.1"
|
|
52
51
|
},
|
|
53
52
|
"overrides": {
|
|
54
53
|
"@opentelemetry/api": "1.0.4",
|
|
@@ -59,7 +58,6 @@
|
|
|
59
58
|
"@opentelemetry/exporter-trace-otlp-http": "0.27.0",
|
|
60
59
|
"@opentelemetry/auto-instrumentations-node": "0.27.0"
|
|
61
60
|
},
|
|
62
|
-
"optionalDependencies": {},
|
|
63
61
|
"engines": {
|
|
64
62
|
"node": ">=12 <=22"
|
|
65
63
|
},
|
|
@@ -77,6 +75,7 @@
|
|
|
77
75
|
"middleware-restify.js",
|
|
78
76
|
"middleware-express.js",
|
|
79
77
|
"middleware-express.d.ts",
|
|
78
|
+
"middleware-fastify.js",
|
|
80
79
|
"server.js",
|
|
81
80
|
"sampling.js",
|
|
82
81
|
"queue/",
|