azify-logger 1.0.14 → 1.0.15
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/index.js +100 -6
- package/middleware-express.d.ts +1 -2
- package/middleware-express.js +61 -13
- package/middleware-restify.js +113 -56
- package/package.json +1 -1
- package/register-restify.js +1 -185
- package/server.js +0 -1
- package/streams/bunyan.js +3 -1
- package/streams/pino.js +12 -5
package/index.js
CHANGED
|
@@ -162,7 +162,6 @@ function createAzifyLoggerFromEnv() {
|
|
|
162
162
|
environment: process.env.NODE_ENV || 'development'
|
|
163
163
|
})
|
|
164
164
|
|
|
165
|
-
// Automatically intercept console methods
|
|
166
165
|
interceptConsole(logger)
|
|
167
166
|
|
|
168
167
|
return logger
|
|
@@ -181,33 +180,128 @@ function interceptConsole(logger) {
|
|
|
181
180
|
|
|
182
181
|
console.log = (...args) => {
|
|
183
182
|
originalConsoleLog(...args);
|
|
184
|
-
|
|
183
|
+
const { getRequestContext } = require('./store');
|
|
184
|
+
const ctx = getRequestContext();
|
|
185
|
+
const message = args.join(' ');
|
|
186
|
+
if (message.includes('failed after')) {
|
|
187
|
+
}
|
|
188
|
+
if (ctx && ctx.traceId) {
|
|
189
|
+
void logger.info(message, { traceId: ctx.traceId, spanId: ctx.spanId, parentSpanId: ctx.parentSpanId, requestId: ctx.requestId });
|
|
190
|
+
} else {
|
|
191
|
+
void logger.info(message);
|
|
192
|
+
}
|
|
185
193
|
};
|
|
186
194
|
|
|
187
195
|
console.error = (...args) => {
|
|
188
196
|
originalConsoleError(...args);
|
|
189
|
-
|
|
197
|
+
const { getRequestContext } = require('./store');
|
|
198
|
+
const ctx = getRequestContext();
|
|
199
|
+
if (ctx && ctx.traceId) {
|
|
200
|
+
void logger.error(args.join(' '), { traceId: ctx.traceId, spanId: ctx.spanId, parentSpanId: ctx.parentSpanId, requestId: ctx.requestId });
|
|
201
|
+
} else {
|
|
202
|
+
void logger.error(args.join(' '));
|
|
203
|
+
}
|
|
190
204
|
};
|
|
191
205
|
|
|
192
206
|
console.warn = (...args) => {
|
|
193
207
|
originalConsoleWarn(...args);
|
|
194
|
-
|
|
208
|
+
const { getRequestContext } = require('./store');
|
|
209
|
+
const ctx = getRequestContext();
|
|
210
|
+
if (ctx && ctx.traceId) {
|
|
211
|
+
void logger.warn(args.join(' '), { traceId: ctx.traceId, spanId: ctx.spanId, parentSpanId: ctx.parentSpanId, requestId: ctx.requestId });
|
|
212
|
+
} else {
|
|
213
|
+
void logger.warn(args.join(' '));
|
|
214
|
+
}
|
|
195
215
|
};
|
|
196
216
|
|
|
197
217
|
console.info = (...args) => {
|
|
198
218
|
originalConsoleInfo(...args);
|
|
199
|
-
|
|
219
|
+
const { getRequestContext } = require('./store');
|
|
220
|
+
const ctx = getRequestContext();
|
|
221
|
+
if (ctx && ctx.traceId) {
|
|
222
|
+
void logger.info(args.join(' '), { traceId: ctx.traceId, spanId: ctx.spanId, parentSpanId: ctx.parentSpanId, requestId: ctx.requestId });
|
|
223
|
+
} else {
|
|
224
|
+
void logger.info(args.join(' '));
|
|
225
|
+
}
|
|
200
226
|
};
|
|
201
227
|
|
|
202
228
|
console.debug = (...args) => {
|
|
203
229
|
originalConsoleDebug(...args);
|
|
204
|
-
|
|
230
|
+
const { getRequestContext } = require('./store');
|
|
231
|
+
const ctx = getRequestContext();
|
|
232
|
+
if (ctx && ctx.traceId) {
|
|
233
|
+
void logger.debug(args.join(' '), { traceId: ctx.traceId, spanId: ctx.spanId, parentSpanId: ctx.parentSpanId, requestId: ctx.requestId });
|
|
234
|
+
} else {
|
|
235
|
+
void logger.debug(args.join(' '));
|
|
236
|
+
}
|
|
205
237
|
};
|
|
206
238
|
}
|
|
207
239
|
|
|
240
|
+
/**
|
|
241
|
+
* Creates a NestJS logger configuration that sends logs to azify-logger
|
|
242
|
+
* @returns {Object} NestJS logger configuration
|
|
243
|
+
* @example
|
|
244
|
+
* const app = await NestFactory.create(AppModule, {
|
|
245
|
+
* logger: createNestLogger()
|
|
246
|
+
* });
|
|
247
|
+
*/
|
|
248
|
+
function createNestLogger() {
|
|
249
|
+
const { getRequestContext } = require('./store')
|
|
250
|
+
const pino = require('pino')
|
|
251
|
+
|
|
252
|
+
return {
|
|
253
|
+
log: (message, context) => {
|
|
254
|
+
const ctx = getRequestContext()
|
|
255
|
+
if (ctx && ctx.traceId) {
|
|
256
|
+
pino().info(message, context || '')
|
|
257
|
+
} else {
|
|
258
|
+
pino().info(message, context || '')
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
error: (message, trace, context) => {
|
|
262
|
+
const ctx = getRequestContext()
|
|
263
|
+
if (ctx && ctx.traceId) {
|
|
264
|
+
pino().error(message, trace || '', context || '')
|
|
265
|
+
} else {
|
|
266
|
+
pino().error(message, trace || '', context || '')
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
warn: (message, context) => {
|
|
270
|
+
const ctx = getRequestContext()
|
|
271
|
+
if (ctx && ctx.traceId) {
|
|
272
|
+
pino().warn(message, context || '')
|
|
273
|
+
} else {
|
|
274
|
+
pino().warn(message, context || '')
|
|
275
|
+
}
|
|
276
|
+
},
|
|
277
|
+
debug: (message, context) => {
|
|
278
|
+
const ctx = getRequestContext()
|
|
279
|
+
if (ctx && ctx.traceId) {
|
|
280
|
+
pino().debug(message, context || '')
|
|
281
|
+
} else {
|
|
282
|
+
pino().debug(message, context || '')
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
verbose: (message, context) => {
|
|
286
|
+
const ctx = getRequestContext()
|
|
287
|
+
if (ctx && ctx.traceId) {
|
|
288
|
+
pino().info(message, context || '')
|
|
289
|
+
} else {
|
|
290
|
+
pino().info(message, context || '')
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (process.env.AZIFY_LOGGER_DISABLE !== '1') {
|
|
297
|
+
require('./init')
|
|
298
|
+
require('./register')
|
|
299
|
+
}
|
|
300
|
+
|
|
208
301
|
module.exports = AzifyLogger
|
|
209
302
|
module.exports.createAzifyLogger = createAzifyLogger
|
|
210
303
|
module.exports.createAzifyLoggerFromEnv = createAzifyLoggerFromEnv
|
|
304
|
+
module.exports.createNestLogger = createNestLogger
|
|
211
305
|
module.exports.interceptConsole = interceptConsole
|
|
212
306
|
module.exports.streams = {
|
|
213
307
|
createBunyanStream: require('./streams/bunyan'),
|
package/middleware-express.d.ts
CHANGED
package/middleware-express.js
CHANGED
|
@@ -63,16 +63,39 @@ function createExpressLoggingMiddleware(options = {}) {
|
|
|
63
63
|
const requestId = req.requestId || require('uuid').v4()
|
|
64
64
|
const middlewareId = require('uuid').v4().substring(0, 8)
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
req.__azifyParentSpanId = reqCtx.parentSpanId
|
|
66
|
+
let existingTraceId = null
|
|
67
|
+
let existingSpanId = null
|
|
68
|
+
let existingParentSpanId = null
|
|
70
69
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
+
}
|
|
82
|
+
|
|
83
|
+
let reqCtx
|
|
84
|
+
if (existingTraceId) {
|
|
85
|
+
reqCtx = {
|
|
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
|
+
}
|
|
94
|
+
|
|
95
|
+
const requestTraceId = reqCtx.traceId
|
|
96
|
+
const requestSpanId = reqCtx.spanId
|
|
97
|
+
const requestParentSpanId = reqCtx.parentSpanId
|
|
74
98
|
|
|
75
|
-
// Store original console methods
|
|
76
99
|
const originalConsole = {
|
|
77
100
|
log: console.log,
|
|
78
101
|
info: console.info,
|
|
@@ -80,7 +103,6 @@ function createExpressLoggingMiddleware(options = {}) {
|
|
|
80
103
|
error: console.error
|
|
81
104
|
}
|
|
82
105
|
|
|
83
|
-
// Override console methods to use the request context
|
|
84
106
|
console.log = (...args) => {
|
|
85
107
|
const message = args.map(String).join(' ')
|
|
86
108
|
sendLog('info', message, {
|
|
@@ -128,13 +150,41 @@ function createExpressLoggingMiddleware(options = {}) {
|
|
|
128
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}')
|
|
129
151
|
baseUrl = baseUrl.replace(/\/[0-9]+/g, '/{id}')
|
|
130
152
|
|
|
153
|
+
function sanitizeHeaders(headers) {
|
|
154
|
+
const sanitized = { ...headers }
|
|
155
|
+
const sensitiveHeaders = ['authorization', 'cookie', 'x-api-key', 'x-auth-token', 'x-access-token']
|
|
156
|
+
|
|
157
|
+
for (const key of Object.keys(sanitized)) {
|
|
158
|
+
if (sensitiveHeaders.includes(key.toLowerCase())) {
|
|
159
|
+
sanitized[key] = '***'
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return sanitized
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function sanitizeBody(body) {
|
|
167
|
+
if (!body || typeof body !== 'object') return body
|
|
168
|
+
|
|
169
|
+
const sanitized = Array.isArray(body) ? [...body] : { ...body }
|
|
170
|
+
const sensitiveFields = ['password', 'token', 'secret', 'apiKey', 'api_key', 'accessToken', 'access_token', 'refreshToken', 'refresh_token', 'clientSecret', 'client_secret']
|
|
171
|
+
|
|
172
|
+
for (const key of Object.keys(sanitized)) {
|
|
173
|
+
if (sensitiveFields.includes(key) || key.toLowerCase().includes('password') || key.toLowerCase().includes('secret')) {
|
|
174
|
+
sanitized[key] = '***'
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return sanitized
|
|
179
|
+
}
|
|
180
|
+
|
|
131
181
|
req._azifyRequestData = {
|
|
132
182
|
requestId,
|
|
133
183
|
method: req.method,
|
|
134
184
|
url: req.url,
|
|
135
185
|
baseUrl: baseUrl,
|
|
136
186
|
path: req.url,
|
|
137
|
-
headers: req.headers || {},
|
|
187
|
+
headers: sanitizeHeaders(req.headers || {}),
|
|
138
188
|
query: req.query || {},
|
|
139
189
|
userAgent: req.headers?.['user-agent'] || 'unknown',
|
|
140
190
|
ip: req.connection?.remoteAddress || req.socket?.remoteAddress || req.ip || 'unknown',
|
|
@@ -147,7 +197,7 @@ function createExpressLoggingMiddleware(options = {}) {
|
|
|
147
197
|
sendLog('info', `[REQUEST] ${req.method} ${req.url}`, req._azifyRequestData)
|
|
148
198
|
} else {
|
|
149
199
|
if (req.body !== undefined) {
|
|
150
|
-
req._azifyRequestData.requestBody = req.body
|
|
200
|
+
req._azifyRequestData.requestBody = sanitizeBody(req.body)
|
|
151
201
|
}
|
|
152
202
|
sendLog('info', `[REQUEST] ${req.method} ${req.url}`, req._azifyRequestData)
|
|
153
203
|
}
|
|
@@ -157,7 +207,6 @@ function createExpressLoggingMiddleware(options = {}) {
|
|
|
157
207
|
logResponse()
|
|
158
208
|
responseLogged = true
|
|
159
209
|
}
|
|
160
|
-
// Restore original console methods
|
|
161
210
|
console.log = originalConsole.log
|
|
162
211
|
console.info = originalConsole.info
|
|
163
212
|
console.warn = originalConsole.warn
|
|
@@ -169,7 +218,6 @@ function createExpressLoggingMiddleware(options = {}) {
|
|
|
169
218
|
logResponse()
|
|
170
219
|
responseLogged = true
|
|
171
220
|
}
|
|
172
|
-
// Restore original console methods
|
|
173
221
|
console.log = originalConsole.log
|
|
174
222
|
console.info = originalConsole.info
|
|
175
223
|
console.warn = originalConsole.warn
|
package/middleware-restify.js
CHANGED
|
@@ -15,11 +15,30 @@ const { als, runWithRequestContext, startRequestContext, getRequestContext } = r
|
|
|
15
15
|
function createRestifyLoggingMiddleware(options = {}) {
|
|
16
16
|
const config = {
|
|
17
17
|
serviceName: options.serviceName || process.env.APP_NAME || 'azipay',
|
|
18
|
-
loggerUrl: options.loggerUrl || process.env.AZIFY_LOGGER_URL || 'http://localhost:3001',
|
|
18
|
+
loggerUrl: (options.loggerUrl || process.env.AZIFY_LOGGER_URL || 'http://localhost:3001/log').replace(/\/log$/, '') + '/log',
|
|
19
19
|
environment: options.environment || process.env.NODE_ENV || 'development'
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
const pendingLogs = new Set()
|
|
23
|
+
|
|
24
|
+
let exitHandlerInstalled = false
|
|
25
|
+
if (!exitHandlerInstalled) {
|
|
26
|
+
exitHandlerInstalled = true
|
|
27
|
+
|
|
28
|
+
process.on('uncaughtException', (err) => {
|
|
29
|
+
console.error('[AZIFY] Uncaught exception:', err.message)
|
|
30
|
+
|
|
31
|
+
if (pendingLogs.size > 0) {
|
|
32
|
+
setTimeout(() => {
|
|
33
|
+
process.exit(1)
|
|
34
|
+
}, 500)
|
|
35
|
+
} else {
|
|
36
|
+
process.exit(1)
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function sendLog(level, message, meta = {}) {
|
|
23
42
|
const logData = {
|
|
24
43
|
level,
|
|
25
44
|
message,
|
|
@@ -35,26 +54,59 @@ function createRestifyLoggingMiddleware(options = {}) {
|
|
|
35
54
|
}
|
|
36
55
|
}
|
|
37
56
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
57
|
+
const logId = Math.random().toString(36).substring(7)
|
|
58
|
+
pendingLogs.add(logId)
|
|
59
|
+
|
|
60
|
+
axios.post(`${config.loggerUrl}`, logData, {
|
|
61
|
+
timeout: 2000
|
|
62
|
+
}).then(() => {
|
|
63
|
+
pendingLogs.delete(logId)
|
|
64
|
+
}).catch(() => {
|
|
65
|
+
pendingLogs.delete(logId)
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function sanitizeHeaders(headers) {
|
|
70
|
+
const sanitized = { ...headers }
|
|
71
|
+
const sensitiveHeaders = ['authorization', 'cookie', 'x-api-key', 'x-auth-token', 'x-access-token']
|
|
72
|
+
|
|
73
|
+
for (const key of Object.keys(sanitized)) {
|
|
74
|
+
if (sensitiveHeaders.includes(key.toLowerCase())) {
|
|
75
|
+
sanitized[key] = '***'
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return sanitized
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function sanitizeBody(body) {
|
|
83
|
+
if (!body || typeof body !== 'object') return body
|
|
84
|
+
|
|
85
|
+
const sanitized = Array.isArray(body) ? [...body] : { ...body }
|
|
86
|
+
const sensitiveFields = ['password', 'token', 'secret', 'apiKey', 'api_key', 'accessToken', 'access_token', 'refreshToken', 'refresh_token', 'clientSecret', 'client_secret']
|
|
87
|
+
|
|
88
|
+
for (const key of Object.keys(sanitized)) {
|
|
89
|
+
if (sensitiveFields.includes(key) || key.toLowerCase().includes('password') || key.toLowerCase().includes('secret')) {
|
|
90
|
+
sanitized[key] = '***'
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return sanitized
|
|
43
95
|
}
|
|
44
96
|
|
|
45
97
|
return function azifyLoggingMiddleware(req, res, next) {
|
|
46
98
|
const startTime = Date.now()
|
|
47
99
|
const requestId = req.requestId || require('uuid').v4()
|
|
48
|
-
const middlewareId = require('uuid').v4().substring(0, 8)
|
|
49
100
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
101
|
+
if (res._azifySetup) {
|
|
102
|
+
return next()
|
|
103
|
+
}
|
|
104
|
+
res._azifySetup = true
|
|
54
105
|
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
const
|
|
106
|
+
const reqCtx = startRequestContext({ requestId })
|
|
107
|
+
const requestTraceId = reqCtx.traceId
|
|
108
|
+
const requestSpanId = reqCtx.spanId
|
|
109
|
+
const requestParentSpanId = reqCtx.parentSpanId
|
|
58
110
|
|
|
59
111
|
let baseUrl = req.url
|
|
60
112
|
if (baseUrl.includes('?')) {
|
|
@@ -69,7 +121,7 @@ function createRestifyLoggingMiddleware(options = {}) {
|
|
|
69
121
|
url: req.url,
|
|
70
122
|
baseUrl: baseUrl,
|
|
71
123
|
path: req.url,
|
|
72
|
-
headers: req.headers,
|
|
124
|
+
headers: sanitizeHeaders(req.headers),
|
|
73
125
|
query: req.query,
|
|
74
126
|
userAgent: req.headers['user-agent'],
|
|
75
127
|
ip: req.connection.remoteAddress || req.socket.remoteAddress,
|
|
@@ -82,27 +134,13 @@ function createRestifyLoggingMiddleware(options = {}) {
|
|
|
82
134
|
sendLog('info', `[REQUEST] ${req.method} ${req.url}`, req._azifyRequestData)
|
|
83
135
|
} else {
|
|
84
136
|
if (req.body !== undefined) {
|
|
85
|
-
req._azifyRequestData.requestBody = req.body
|
|
137
|
+
req._azifyRequestData.requestBody = sanitizeBody(req.body)
|
|
86
138
|
}
|
|
87
139
|
sendLog('info', `[REQUEST] ${req.method} ${req.url}`, req._azifyRequestData)
|
|
88
140
|
}
|
|
89
141
|
|
|
90
|
-
res.
|
|
91
|
-
if (!responseLogged) {
|
|
92
|
-
logResponse()
|
|
93
|
-
responseLogged = true
|
|
94
|
-
}
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
res.on('close', () => {
|
|
98
|
-
if (!responseLogged) {
|
|
99
|
-
logResponse()
|
|
100
|
-
responseLogged = true
|
|
101
|
-
}
|
|
102
|
-
})
|
|
103
|
-
|
|
142
|
+
res._azifyResponseLogged = false
|
|
104
143
|
let sentBody
|
|
105
|
-
let responseLogged = false
|
|
106
144
|
|
|
107
145
|
const originalSend = res.send && res.send.bind(res)
|
|
108
146
|
if (originalSend) {
|
|
@@ -115,9 +153,9 @@ function createRestifyLoggingMiddleware(options = {}) {
|
|
|
115
153
|
}
|
|
116
154
|
} catch (_) {}
|
|
117
155
|
|
|
118
|
-
if (!
|
|
156
|
+
if (!res._azifyResponseLogged) {
|
|
157
|
+
res._azifyResponseLogged = true
|
|
119
158
|
logResponse()
|
|
120
|
-
responseLogged = true
|
|
121
159
|
}
|
|
122
160
|
|
|
123
161
|
return originalSend.apply(this, arguments)
|
|
@@ -176,21 +214,8 @@ function createRestifyLoggingMiddleware(options = {}) {
|
|
|
176
214
|
res._actualStatusCode = res.statusCode || 200
|
|
177
215
|
}
|
|
178
216
|
}
|
|
179
|
-
|
|
180
|
-
if (!responseLogged) {
|
|
181
|
-
logResponse()
|
|
182
|
-
responseLogged = true
|
|
183
|
-
}
|
|
184
|
-
|
|
185
217
|
return originalJsonMethod.apply(this, arguments)
|
|
186
218
|
}
|
|
187
|
-
|
|
188
|
-
res.on('finish', function() {
|
|
189
|
-
if (!responseLogged) {
|
|
190
|
-
logResponse()
|
|
191
|
-
responseLogged = true
|
|
192
|
-
}
|
|
193
|
-
})
|
|
194
219
|
|
|
195
220
|
const originalEnd = res.end
|
|
196
221
|
res.end = function(chunk, encoding) {
|
|
@@ -209,9 +234,9 @@ function createRestifyLoggingMiddleware(options = {}) {
|
|
|
209
234
|
}
|
|
210
235
|
} catch (_) {}
|
|
211
236
|
|
|
212
|
-
if (!
|
|
237
|
+
if (!res._azifyResponseLogged) {
|
|
213
238
|
logResponse()
|
|
214
|
-
|
|
239
|
+
res._azifyResponseLogged = true
|
|
215
240
|
}
|
|
216
241
|
|
|
217
242
|
originalEnd.call(this, chunk, encoding)
|
|
@@ -276,14 +301,46 @@ function createRestifyLoggingMiddleware(options = {}) {
|
|
|
276
301
|
|
|
277
302
|
req._azifyContext = reqCtx
|
|
278
303
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
304
|
+
const originalNext = next
|
|
305
|
+
const wrappedNext = (err) => {
|
|
306
|
+
if (err && !res._azifyResponseLogged) {
|
|
307
|
+
const errorData = {
|
|
308
|
+
...req._azifyRequestData,
|
|
309
|
+
statusCode: res.statusCode || 500,
|
|
310
|
+
responseTime: Date.now() - startTime,
|
|
311
|
+
error: {
|
|
312
|
+
message: err.message || String(err),
|
|
313
|
+
stack: err.stack,
|
|
314
|
+
name: err.name,
|
|
315
|
+
code: err.code
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
sendLog('error', `[ERROR] ${req.method} ${req.url}: ${err.message || String(err)}`, errorData)
|
|
319
|
+
res._azifyResponseLogged = true
|
|
320
|
+
}
|
|
321
|
+
return originalNext(err)
|
|
286
322
|
}
|
|
323
|
+
|
|
324
|
+
res.on('error', (error) => {
|
|
325
|
+
if (!res._azifyResponseLogged) {
|
|
326
|
+
const errorData = {
|
|
327
|
+
...req._azifyRequestData,
|
|
328
|
+
statusCode: res.statusCode || 500,
|
|
329
|
+
responseTime: Date.now() - startTime,
|
|
330
|
+
error: {
|
|
331
|
+
message: error.message,
|
|
332
|
+
stack: error.stack,
|
|
333
|
+
name: error.name
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
sendLog('error', `[ERROR] ${req.method} ${req.url}: ${error.message}`, errorData)
|
|
337
|
+
res._azifyResponseLogged = true
|
|
338
|
+
}
|
|
339
|
+
})
|
|
340
|
+
|
|
341
|
+
runWithRequestContext(reqCtx, () => {
|
|
342
|
+
wrappedNext()
|
|
343
|
+
})
|
|
287
344
|
}
|
|
288
345
|
}
|
|
289
346
|
|
package/package.json
CHANGED
package/register-restify.js
CHANGED
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
console.log('🔧 @azify/logger-client/register-restify carregando...')
|
|
2
2
|
|
|
3
|
-
function generateTraceId() {
|
|
4
|
-
return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15) + Date.now().toString(36)
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
function generateSpanId() {
|
|
8
|
-
return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 7)
|
|
9
|
-
}
|
|
10
|
-
|
|
11
3
|
const Module = require('module')
|
|
12
4
|
const originalRequire = Module.prototype.require
|
|
13
5
|
|
|
@@ -16,185 +8,9 @@ let patched = false
|
|
|
16
8
|
Module.prototype.require = function(id) {
|
|
17
9
|
const module = originalRequire.apply(this, arguments)
|
|
18
10
|
|
|
19
|
-
if (id && typeof id === 'string' && id.includes('restify')) {
|
|
20
|
-
}
|
|
21
|
-
|
|
22
11
|
if (!patched && (id === 'restify' || id.endsWith('/restify') || id.includes('restify/lib'))) {
|
|
23
12
|
patched = true
|
|
24
|
-
console.log(' ✅ Restify detectado!
|
|
25
|
-
|
|
26
|
-
try {
|
|
27
|
-
let trace, context
|
|
28
|
-
try {
|
|
29
|
-
const otel = require('@opentelemetry/api')
|
|
30
|
-
trace = otel.trace
|
|
31
|
-
context = otel.context
|
|
32
|
-
} catch (_) {}
|
|
33
|
-
|
|
34
|
-
const ServerProto = module.Server && module.Server.prototype
|
|
35
|
-
|
|
36
|
-
if (!ServerProto) return module
|
|
37
|
-
|
|
38
|
-
function wrapAsyncMiddleware(handler) {
|
|
39
|
-
const isAsync = handler && handler.constructor && handler.constructor.name === 'AsyncFunction'
|
|
40
|
-
const takesThree = typeof handler === 'function' && handler.length === 3
|
|
41
|
-
|
|
42
|
-
if (isAsync && takesThree) {
|
|
43
|
-
return function wrappedAsyncMiddleware(req, res, next) {
|
|
44
|
-
try {
|
|
45
|
-
const promise = handler(req, res, next)
|
|
46
|
-
if (promise && typeof promise.then === 'function') {
|
|
47
|
-
promise.catch(next)
|
|
48
|
-
}
|
|
49
|
-
} catch (err) {
|
|
50
|
-
next(err)
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return handler
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (ServerProto && !ServerProto.__azifyPatchedUse) {
|
|
58
|
-
const originalUse = ServerProto.use
|
|
59
|
-
ServerProto.use = function patchedUse(...handlers) {
|
|
60
|
-
const patched = handlers.map(h => wrapAsyncMiddleware(h))
|
|
61
|
-
return originalUse.apply(this, patched)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const originalPre = ServerProto.pre
|
|
65
|
-
ServerProto.pre = function patchedPre(...handlers) {
|
|
66
|
-
const patched = handlers.map(h => wrapAsyncMiddleware(h))
|
|
67
|
-
return originalPre.apply(this, patched)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
ServerProto.__azifyPatchedUse = true
|
|
71
|
-
console.log('✅ Restify 11 async middleware patch aplicado')
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (ServerProto && !ServerProto.__azifyReqResLogged) {
|
|
75
|
-
const { createAzifyLoggerFromEnv } = require('./index.js')
|
|
76
|
-
const azifyLogger = createAzifyLoggerFromEnv()
|
|
77
|
-
|
|
78
|
-
ServerProto.use(function azifyAutoRR (req, res, next) {
|
|
79
|
-
if (req.__azifyLogged) return next()
|
|
80
|
-
req.__azifyLogged = true
|
|
81
|
-
const start = Date.now()
|
|
82
|
-
|
|
83
|
-
let traceId, spanId
|
|
84
|
-
|
|
85
|
-
if (trace && context) {
|
|
86
|
-
const span = trace.getSpan(context.active())
|
|
87
|
-
const spanContext = span?.spanContext()
|
|
88
|
-
|
|
89
|
-
if (spanContext) {
|
|
90
|
-
traceId = spanContext.traceId
|
|
91
|
-
spanId = spanContext.spanId
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (!traceId) {
|
|
96
|
-
traceId = generateTraceId()
|
|
97
|
-
spanId = generateSpanId()
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
req.__azifyTrace = { traceId, spanId }
|
|
101
|
-
|
|
102
|
-
const requestId = req.requestId || req.id || (req.getId && req.getId())
|
|
103
|
-
|
|
104
|
-
const requestMeta = {
|
|
105
|
-
requestId,
|
|
106
|
-
method: req.method,
|
|
107
|
-
url: req.url,
|
|
108
|
-
path: req.path(),
|
|
109
|
-
headers: req.headers,
|
|
110
|
-
query: req.query,
|
|
111
|
-
params: req.params,
|
|
112
|
-
userAgent: req.headers?.['user-agent'],
|
|
113
|
-
ip: (req.connection && req.connection.remoteAddress) || (req.socket && req.socket.remoteAddress),
|
|
114
|
-
requestBody: req.body,
|
|
115
|
-
traceId,
|
|
116
|
-
spanId
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
azifyLogger.info(`[REQUEST] ${req.method} ${req.url}`, requestMeta)
|
|
120
|
-
|
|
121
|
-
const originalSend = res.send
|
|
122
|
-
const originalJson = res.json
|
|
123
|
-
|
|
124
|
-
function logResponse(methodName, ...args) {
|
|
125
|
-
const statusCode = res.statusCode || (typeof args[0] === 'number' ? args[0] : 200)
|
|
126
|
-
const body = (args.length === 1) ? args[0] : (typeof args[0] === 'number' ? args[1] : (args[1] || args[0]))
|
|
127
|
-
|
|
128
|
-
const { traceId, spanId } = req.__azifyTrace || {}
|
|
129
|
-
|
|
130
|
-
const responseMeta = {
|
|
131
|
-
requestId,
|
|
132
|
-
method: req.method,
|
|
133
|
-
url: req.url,
|
|
134
|
-
statusCode,
|
|
135
|
-
responseTime: Date.now() - start,
|
|
136
|
-
responseBody: body,
|
|
137
|
-
responseHeaders: res.getHeaders?.() || {},
|
|
138
|
-
traceId,
|
|
139
|
-
spanId,
|
|
140
|
-
responseMethod: methodName
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const message = (typeof body === 'string' && body.length > 0)
|
|
144
|
-
? body
|
|
145
|
-
: `[RESPONSE] ${req.method} ${req.url} ${statusCode} ${Date.now() - start}ms`
|
|
146
|
-
azifyLogger.info(message, responseMeta)
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
res.send = function wrappedSend (...args) {
|
|
150
|
-
logResponse('send', ...args)
|
|
151
|
-
res.__azifyResponseLogged = true
|
|
152
|
-
return originalSend.apply(this, args)
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (originalJson) {
|
|
156
|
-
res.json = function wrappedJson (...args) {
|
|
157
|
-
logResponse('json', ...args)
|
|
158
|
-
res.__azifyResponseLogged = true
|
|
159
|
-
return originalJson.apply(this, args)
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const originalEnd = res.end
|
|
164
|
-
res.end = function wrappedEnd(chunk, encoding) {
|
|
165
|
-
if (!res.__azifyResponseLogged && chunk) {
|
|
166
|
-
const { traceId, spanId } = req.__azifyTrace || {}
|
|
167
|
-
|
|
168
|
-
const responseMeta = {
|
|
169
|
-
requestId,
|
|
170
|
-
method: req.method,
|
|
171
|
-
url: req.url,
|
|
172
|
-
statusCode: res.statusCode,
|
|
173
|
-
responseTime: Date.now() - start,
|
|
174
|
-
responseBody: chunk,
|
|
175
|
-
responseHeaders: res.getHeaders?.() || {},
|
|
176
|
-
traceId,
|
|
177
|
-
spanId,
|
|
178
|
-
responseMethod: 'end'
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const message = (typeof chunk === 'string' && chunk.length > 0)
|
|
182
|
-
? chunk
|
|
183
|
-
: `[RESPONSE] ${req.method} ${req.url} ${res.statusCode} ${Date.now() - start}ms`
|
|
184
|
-
azifyLogger.info(message, responseMeta)
|
|
185
|
-
res.__azifyResponseLogged = true
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
return originalEnd.call(this, chunk, encoding)
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
next()
|
|
192
|
-
})
|
|
193
|
-
ServerProto.__azifyReqResLogged = true
|
|
194
|
-
}
|
|
195
|
-
} catch (error) {
|
|
196
|
-
console.error('❌ Erro ao aplicar patches no Restify:', error.message)
|
|
197
|
-
}
|
|
13
|
+
console.log(' ✅ Restify detectado!')
|
|
198
14
|
}
|
|
199
15
|
|
|
200
16
|
return module
|
package/server.js
CHANGED
|
@@ -167,7 +167,6 @@ app.post('/log', async (req, res) => {
|
|
|
167
167
|
return res.status(400).json({ success: false, message: 'Level and message are required.' })
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
// Filtrar logs verbosos do Prisma e outros logs desnecessários
|
|
171
170
|
const shouldFilterLog = (
|
|
172
171
|
message.includes('prisma:query') ||
|
|
173
172
|
message.includes('prisma:info') ||
|
package/streams/bunyan.js
CHANGED
|
@@ -39,8 +39,10 @@ function createBunyanStream(options = {}) {
|
|
|
39
39
|
|
|
40
40
|
const headers = {}
|
|
41
41
|
|
|
42
|
+
const { time, v, level: _, msg, name, hostname: bunyanHostname, pid, ...cleanRecord } = record
|
|
43
|
+
|
|
42
44
|
const meta = {
|
|
43
|
-
...
|
|
45
|
+
...cleanRecord,
|
|
44
46
|
service: { name: serviceName, version: record.service?.version || '1.0.0' },
|
|
45
47
|
environment,
|
|
46
48
|
timestamp: new Date().toISOString(),
|
package/streams/pino.js
CHANGED
|
@@ -16,11 +16,18 @@ function createPinoStream(options = {}) {
|
|
|
16
16
|
|
|
17
17
|
let traceId, spanId
|
|
18
18
|
try {
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
if (
|
|
22
|
-
traceId =
|
|
23
|
-
spanId =
|
|
19
|
+
const { getRequestContext } = require('../store')
|
|
20
|
+
const ctx = getRequestContext()
|
|
21
|
+
if (ctx && ctx.traceId) {
|
|
22
|
+
traceId = ctx.traceId
|
|
23
|
+
spanId = ctx.spanId
|
|
24
|
+
} else {
|
|
25
|
+
const span = trace.getSpan(context.active())
|
|
26
|
+
const spanContext = span?.spanContext()
|
|
27
|
+
if (spanContext) {
|
|
28
|
+
traceId = spanContext.traceId
|
|
29
|
+
spanId = spanContext.spanId
|
|
30
|
+
}
|
|
24
31
|
}
|
|
25
32
|
} catch (_) {}
|
|
26
33
|
|