@onlineapps/service-wrapper 2.1.5 → 2.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/ServiceWrapper.js +3 -12
- package/src/index.js +4 -3
- package/src/HttpLoggingMiddleware.js +0 -295
package/package.json
CHANGED
package/src/ServiceWrapper.js
CHANGED
|
@@ -22,7 +22,6 @@ const CookbookConnector = require('@onlineapps/conn-orch-cookbook');
|
|
|
22
22
|
const CacheConnector = require('@onlineapps/conn-base-cache');
|
|
23
23
|
const ErrorHandlerConnector = require('@onlineapps/conn-infra-error-handler');
|
|
24
24
|
const { ValidationOrchestrator } = require('@onlineapps/conn-orch-validator');
|
|
25
|
-
const { createHttpLogging } = require('./HttpLoggingMiddleware');
|
|
26
25
|
|
|
27
26
|
const INFRA_QUEUE_OWNERS = {
|
|
28
27
|
'workflow.init': 'Gateway (api_gateway)',
|
|
@@ -559,17 +558,9 @@ class ServiceWrapper {
|
|
|
559
558
|
// Logger is now available, use it
|
|
560
559
|
this.logger.info('Monitoring connector initialized', { logsDir });
|
|
561
560
|
|
|
562
|
-
//
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
const httpLogging = createHttpLogging(() => this.logger, loggingConfig);
|
|
566
|
-
|
|
567
|
-
// Store for access from outside if needed
|
|
568
|
-
this.httpLogging = httpLogging;
|
|
569
|
-
|
|
570
|
-
// Apply middlewares to Express app
|
|
571
|
-
httpLogging.applyTo(this.app);
|
|
572
|
-
}
|
|
561
|
+
// NOTE: HTTP logging middleware is applied directly in service's app.js
|
|
562
|
+
// using middlewares/httpLogging.js with lazy logger access via lib/logger.js
|
|
563
|
+
// Configuration is in conn-config/config.json -> wrapper.logging (for reference)
|
|
573
564
|
}
|
|
574
565
|
|
|
575
566
|
/**
|
package/src/index.js
CHANGED
|
@@ -13,15 +13,16 @@
|
|
|
13
13
|
|
|
14
14
|
const ServiceWrapper = require('./ServiceWrapper');
|
|
15
15
|
const { ConfigLoader } = require('./ConfigLoader');
|
|
16
|
-
const HttpLoggingMiddleware = require('./HttpLoggingMiddleware');
|
|
17
16
|
|
|
18
17
|
// Note: WorkflowProcessor and ApiCaller functionality has been moved to connectors:
|
|
19
18
|
// - WorkflowProcessor -> @onlineapps/conn-orch-orchestrator
|
|
20
19
|
// - ApiCaller -> @onlineapps/conn-orch-api-mapper
|
|
21
20
|
|
|
21
|
+
// Note: HTTP logging middleware is now in each service's middlewares/httpLogging.js
|
|
22
|
+
// It uses lazy logger access via lib/logger.js (set after wrapper.initialize())
|
|
23
|
+
|
|
22
24
|
module.exports = ServiceWrapper;
|
|
23
25
|
module.exports.ServiceWrapper = ServiceWrapper;
|
|
24
26
|
module.exports.ConfigLoader = ConfigLoader;
|
|
25
|
-
module.exports.HttpLoggingMiddleware = HttpLoggingMiddleware;
|
|
26
27
|
module.exports.default = ServiceWrapper;
|
|
27
|
-
module.exports.VERSION = '2.1.
|
|
28
|
+
module.exports.VERSION = '2.1.6';
|
|
@@ -1,295 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* HTTP Logging Middleware
|
|
5
|
-
*
|
|
6
|
-
* Configurable request/response logging for business services.
|
|
7
|
-
* Logs to both local files and central monitoring via wrapper.logger.
|
|
8
|
-
*
|
|
9
|
-
* Configuration in conn-config/config.json:
|
|
10
|
-
* {
|
|
11
|
-
* "wrapper": {
|
|
12
|
-
* "logging": {
|
|
13
|
-
* "enabled": true, // Master switch
|
|
14
|
-
* "level": "info", // Log level: debug, info, warn, error
|
|
15
|
-
* "requests": {
|
|
16
|
-
* "enabled": true, // Log incoming requests
|
|
17
|
-
* "bodies": true, // Include request bodies
|
|
18
|
-
* "headers": false // Include request headers (careful with auth tokens)
|
|
19
|
-
* },
|
|
20
|
-
* "responses": {
|
|
21
|
-
* "enabled": true, // Log outgoing responses
|
|
22
|
-
* "bodies": true // Include response bodies
|
|
23
|
-
* },
|
|
24
|
-
* "excludePaths": [ // Paths to exclude from logging
|
|
25
|
-
* "/health",
|
|
26
|
-
* "/status",
|
|
27
|
-
* "/metrics"
|
|
28
|
-
* ]
|
|
29
|
-
* }
|
|
30
|
-
* }
|
|
31
|
-
* }
|
|
32
|
-
*/
|
|
33
|
-
|
|
34
|
-
const DEFAULT_CONFIG = {
|
|
35
|
-
enabled: true,
|
|
36
|
-
level: 'info',
|
|
37
|
-
requests: {
|
|
38
|
-
enabled: true,
|
|
39
|
-
bodies: true,
|
|
40
|
-
headers: false
|
|
41
|
-
},
|
|
42
|
-
responses: {
|
|
43
|
-
enabled: true,
|
|
44
|
-
bodies: true
|
|
45
|
-
},
|
|
46
|
-
excludePaths: ['/health', '/status', '/metrics', '/specification']
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Merge user config with defaults
|
|
51
|
-
*/
|
|
52
|
-
function mergeConfig(userConfig = {}) {
|
|
53
|
-
return {
|
|
54
|
-
enabled: userConfig.enabled ?? DEFAULT_CONFIG.enabled,
|
|
55
|
-
level: userConfig.level ?? DEFAULT_CONFIG.level,
|
|
56
|
-
requests: {
|
|
57
|
-
enabled: userConfig.requests?.enabled ?? DEFAULT_CONFIG.requests.enabled,
|
|
58
|
-
bodies: userConfig.requests?.bodies ?? DEFAULT_CONFIG.requests.bodies,
|
|
59
|
-
headers: userConfig.requests?.headers ?? DEFAULT_CONFIG.requests.headers
|
|
60
|
-
},
|
|
61
|
-
responses: {
|
|
62
|
-
enabled: userConfig.responses?.enabled ?? DEFAULT_CONFIG.responses.enabled,
|
|
63
|
-
bodies: userConfig.responses?.bodies ?? DEFAULT_CONFIG.responses.bodies
|
|
64
|
-
},
|
|
65
|
-
excludePaths: userConfig.excludePaths ?? DEFAULT_CONFIG.excludePaths
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Check if path should be excluded from logging
|
|
71
|
-
*/
|
|
72
|
-
function shouldExclude(path, excludePaths) {
|
|
73
|
-
return excludePaths.some(excluded => {
|
|
74
|
-
// Exact match or prefix match
|
|
75
|
-
return path === excluded || path.startsWith(excluded + '/');
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Safely stringify body for logging
|
|
81
|
-
*/
|
|
82
|
-
function safeStringify(body) {
|
|
83
|
-
if (body === undefined || body === null) {
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (typeof body === 'string') {
|
|
88
|
-
// Already a string - could be JSON or plain text
|
|
89
|
-
try {
|
|
90
|
-
// Try to parse and re-stringify for consistent format
|
|
91
|
-
return JSON.parse(body);
|
|
92
|
-
} catch {
|
|
93
|
-
return body;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (Buffer.isBuffer(body)) {
|
|
98
|
-
return `[Buffer: ${body.length} bytes]`;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Object - return as is (will be serialized by logger)
|
|
102
|
-
return body;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Create request logging middleware
|
|
107
|
-
* @param {Function} getLogger - Function that returns logger instance
|
|
108
|
-
* @param {Object} config - Logging configuration
|
|
109
|
-
* @returns {Function} Express middleware
|
|
110
|
-
*/
|
|
111
|
-
function createRequestLogger(getLogger, config) {
|
|
112
|
-
const cfg = mergeConfig(config);
|
|
113
|
-
|
|
114
|
-
return (req, res, next) => {
|
|
115
|
-
// Skip if disabled
|
|
116
|
-
if (!cfg.enabled || !cfg.requests.enabled) {
|
|
117
|
-
return next();
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Skip excluded paths
|
|
121
|
-
if (shouldExclude(req.path, cfg.excludePaths)) {
|
|
122
|
-
return next();
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const logger = getLogger();
|
|
126
|
-
if (!logger) {
|
|
127
|
-
return next();
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Build log data
|
|
131
|
-
const logData = {
|
|
132
|
-
type: 'request',
|
|
133
|
-
method: req.method,
|
|
134
|
-
path: req.path,
|
|
135
|
-
url: req.originalUrl,
|
|
136
|
-
ip: req.ip || req.connection?.remoteAddress,
|
|
137
|
-
userAgent: req.get('user-agent')
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
// Add query params if present
|
|
141
|
-
if (req.query && Object.keys(req.query).length > 0) {
|
|
142
|
-
logData.query = req.query;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Add request body if enabled
|
|
146
|
-
if (cfg.requests.bodies && req.body && Object.keys(req.body).length > 0) {
|
|
147
|
-
logData.body = safeStringify(req.body);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Add headers if enabled
|
|
151
|
-
if (cfg.requests.headers) {
|
|
152
|
-
// Filter out sensitive headers
|
|
153
|
-
const headers = { ...req.headers };
|
|
154
|
-
delete headers.authorization;
|
|
155
|
-
delete headers.cookie;
|
|
156
|
-
logData.headers = headers;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Store start time for response duration
|
|
160
|
-
req._loggingStartTime = Date.now();
|
|
161
|
-
|
|
162
|
-
logger.info('HTTP Request', logData);
|
|
163
|
-
next();
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Create response logging middleware
|
|
169
|
-
* @param {Function} getLogger - Function that returns logger instance
|
|
170
|
-
* @param {Object} config - Logging configuration
|
|
171
|
-
* @returns {Function} Express middleware
|
|
172
|
-
*/
|
|
173
|
-
function createResponseLogger(getLogger, config) {
|
|
174
|
-
const cfg = mergeConfig(config);
|
|
175
|
-
|
|
176
|
-
return (req, res, next) => {
|
|
177
|
-
// Skip if disabled
|
|
178
|
-
if (!cfg.enabled || !cfg.responses.enabled) {
|
|
179
|
-
return next();
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// Skip excluded paths
|
|
183
|
-
if (shouldExclude(req.path, cfg.excludePaths)) {
|
|
184
|
-
return next();
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
const logger = getLogger();
|
|
188
|
-
if (!logger) {
|
|
189
|
-
return next();
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// Store original methods
|
|
193
|
-
const originalSend = res.send;
|
|
194
|
-
const originalJson = res.json;
|
|
195
|
-
|
|
196
|
-
// Flag to prevent double logging
|
|
197
|
-
let logged = false;
|
|
198
|
-
|
|
199
|
-
const logResponse = (body) => {
|
|
200
|
-
if (logged) return;
|
|
201
|
-
logged = true;
|
|
202
|
-
|
|
203
|
-
const duration = req._loggingStartTime
|
|
204
|
-
? Date.now() - req._loggingStartTime
|
|
205
|
-
: null;
|
|
206
|
-
|
|
207
|
-
const logData = {
|
|
208
|
-
type: 'response',
|
|
209
|
-
method: req.method,
|
|
210
|
-
path: req.path,
|
|
211
|
-
statusCode: res.statusCode,
|
|
212
|
-
statusMessage: res.statusMessage
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
if (duration !== null) {
|
|
216
|
-
logData.durationMs = duration;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Add response body if enabled
|
|
220
|
-
if (cfg.responses.bodies && body !== undefined) {
|
|
221
|
-
logData.body = safeStringify(body);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// Choose log level based on status code
|
|
225
|
-
if (res.statusCode >= 500) {
|
|
226
|
-
logger.error('HTTP Response', logData);
|
|
227
|
-
} else if (res.statusCode >= 400) {
|
|
228
|
-
logger.warn('HTTP Response', logData);
|
|
229
|
-
} else {
|
|
230
|
-
logger.info('HTTP Response', logData);
|
|
231
|
-
}
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
// Override res.send
|
|
235
|
-
res.send = function(body) {
|
|
236
|
-
logResponse(body);
|
|
237
|
-
return originalSend.call(this, body);
|
|
238
|
-
};
|
|
239
|
-
|
|
240
|
-
// Override res.json
|
|
241
|
-
res.json = function(body) {
|
|
242
|
-
logResponse(body);
|
|
243
|
-
return originalJson.call(this, body);
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
next();
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* Create combined HTTP logging middleware
|
|
252
|
-
* @param {Function} getLogger - Function that returns logger instance
|
|
253
|
-
* @param {Object} config - Logging configuration from wrapper.logging
|
|
254
|
-
* @returns {Object} Object with requestLogger and responseLogger middlewares
|
|
255
|
-
*/
|
|
256
|
-
function createHttpLogging(getLogger, config = {}) {
|
|
257
|
-
const cfg = mergeConfig(config);
|
|
258
|
-
|
|
259
|
-
return {
|
|
260
|
-
config: cfg,
|
|
261
|
-
requestLogger: createRequestLogger(getLogger, config),
|
|
262
|
-
responseLogger: createResponseLogger(getLogger, config),
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* Apply both middlewares to Express app
|
|
266
|
-
* @param {Object} app - Express application
|
|
267
|
-
*/
|
|
268
|
-
applyTo(app) {
|
|
269
|
-
if (!cfg.enabled) {
|
|
270
|
-
console.log('[HttpLogging] Disabled by configuration');
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
if (cfg.requests.enabled) {
|
|
275
|
-
app.use(this.requestLogger);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
if (cfg.responses.enabled) {
|
|
279
|
-
app.use(this.responseLogger);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
console.log(`[HttpLogging] Enabled (requests: ${cfg.requests.enabled}, responses: ${cfg.responses.enabled}, bodies: ${cfg.requests.bodies})`);
|
|
283
|
-
console.log(`[HttpLogging] Excluded paths: ${cfg.excludePaths.join(', ')}`);
|
|
284
|
-
}
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
module.exports = {
|
|
289
|
-
createHttpLogging,
|
|
290
|
-
createRequestLogger,
|
|
291
|
-
createResponseLogger,
|
|
292
|
-
mergeConfig,
|
|
293
|
-
DEFAULT_CONFIG
|
|
294
|
-
};
|
|
295
|
-
|