azify-logger 1.0.13 → 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 CHANGED
@@ -73,7 +73,7 @@ class AzifyLogger {
73
73
  })
74
74
  } catch (_) {}
75
75
 
76
- await axios.post(`${this.options.loggerUrl}/log`, logData, {
76
+ await axios.post(`${this.options.loggerUrl}`, logData, {
77
77
  timeout: 5000,
78
78
  headers
79
79
  })
@@ -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
- void logger.info(args.join(' '));
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
- void logger.error(args.join(' '));
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
- void logger.warn(args.join(' '));
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
- void logger.info(args.join(' '));
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
- void logger.debug(args.join(' '));
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'),
@@ -17,4 +17,4 @@ declare function createExpressLoggingMiddleware(options?: {
17
17
  environment?: string;
18
18
  }): ExpressMiddleware;
19
19
 
20
- export default createExpressLoggingMiddleware;
20
+ export = createExpressLoggingMiddleware;
@@ -63,14 +63,85 @@ 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
- const reqCtx = startRequestContext({ requestId })
67
- req.__azifyTraceId = reqCtx.traceId
68
- req.__azifySpanId = reqCtx.spanId
69
- req.__azifyParentSpanId = reqCtx.parentSpanId
66
+ let existingTraceId = null
67
+ let existingSpanId = null
68
+ let existingParentSpanId = null
70
69
 
71
- const requestTraceId = req.__azifyTraceId
72
- const requestSpanId = req.__azifySpanId
73
- const requestParentSpanId = req.__azifyParentSpanId
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
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
+ }
74
145
 
75
146
  let baseUrl = req.url
76
147
  if (baseUrl.includes('?')) {
@@ -79,13 +150,41 @@ function createExpressLoggingMiddleware(options = {}) {
79
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}')
80
151
  baseUrl = baseUrl.replace(/\/[0-9]+/g, '/{id}')
81
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
+
82
181
  req._azifyRequestData = {
83
182
  requestId,
84
183
  method: req.method,
85
184
  url: req.url,
86
185
  baseUrl: baseUrl,
87
186
  path: req.url,
88
- headers: req.headers || {},
187
+ headers: sanitizeHeaders(req.headers || {}),
89
188
  query: req.query || {},
90
189
  userAgent: req.headers?.['user-agent'] || 'unknown',
91
190
  ip: req.connection?.remoteAddress || req.socket?.remoteAddress || req.ip || 'unknown',
@@ -98,7 +197,7 @@ function createExpressLoggingMiddleware(options = {}) {
98
197
  sendLog('info', `[REQUEST] ${req.method} ${req.url}`, req._azifyRequestData)
99
198
  } else {
100
199
  if (req.body !== undefined) {
101
- req._azifyRequestData.requestBody = req.body
200
+ req._azifyRequestData.requestBody = sanitizeBody(req.body)
102
201
  }
103
202
  sendLog('info', `[REQUEST] ${req.method} ${req.url}`, req._azifyRequestData)
104
203
  }
@@ -108,6 +207,10 @@ function createExpressLoggingMiddleware(options = {}) {
108
207
  logResponse()
109
208
  responseLogged = true
110
209
  }
210
+ console.log = originalConsole.log
211
+ console.info = originalConsole.info
212
+ console.warn = originalConsole.warn
213
+ console.error = originalConsole.error
111
214
  })
112
215
 
113
216
  res.on('close', () => {
@@ -115,6 +218,10 @@ function createExpressLoggingMiddleware(options = {}) {
115
218
  logResponse()
116
219
  responseLogged = true
117
220
  }
221
+ console.log = originalConsole.log
222
+ console.info = originalConsole.info
223
+ console.warn = originalConsole.warn
224
+ console.error = originalConsole.error
118
225
  })
119
226
 
120
227
  let sentBody
@@ -1,14 +1,44 @@
1
+ /**
2
+ * Creates a Restify middleware for automatic request/response logging with azify-logger
3
+ * @param {Object} options - Configuration options
4
+ * @param {string} [options.serviceName] - Name of the service (defaults to APP_NAME env var or 'azipay')
5
+ * @param {string} [options.loggerUrl] - URL of the azify-logger service (defaults to AZIFY_LOGGER_URL env var or 'http://localhost:3001')
6
+ * @param {string} [options.environment] - Environment name (defaults to NODE_ENV env var or 'development')
7
+ * @returns {Function} Restify middleware function
8
+ * @example
9
+ * const azifyMiddleware = require('azify-logger/middleware-restify');
10
+ * server.use(azifyMiddleware({ serviceName: 'my-app' }));
11
+ */
1
12
  const axios = require('axios')
2
13
  const { als, runWithRequestContext, startRequestContext, getRequestContext } = require('./store')
3
14
 
4
15
  function createRestifyLoggingMiddleware(options = {}) {
5
16
  const config = {
6
17
  serviceName: options.serviceName || process.env.APP_NAME || 'azipay',
7
- 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',
8
19
  environment: options.environment || process.env.NODE_ENV || 'development'
9
20
  }
10
21
 
11
- async function sendLog(level, message, meta = {}) {
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 = {}) {
12
42
  const logData = {
13
43
  level,
14
44
  message,
@@ -24,26 +54,59 @@ function createRestifyLoggingMiddleware(options = {}) {
24
54
  }
25
55
  }
26
56
 
27
- try {
28
- await axios.post(`${config.loggerUrl}/log`, logData, {
29
- timeout: 5000
30
- })
31
- } catch (error) {}
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
32
95
  }
33
96
 
34
97
  return function azifyLoggingMiddleware(req, res, next) {
35
98
  const startTime = Date.now()
36
99
  const requestId = req.requestId || require('uuid').v4()
37
- const middlewareId = require('uuid').v4().substring(0, 8)
38
100
 
39
- const reqCtx = startRequestContext({ requestId })
40
- req.__azifyTraceId = reqCtx.traceId
41
- req.__azifySpanId = reqCtx.spanId
42
- req.__azifyParentSpanId = reqCtx.parentSpanId
101
+ if (res._azifySetup) {
102
+ return next()
103
+ }
104
+ res._azifySetup = true
43
105
 
44
- const requestTraceId = req.__azifyTraceId
45
- const requestSpanId = req.__azifySpanId
46
- const requestParentSpanId = req.__azifyParentSpanId
106
+ const reqCtx = startRequestContext({ requestId })
107
+ const requestTraceId = reqCtx.traceId
108
+ const requestSpanId = reqCtx.spanId
109
+ const requestParentSpanId = reqCtx.parentSpanId
47
110
 
48
111
  let baseUrl = req.url
49
112
  if (baseUrl.includes('?')) {
@@ -58,7 +121,7 @@ function createRestifyLoggingMiddleware(options = {}) {
58
121
  url: req.url,
59
122
  baseUrl: baseUrl,
60
123
  path: req.url,
61
- headers: req.headers,
124
+ headers: sanitizeHeaders(req.headers),
62
125
  query: req.query,
63
126
  userAgent: req.headers['user-agent'],
64
127
  ip: req.connection.remoteAddress || req.socket.remoteAddress,
@@ -71,27 +134,13 @@ function createRestifyLoggingMiddleware(options = {}) {
71
134
  sendLog('info', `[REQUEST] ${req.method} ${req.url}`, req._azifyRequestData)
72
135
  } else {
73
136
  if (req.body !== undefined) {
74
- req._azifyRequestData.requestBody = req.body
137
+ req._azifyRequestData.requestBody = sanitizeBody(req.body)
75
138
  }
76
139
  sendLog('info', `[REQUEST] ${req.method} ${req.url}`, req._azifyRequestData)
77
140
  }
78
141
 
79
- res.on('finish', () => {
80
- if (!responseLogged) {
81
- logResponse()
82
- responseLogged = true
83
- }
84
- })
85
-
86
- res.on('close', () => {
87
- if (!responseLogged) {
88
- logResponse()
89
- responseLogged = true
90
- }
91
- })
92
-
142
+ res._azifyResponseLogged = false
93
143
  let sentBody
94
- let responseLogged = false
95
144
 
96
145
  const originalSend = res.send && res.send.bind(res)
97
146
  if (originalSend) {
@@ -104,9 +153,9 @@ function createRestifyLoggingMiddleware(options = {}) {
104
153
  }
105
154
  } catch (_) {}
106
155
 
107
- if (!responseLogged) {
156
+ if (!res._azifyResponseLogged) {
157
+ res._azifyResponseLogged = true
108
158
  logResponse()
109
- responseLogged = true
110
159
  }
111
160
 
112
161
  return originalSend.apply(this, arguments)
@@ -165,21 +214,8 @@ function createRestifyLoggingMiddleware(options = {}) {
165
214
  res._actualStatusCode = res.statusCode || 200
166
215
  }
167
216
  }
168
-
169
- if (!responseLogged) {
170
- logResponse()
171
- responseLogged = true
172
- }
173
-
174
217
  return originalJsonMethod.apply(this, arguments)
175
218
  }
176
-
177
- res.on('finish', function() {
178
- if (!responseLogged) {
179
- logResponse()
180
- responseLogged = true
181
- }
182
- })
183
219
 
184
220
  const originalEnd = res.end
185
221
  res.end = function(chunk, encoding) {
@@ -198,9 +234,9 @@ function createRestifyLoggingMiddleware(options = {}) {
198
234
  }
199
235
  } catch (_) {}
200
236
 
201
- if (!responseLogged) {
237
+ if (!res._azifyResponseLogged) {
202
238
  logResponse()
203
- responseLogged = true
239
+ res._azifyResponseLogged = true
204
240
  }
205
241
 
206
242
  originalEnd.call(this, chunk, encoding)
@@ -265,14 +301,46 @@ function createRestifyLoggingMiddleware(options = {}) {
265
301
 
266
302
  req._azifyContext = reqCtx
267
303
 
268
- try {
269
- runWithRequestContext(reqCtx, () => {
270
- next()
271
- })
272
- } catch (error) {
273
- console.error('Error in azify middleware:', error)
274
- next()
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)
275
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
+ })
276
344
  }
277
345
  }
278
346
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "azify-logger",
3
- "version": "1.0.13",
3
+ "version": "1.0.15",
4
4
  "description": "Azify Logger Client - Centralized logging for OpenSearch",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -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! Aplicando patches...')
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,6 +167,22 @@ 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
+ const shouldFilterLog = (
171
+ message.includes('prisma:query') ||
172
+ message.includes('prisma:info') ||
173
+ message.includes('Starting a mysql pool') ||
174
+ message.includes('SELECT `') ||
175
+ message.includes('INSERT `') ||
176
+ message.includes('UPDATE `') ||
177
+ message.includes('DELETE `') ||
178
+ message.includes('%s: %s') ||
179
+ message.includes('Application Startup Time')
180
+ )
181
+
182
+ if (shouldFilterLog) {
183
+ return res.json({ success: true, message: 'Log filtrado (Prisma verboso)' })
184
+ }
185
+
170
186
  const requestId = meta?.requestId
171
187
 
172
188
  let traceContext = null
@@ -0,0 +1,19 @@
1
+ import { Writable } from 'stream';
2
+
3
+ export interface BunyanStreamOptions {
4
+ loggerUrl?: string;
5
+ serviceName?: string;
6
+ environment?: string;
7
+ }
8
+
9
+ /**
10
+ * Creates a Bunyan stream for azify-logger
11
+ * @param options - Configuration options
12
+ * @returns Writable stream
13
+ * @example
14
+ * const bunyanStream = require('azify-logger/streams/bunyan');
15
+ * const stream = bunyanStream({ loggerUrl: 'http://localhost:3001' });
16
+ */
17
+ declare function createBunyanStream(options?: BunyanStreamOptions): Writable;
18
+
19
+ export = createBunyanStream;
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
- ...record,
45
+ ...cleanRecord,
44
46
  service: { name: serviceName, version: record.service?.version || '1.0.0' },
45
47
  environment,
46
48
  timestamp: new Date().toISOString(),
@@ -52,7 +54,7 @@ function createBunyanStream(options = {}) {
52
54
 
53
55
  const payload = { level, message: record.msg || record.message || 'log', meta }
54
56
 
55
- axios.post(`${loggerUrl}/log`, payload, { headers, timeout: 3001 }).catch(() => {})
57
+ axios.post(`${loggerUrl}`, payload, { headers, timeout: 3001 }).catch(() => {})
56
58
  }
57
59
  }
58
60
  }
@@ -0,0 +1,19 @@
1
+ import { Transform } from 'stream';
2
+
3
+ export interface PinoStreamOptions {
4
+ loggerUrl?: string;
5
+ serviceName?: string;
6
+ environment?: string;
7
+ }
8
+
9
+ /**
10
+ * Creates a Pino stream for azify-logger
11
+ * @param options - Configuration options
12
+ * @returns Transform stream
13
+ * @example
14
+ * const pinoStream = require('azify-logger/streams/pino');
15
+ * const stream = pinoStream({ loggerUrl: 'http://localhost:3001' });
16
+ */
17
+ declare function createPinoStream(options?: PinoStreamOptions): Transform;
18
+
19
+ export = createPinoStream;
package/streams/pino.js CHANGED
@@ -16,11 +16,18 @@ function createPinoStream(options = {}) {
16
16
 
17
17
  let traceId, spanId
18
18
  try {
19
- const span = trace.getSpan(context.active())
20
- const spanContext = span?.spanContext()
21
- if (spanContext) {
22
- traceId = spanContext.traceId
23
- spanId = spanContext.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
 
@@ -47,7 +54,7 @@ function createPinoStream(options = {}) {
47
54
  }
48
55
 
49
56
  const payload = { level, message: record.msg || record.message || 'log', meta }
50
- axios.post(`${loggerUrl}/log`, payload, { headers, timeout: 3001 }).catch(() => {})
57
+ axios.post(`${loggerUrl}`, payload, { headers, timeout: 3001 }).catch(() => {})
51
58
  }
52
59
  }
53
60
  }