@devilsdev/rag-pipeline-utils 2.1.12 → 2.2.1
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/.ragrc.schema.json +218 -0
- package/README.md +178 -550
- package/bin/cli.js +8 -14
- package/contracts/reranker-contract.json +69 -0
- package/dist/index.d.ts +237 -0
- package/dist/index.mjs +22 -7
- package/package.json +18 -13
- package/src/ai/adaptive-retrieval.js +191 -0
- package/src/ai/federated-learning.js +214 -0
- package/src/ai/federation/federated-learning-coordinator.js +345 -0
- package/src/ai/federation.js +76 -0
- package/src/ai/index-fixed.js +509 -0
- package/src/ai/index.js +33 -0
- package/src/ai/model-trainer.js +217 -0
- package/src/ai/model-training.js +205 -0
- package/src/ai/module-template.js +37 -0
- package/src/ai/multimodal/multi-modal-processor.js +345 -0
- package/src/ai/multimodal-processing.js +268 -0
- package/src/ai/multimodal.js +71 -0
- package/src/ai/orchestrator.js +70 -0
- package/src/ai/retrieval/adaptive-retrieval-engine.js +398 -0
- package/src/ai/retrieval-engine.js +69 -0
- package/src/ai/training/model-training-orchestrator.js +228 -0
- package/src/ci/workflow-analyzer.js +71 -0
- package/src/cli/commands/ai-ml.js +967 -0
- package/src/cli/commands/docs.js +228 -0
- package/src/cli/commands/dx.js +538 -0
- package/src/cli/commands/plugin-hub.js +875 -0
- package/src/cli/doctor-command.js +639 -0
- package/src/cli/enhanced-cli-commands.js +945 -0
- package/src/cli/interactive-wizard.js +997 -0
- package/src/cli/plugin-marketplace-commands.js +869 -0
- package/src/cli.js +17 -0
- package/src/config/enhanced-ragrc-schema.js +632 -0
- package/src/config/load-config.js +54 -0
- package/src/config/load-plugin-config.js +69 -0
- package/src/config/normalize-config.js +105 -0
- package/src/config/schema-validator.js +315 -0
- package/src/config/validate-plugin-schema.js +35 -0
- package/src/config/validate-schema.js +113 -0
- package/src/contracts/plugin-contracts.js +33 -0
- package/src/core/create-pipeline.js +99 -0
- package/src/core/dependency-injection.js +242 -0
- package/src/core/observability/event-logger.js +241 -0
- package/src/core/observability/instrumented-pipeline.js +609 -0
- package/src/core/observability/metrics.js +497 -0
- package/src/core/observability/tracing.js +781 -0
- package/src/core/performance/benchmark.js +516 -0
- package/src/core/performance/parallel-processor.js +240 -0
- package/src/core/performance/streaming-safeguards.js +620 -0
- package/src/core/pipeline-factory.js +60 -0
- package/src/core/plugin-contracts.js +89 -0
- package/src/core/plugin-marketplace/plugin-metadata.js +485 -0
- package/src/core/plugin-marketplace/plugin-publisher.js +574 -0
- package/src/core/plugin-marketplace/plugin-registry-format.js +419 -0
- package/src/core/plugin-marketplace/version-resolver.js +61 -0
- package/src/core/plugin-registry.js +294 -0
- package/src/dag/dag-engine.js +954 -0
- package/src/dag/dag-node.js +76 -0
- package/src/dag/enhanced-dag-engine.js +822 -0
- package/src/dx/index.js +40 -0
- package/src/dx/integration-templates.js +665 -0
- package/src/dx/performance-profiler.js +968 -0
- package/src/dx/realtime-debugger.js +755 -0
- package/src/dx/visual-pipeline-builder.js +578 -0
- package/src/ecosystem/plugin-analytics-dashboard.js +778 -0
- package/src/ecosystem/plugin-certification.js +580 -0
- package/src/ecosystem/plugin-hub.js +821 -0
- package/src/enterprise/audit-logging.js +967 -0
- package/src/enterprise/data-governance.js +408 -0
- package/src/enterprise/multi-tenancy.js +496 -0
- package/src/enterprise/sso-integration.js +1030 -0
- package/src/evaluate/evaluator.js +52 -0
- package/src/evaluate/scoring.js +91 -0
- package/src/index.js +67 -0
- package/src/ingest.js +59 -0
- package/src/loader/csv-loader.js +38 -0
- package/src/loader/directory-loader.js +48 -0
- package/src/loader/html-loader.js +62 -0
- package/src/loader/markdown-loader.js +67 -0
- package/src/mocks/openai-embedder.js +119 -0
- package/src/mocks/openai-llm.js +77 -0
- package/src/mocks/pdf-loader.js +21 -0
- package/src/mocks/pinecone-retriever.js +106 -0
- package/src/observability/audit-logger.js +758 -0
- package/src/observability/dashboard-config.json +675 -0
- package/src/observability/event-logger.js +310 -0
- package/src/observability/metrics.js +691 -0
- package/src/observability/security-monitor.js +830 -0
- package/src/observability/slo-monitor.js +319 -0
- package/src/observability/telemetry.js +686 -0
- package/src/pipeline/pipeline.js +18 -0
- package/src/plugins/sample-embedder.js +53 -0
- package/src/plugins/sample-llm.js +30 -0
- package/src/plugins/sample-loader.js +24 -0
- package/src/plugins/sample-retriever.js +84 -0
- package/src/query.js +117 -0
- package/src/reranker/llm-reranker.js +111 -0
- package/src/scripts/script-utilities.js +36 -0
- package/src/security/plugin-sandbox.js +586 -0
- package/src/security/plugin-signature-verifier.js +414 -0
- package/src/security/validator.js +36 -0
- package/src/utils/ci/diagnostic-reporter.js +57 -0
- package/src/utils/logger.js +211 -0
- package/src/utils/performance-monitor.js +561 -0
- package/src/utils/plugin-scaffolder.js +447 -0
- package/src/utils/rate-limiter.js +244 -0
- package/src/utils/retry-policy.js +443 -0
- package/src/utils/retry.js +107 -0
- package/src/utils/safe-expression-evaluator.js +579 -0
- package/src/utils/secure-logging.js +338 -0
- package/src/utils/structured-logger.js +388 -0
- package/src/utils/validate-plugin-contract.js +42 -0
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Enterprise Performance Monitoring System
|
|
3
|
+
* Provides comprehensive performance tracking, metrics collection, and observability
|
|
4
|
+
*
|
|
5
|
+
* @author DevilsDev Team
|
|
6
|
+
* @since 2.1.8
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const { logger } = require('./structured-logger.js');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {Object} PerformanceMetric
|
|
13
|
+
* @property {string} name - Metric name
|
|
14
|
+
* @property {number} value - Metric value
|
|
15
|
+
* @property {string} unit - Metric unit (ms, bytes, count, etc.)
|
|
16
|
+
* @property {Date} timestamp - When metric was recorded
|
|
17
|
+
* @property {Object} tags - Additional metric tags
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @typedef {Object} TimerMetric
|
|
22
|
+
* @property {string} name - Timer name
|
|
23
|
+
* @property {number} startTime - Start timestamp
|
|
24
|
+
* @property {number} [endTime] - End timestamp
|
|
25
|
+
* @property {number} [duration] - Duration in milliseconds
|
|
26
|
+
* @property {Object} [tags] - Additional tags
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Enterprise performance monitoring with metrics aggregation
|
|
31
|
+
*/
|
|
32
|
+
class PerformanceMonitor {
|
|
33
|
+
constructor(options = {}) {
|
|
34
|
+
this.serviceName = options.serviceName || 'rag-pipeline-utils';
|
|
35
|
+
this.enableMemoryTracking = options.enableMemoryTracking !== false;
|
|
36
|
+
this.enableCpuTracking = options.enableCpuTracking !== false;
|
|
37
|
+
this.metricsRetentionMs = options.metricsRetentionMs || 24 * 60 * 60 * 1000; // 24 hours
|
|
38
|
+
this.aggregationInterval = options.aggregationInterval || 60000; // 1 minute
|
|
39
|
+
|
|
40
|
+
// Metrics storage
|
|
41
|
+
this.metrics = new Map(); // name -> array of metrics
|
|
42
|
+
this.timers = new Map(); // timerId -> timer data
|
|
43
|
+
this.counters = new Map(); // name -> counter value
|
|
44
|
+
this.gauges = new Map(); // name -> gauge value
|
|
45
|
+
this.histograms = new Map(); // name -> array of values
|
|
46
|
+
|
|
47
|
+
// Performance tracking
|
|
48
|
+
this.systemMetrics = {
|
|
49
|
+
memoryUsage: [],
|
|
50
|
+
cpuUsage: [],
|
|
51
|
+
eventLoopLag: [],
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Start background monitoring
|
|
55
|
+
this.startSystemMonitoring();
|
|
56
|
+
|
|
57
|
+
this.logger = logger.child({
|
|
58
|
+
component: 'performance-monitor',
|
|
59
|
+
service: this.serviceName,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
this.logger.info('Performance monitoring initialized', {
|
|
63
|
+
memoryTracking: this.enableMemoryTracking,
|
|
64
|
+
cpuTracking: this.enableCpuTracking,
|
|
65
|
+
retentionMs: this.metricsRetentionMs,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Start system resource monitoring
|
|
71
|
+
*/
|
|
72
|
+
startSystemMonitoring() {
|
|
73
|
+
if (this.enableMemoryTracking) {
|
|
74
|
+
this.memoryInterval = setInterval(() => {
|
|
75
|
+
this.recordMemoryUsage();
|
|
76
|
+
}, 30000); // Every 30 seconds
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (this.enableCpuTracking) {
|
|
80
|
+
this.cpuInterval = setInterval(() => {
|
|
81
|
+
this.recordCpuUsage();
|
|
82
|
+
}, 30000); // Every 30 seconds
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Event loop lag monitoring
|
|
86
|
+
this.eventLoopInterval = setInterval(() => {
|
|
87
|
+
this.recordEventLoopLag();
|
|
88
|
+
}, 10000); // Every 10 seconds
|
|
89
|
+
|
|
90
|
+
// Cleanup old metrics
|
|
91
|
+
this.cleanupInterval = setInterval(() => {
|
|
92
|
+
this.cleanupOldMetrics();
|
|
93
|
+
}, this.aggregationInterval);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Stop system monitoring
|
|
98
|
+
*/
|
|
99
|
+
stopSystemMonitoring() {
|
|
100
|
+
if (this.memoryInterval) clearInterval(this.memoryInterval);
|
|
101
|
+
if (this.cpuInterval) clearInterval(this.cpuInterval);
|
|
102
|
+
if (this.eventLoopInterval) clearInterval(this.eventLoopInterval);
|
|
103
|
+
if (this.cleanupInterval) clearInterval(this.cleanupInterval);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Record memory usage metrics
|
|
108
|
+
*/
|
|
109
|
+
recordMemoryUsage() {
|
|
110
|
+
const memUsage = process.memoryUsage();
|
|
111
|
+
const timestamp = Date.now();
|
|
112
|
+
|
|
113
|
+
const memoryMetrics = {
|
|
114
|
+
heapUsed: memUsage.heapUsed,
|
|
115
|
+
heapTotal: memUsage.heapTotal,
|
|
116
|
+
external: memUsage.external,
|
|
117
|
+
rss: memUsage.rss,
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
this.systemMetrics.memoryUsage.push({
|
|
121
|
+
timestamp,
|
|
122
|
+
...memoryMetrics,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Update gauges
|
|
126
|
+
for (const [key, value] of Object.entries(memoryMetrics)) {
|
|
127
|
+
this.gauge(`memory.${key}`, value, { unit: 'bytes' });
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Cleanup old memory metrics
|
|
131
|
+
const cutoff = timestamp - this.metricsRetentionMs;
|
|
132
|
+
this.systemMetrics.memoryUsage = this.systemMetrics.memoryUsage.filter(
|
|
133
|
+
(m) => m.timestamp > cutoff,
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Record CPU usage metrics
|
|
139
|
+
*/
|
|
140
|
+
recordCpuUsage() {
|
|
141
|
+
const cpuUsage = process.cpuUsage();
|
|
142
|
+
const timestamp = Date.now();
|
|
143
|
+
|
|
144
|
+
this.systemMetrics.cpuUsage.push({
|
|
145
|
+
timestamp,
|
|
146
|
+
user: cpuUsage.user,
|
|
147
|
+
system: cpuUsage.system,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
this.gauge('cpu.user', cpuUsage.user, { unit: 'microseconds' });
|
|
151
|
+
this.gauge('cpu.system', cpuUsage.system, { unit: 'microseconds' });
|
|
152
|
+
|
|
153
|
+
// Cleanup old CPU metrics
|
|
154
|
+
const cutoff = timestamp - this.metricsRetentionMs;
|
|
155
|
+
this.systemMetrics.cpuUsage = this.systemMetrics.cpuUsage.filter(
|
|
156
|
+
(m) => m.timestamp > cutoff,
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Record event loop lag
|
|
162
|
+
*/
|
|
163
|
+
recordEventLoopLag() {
|
|
164
|
+
const start = process.hrtime.bigint();
|
|
165
|
+
setImmediate(() => {
|
|
166
|
+
const lag = Number(process.hrtime.bigint() - start) / 1000000; // Convert to ms
|
|
167
|
+
const timestamp = Date.now();
|
|
168
|
+
|
|
169
|
+
this.systemMetrics.eventLoopLag.push({
|
|
170
|
+
timestamp,
|
|
171
|
+
lag,
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
this.gauge('eventloop.lag', lag, { unit: 'ms' });
|
|
175
|
+
|
|
176
|
+
// Cleanup old lag metrics
|
|
177
|
+
const cutoff = timestamp - this.metricsRetentionMs;
|
|
178
|
+
this.systemMetrics.eventLoopLag = this.systemMetrics.eventLoopLag.filter(
|
|
179
|
+
(m) => m.timestamp > cutoff,
|
|
180
|
+
);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Start a timer for measuring duration
|
|
186
|
+
* @param {string} name - Timer name
|
|
187
|
+
* @param {Object} [tags={}] - Additional tags
|
|
188
|
+
* @returns {string} Timer ID
|
|
189
|
+
*/
|
|
190
|
+
startTimer(name, tags = {}) {
|
|
191
|
+
const timerId = `${name}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
192
|
+
|
|
193
|
+
this.timers.set(timerId, {
|
|
194
|
+
name,
|
|
195
|
+
startTime: performance.now(),
|
|
196
|
+
tags,
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
return timerId;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* End a timer and record the duration
|
|
204
|
+
* @param {string} timerId - Timer ID from startTimer
|
|
205
|
+
* @returns {number} Duration in milliseconds
|
|
206
|
+
*/
|
|
207
|
+
endTimer(timerId) {
|
|
208
|
+
const timer = this.timers.get(timerId);
|
|
209
|
+
if (!timer) {
|
|
210
|
+
this.logger.warn('Timer not found', { timerId });
|
|
211
|
+
return 0;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const endTime = performance.now();
|
|
215
|
+
const duration = endTime - timer.startTime;
|
|
216
|
+
|
|
217
|
+
timer.endTime = endTime;
|
|
218
|
+
timer.duration = duration;
|
|
219
|
+
|
|
220
|
+
// Record as histogram
|
|
221
|
+
this.histogram(timer.name, duration, { ...timer.tags, unit: 'ms' });
|
|
222
|
+
|
|
223
|
+
// Remove timer from active timers
|
|
224
|
+
this.timers.delete(timerId);
|
|
225
|
+
|
|
226
|
+
this.logger.debug('Timer completed', {
|
|
227
|
+
name: timer.name,
|
|
228
|
+
duration,
|
|
229
|
+
tags: timer.tags,
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
return duration;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Measure execution time of a function
|
|
237
|
+
* @param {string} name - Metric name
|
|
238
|
+
* @param {Function} fn - Function to measure
|
|
239
|
+
* @param {Object} [tags={}] - Additional tags
|
|
240
|
+
* @returns {Promise<any>} Function result
|
|
241
|
+
*/
|
|
242
|
+
async time(name, fn, tags = {}) {
|
|
243
|
+
const timerId = this.startTimer(name, tags);
|
|
244
|
+
|
|
245
|
+
try {
|
|
246
|
+
const result = await fn();
|
|
247
|
+
const duration = this.endTimer(timerId);
|
|
248
|
+
|
|
249
|
+
this.logger.debug('Function execution timed', {
|
|
250
|
+
name,
|
|
251
|
+
duration,
|
|
252
|
+
success: true,
|
|
253
|
+
tags,
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
return result;
|
|
257
|
+
} catch (error) {
|
|
258
|
+
const duration = this.endTimer(timerId);
|
|
259
|
+
|
|
260
|
+
this.logger.warn('Function execution failed', {
|
|
261
|
+
name,
|
|
262
|
+
duration,
|
|
263
|
+
success: false,
|
|
264
|
+
error: error.message,
|
|
265
|
+
tags,
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
throw error;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Increment a counter
|
|
274
|
+
* @param {string} name - Counter name
|
|
275
|
+
* @param {number} [value=1] - Increment value
|
|
276
|
+
* @param {Object} [tags={}] - Additional tags
|
|
277
|
+
*/
|
|
278
|
+
counter(name, value = 1, tags = {}) {
|
|
279
|
+
const current = this.counters.get(name) || 0;
|
|
280
|
+
this.counters.set(name, current + value);
|
|
281
|
+
|
|
282
|
+
this.recordMetric({
|
|
283
|
+
name,
|
|
284
|
+
value: current + value,
|
|
285
|
+
unit: 'count',
|
|
286
|
+
timestamp: new Date(),
|
|
287
|
+
tags: { ...tags, type: 'counter' },
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Set a gauge value
|
|
293
|
+
* @param {string} name - Gauge name
|
|
294
|
+
* @param {number} value - Gauge value
|
|
295
|
+
* @param {Object} [tags={}] - Additional tags
|
|
296
|
+
*/
|
|
297
|
+
gauge(name, value, tags = {}) {
|
|
298
|
+
this.gauges.set(name, value);
|
|
299
|
+
|
|
300
|
+
this.recordMetric({
|
|
301
|
+
name,
|
|
302
|
+
value,
|
|
303
|
+
unit: tags.unit || 'value',
|
|
304
|
+
timestamp: new Date(),
|
|
305
|
+
tags: { ...tags, type: 'gauge' },
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Record a histogram value
|
|
311
|
+
* @param {string} name - Histogram name
|
|
312
|
+
* @param {number} value - Value to record
|
|
313
|
+
* @param {Object} [tags={}] - Additional tags
|
|
314
|
+
*/
|
|
315
|
+
histogram(name, value, tags = {}) {
|
|
316
|
+
if (!this.histograms.has(name)) {
|
|
317
|
+
this.histograms.set(name, []);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const values = this.histograms.get(name);
|
|
321
|
+
values.push({ value, timestamp: Date.now() });
|
|
322
|
+
|
|
323
|
+
// Keep only recent values
|
|
324
|
+
const cutoff = Date.now() - this.metricsRetentionMs;
|
|
325
|
+
this.histograms.set(
|
|
326
|
+
name,
|
|
327
|
+
values.filter((v) => v.timestamp > cutoff),
|
|
328
|
+
);
|
|
329
|
+
|
|
330
|
+
this.recordMetric({
|
|
331
|
+
name,
|
|
332
|
+
value,
|
|
333
|
+
unit: tags.unit || 'value',
|
|
334
|
+
timestamp: new Date(),
|
|
335
|
+
tags: { ...tags, type: 'histogram' },
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Record a generic metric
|
|
341
|
+
* @param {PerformanceMetric} metric - Metric to record
|
|
342
|
+
*/
|
|
343
|
+
recordMetric(metric) {
|
|
344
|
+
if (!this.metrics.has(metric.name)) {
|
|
345
|
+
this.metrics.set(metric.name, []);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const metricArray = this.metrics.get(metric.name);
|
|
349
|
+
metricArray.push(metric);
|
|
350
|
+
|
|
351
|
+
// Emit to logger for observability
|
|
352
|
+
this.logger.debug('Metric recorded', {
|
|
353
|
+
metricName: metric.name,
|
|
354
|
+
value: metric.value,
|
|
355
|
+
unit: metric.unit,
|
|
356
|
+
tags: metric.tags,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Get statistics for a histogram
|
|
362
|
+
* @param {string} name - Histogram name
|
|
363
|
+
* @returns {Object} Statistics
|
|
364
|
+
*/
|
|
365
|
+
getHistogramStats(name) {
|
|
366
|
+
const histogram = this.histograms.get(name);
|
|
367
|
+
if (!histogram || histogram.length === 0) {
|
|
368
|
+
return null;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const values = histogram.map((h) => h.value).sort((a, b) => a - b);
|
|
372
|
+
const count = values.length;
|
|
373
|
+
const sum = values.reduce((a, b) => a + b, 0);
|
|
374
|
+
const mean = sum / count;
|
|
375
|
+
|
|
376
|
+
const p50 = values[Math.floor(count * 0.5)];
|
|
377
|
+
const p95 = values[Math.floor(count * 0.95)];
|
|
378
|
+
const p99 = values[Math.floor(count * 0.99)];
|
|
379
|
+
|
|
380
|
+
return {
|
|
381
|
+
count,
|
|
382
|
+
sum,
|
|
383
|
+
mean,
|
|
384
|
+
min: values[0],
|
|
385
|
+
max: values[count - 1],
|
|
386
|
+
p50,
|
|
387
|
+
p95,
|
|
388
|
+
p99,
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Get current system metrics
|
|
394
|
+
* @returns {Object} System metrics
|
|
395
|
+
*/
|
|
396
|
+
getSystemMetrics() {
|
|
397
|
+
const latest = {
|
|
398
|
+
memory:
|
|
399
|
+
this.systemMetrics.memoryUsage[
|
|
400
|
+
this.systemMetrics.memoryUsage.length - 1
|
|
401
|
+
],
|
|
402
|
+
cpu: this.systemMetrics.cpuUsage[this.systemMetrics.cpuUsage.length - 1],
|
|
403
|
+
eventLoop:
|
|
404
|
+
this.systemMetrics.eventLoopLag[
|
|
405
|
+
this.systemMetrics.eventLoopLag.length - 1
|
|
406
|
+
],
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
return {
|
|
410
|
+
current: latest,
|
|
411
|
+
history: {
|
|
412
|
+
memory: this.systemMetrics.memoryUsage.slice(-60), // Last 60 readings
|
|
413
|
+
cpu: this.systemMetrics.cpuUsage.slice(-60),
|
|
414
|
+
eventLoop: this.systemMetrics.eventLoopLag.slice(-60),
|
|
415
|
+
},
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Get all metrics summary
|
|
421
|
+
* @returns {Object} Metrics summary
|
|
422
|
+
*/
|
|
423
|
+
getMetricsSummary() {
|
|
424
|
+
const summary = {
|
|
425
|
+
counters: Object.fromEntries(this.counters),
|
|
426
|
+
gauges: Object.fromEntries(this.gauges),
|
|
427
|
+
histograms: {},
|
|
428
|
+
system: this.getSystemMetrics(),
|
|
429
|
+
activeTimers: this.timers.size,
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
// Add histogram statistics
|
|
433
|
+
for (const [name] of this.histograms) {
|
|
434
|
+
summary.histograms[name] = this.getHistogramStats(name);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
return summary;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Export metrics in Prometheus format
|
|
442
|
+
* @returns {string} Prometheus formatted metrics
|
|
443
|
+
*/
|
|
444
|
+
exportPrometheusMetrics() {
|
|
445
|
+
const lines = [];
|
|
446
|
+
const timestamp = Date.now();
|
|
447
|
+
|
|
448
|
+
// Counters
|
|
449
|
+
for (const [name, value] of this.counters) {
|
|
450
|
+
lines.push(`# TYPE ${name} counter`);
|
|
451
|
+
lines.push(`${name} ${value} ${timestamp}`);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// Gauges
|
|
455
|
+
for (const [name, value] of this.gauges) {
|
|
456
|
+
lines.push(`# TYPE ${name} gauge`);
|
|
457
|
+
lines.push(`${name} ${value} ${timestamp}`);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// Histograms
|
|
461
|
+
for (const [name] of this.histograms) {
|
|
462
|
+
const stats = this.getHistogramStats(name);
|
|
463
|
+
if (stats) {
|
|
464
|
+
lines.push(`# TYPE ${name} histogram`);
|
|
465
|
+
lines.push(`${name}_count ${stats.count} ${timestamp}`);
|
|
466
|
+
lines.push(`${name}_sum ${stats.sum} ${timestamp}`);
|
|
467
|
+
lines.push(`${name}_bucket{le="50"} ${stats.p50} ${timestamp}`);
|
|
468
|
+
lines.push(`${name}_bucket{le="95"} ${stats.p95} ${timestamp}`);
|
|
469
|
+
lines.push(`${name}_bucket{le="99"} ${stats.p99} ${timestamp}`);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
return lines.join('\n');
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Clean up old metrics
|
|
478
|
+
*/
|
|
479
|
+
cleanupOldMetrics() {
|
|
480
|
+
const cutoff = Date.now() - this.metricsRetentionMs;
|
|
481
|
+
|
|
482
|
+
// Clean up stored metrics
|
|
483
|
+
for (const [name, metricArray] of this.metrics) {
|
|
484
|
+
const filtered = metricArray.filter(
|
|
485
|
+
(m) => m.timestamp.getTime() > cutoff,
|
|
486
|
+
);
|
|
487
|
+
if (filtered.length === 0) {
|
|
488
|
+
this.metrics.delete(name);
|
|
489
|
+
} else {
|
|
490
|
+
this.metrics.set(name, filtered);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// Clean up histograms
|
|
495
|
+
for (const [name, values] of this.histograms) {
|
|
496
|
+
const filtered = values.filter((v) => v.timestamp > cutoff);
|
|
497
|
+
if (filtered.length === 0) {
|
|
498
|
+
this.histograms.delete(name);
|
|
499
|
+
} else {
|
|
500
|
+
this.histograms.set(name, filtered);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
this.logger.debug('Old metrics cleaned up', {
|
|
505
|
+
activeMetrics: this.metrics.size,
|
|
506
|
+
activeHistograms: this.histograms.size,
|
|
507
|
+
cutoffTime: new Date(cutoff).toISOString(),
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* Reset all metrics
|
|
513
|
+
*/
|
|
514
|
+
reset() {
|
|
515
|
+
this.metrics.clear();
|
|
516
|
+
this.timers.clear();
|
|
517
|
+
this.counters.clear();
|
|
518
|
+
this.gauges.clear();
|
|
519
|
+
this.histograms.clear();
|
|
520
|
+
this.systemMetrics = {
|
|
521
|
+
memoryUsage: [],
|
|
522
|
+
cpuUsage: [],
|
|
523
|
+
eventLoopLag: [],
|
|
524
|
+
};
|
|
525
|
+
|
|
526
|
+
this.logger.info('Performance metrics reset');
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Shutdown performance monitoring
|
|
531
|
+
*/
|
|
532
|
+
shutdown() {
|
|
533
|
+
this.stopSystemMonitoring();
|
|
534
|
+
this.logger.info('Performance monitoring shutdown');
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Create performance monitor instance
|
|
540
|
+
* @param {Object} [options={}] - Monitor configuration
|
|
541
|
+
* @returns {PerformanceMonitor} Monitor instance
|
|
542
|
+
*/
|
|
543
|
+
function createPerformanceMonitor(options = {}) {
|
|
544
|
+
return new PerformanceMonitor(options);
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// Default monitor instance
|
|
548
|
+
const defaultMonitor = createPerformanceMonitor({
|
|
549
|
+
serviceName: 'rag-pipeline-utils',
|
|
550
|
+
enableMemoryTracking: true,
|
|
551
|
+
enableCpuTracking: true,
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
module.exports = {
|
|
555
|
+
PerformanceMonitor,
|
|
556
|
+
createPerformanceMonitor,
|
|
557
|
+
monitor: defaultMonitor,
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
// CommonJS/ESM interop
|
|
561
|
+
module.exports.default = module.exports;
|