@ai-capabilities-suite/mcp-debugger-core
Version:
Core debugging engine for Node.js and TypeScript applications. Provides Inspector Protocol integration, breakpoint management, variable inspection, execution control, profiling, hang detection, and source map support.
241 lines • 7.38 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MetricsCollector = exports.MetricType = void 0;
/**
* Metric types for tracking different aspects of the debugger
*/
var MetricType;
(function (MetricType) {
MetricType["SESSION_DURATION"] = "session_duration";
MetricType["SESSION_COUNT"] = "session_count";
MetricType["BREAKPOINT_HIT"] = "breakpoint_hit";
MetricType["OPERATION_LATENCY"] = "operation_latency";
MetricType["ERROR_RATE"] = "error_rate";
})(MetricType || (exports.MetricType = MetricType = {}));
/**
* Metrics collector for enterprise observability
* Tracks session metrics, operation latencies, and error rates
*/
class MetricsCollector {
constructor() {
this.metrics = [];
this.sessionStartTimes = new Map();
this.breakpointHitCounts = new Map();
this.operationStartTimes = new Map();
this.errorCounts = new Map();
this.maxMetricsSize = 10000;
}
/**
* Record a session start
*/
recordSessionStart(sessionId) {
this.sessionStartTimes.set(sessionId, Date.now());
this.recordMetric(MetricType.SESSION_COUNT, 1, { action: "start" });
}
/**
* Record a session end and calculate duration
*/
recordSessionEnd(sessionId) {
const startTime = this.sessionStartTimes.get(sessionId);
if (startTime) {
const duration = Date.now() - startTime;
this.recordMetric(MetricType.SESSION_DURATION, duration, { sessionId });
this.sessionStartTimes.delete(sessionId);
}
this.recordMetric(MetricType.SESSION_COUNT, 1, { action: "end" });
}
/**
* Record a breakpoint hit
*/
recordBreakpointHit(breakpointId, sessionId) {
const currentCount = this.breakpointHitCounts.get(breakpointId) || 0;
this.breakpointHitCounts.set(breakpointId, currentCount + 1);
const labels = { breakpointId };
if (sessionId) {
labels["sessionId"] = sessionId;
}
this.recordMetric(MetricType.BREAKPOINT_HIT, 1, labels);
}
/**
* Start tracking an operation
*/
startOperation(operationId, operationType) {
this.operationStartTimes.set(operationId, Date.now());
}
/**
* End tracking an operation and record latency
*/
endOperation(operationId, operationType, success = true) {
const startTime = this.operationStartTimes.get(operationId);
if (startTime) {
const latency = Date.now() - startTime;
this.recordMetric(MetricType.OPERATION_LATENCY, latency, {
operationType,
success: success.toString(),
});
this.operationStartTimes.delete(operationId);
}
if (!success) {
this.recordError(operationType);
}
}
/**
* Record an error
*/
recordError(errorType) {
const currentCount = this.errorCounts.get(errorType) || 0;
this.errorCounts.set(errorType, currentCount + 1);
this.recordMetric(MetricType.ERROR_RATE, 1, { errorType });
}
/**
* Record a generic metric
*/
recordMetric(type, value, labels) {
const entry = {
type,
timestamp: Date.now(),
value,
labels,
};
this.metrics.push(entry);
// Limit metrics size to prevent memory issues
if (this.metrics.length > this.maxMetricsSize) {
this.metrics.shift();
}
}
/**
* Get all metrics
*/
getAllMetrics() {
return [...this.metrics];
}
/**
* Get metrics by type
*/
getMetricsByType(type) {
return this.metrics.filter((m) => m.type === type);
}
/**
* Get metrics within a time range
*/
getMetricsInRange(startTime, endTime) {
return this.metrics.filter((m) => m.timestamp >= startTime && m.timestamp <= endTime);
}
/**
* Calculate statistics for a set of metrics
*/
calculateStats(values) {
if (values.length === 0) {
return {
count: 0,
sum: 0,
min: 0,
max: 0,
avg: 0,
};
}
const sorted = [...values].sort((a, b) => a - b);
const sum = values.reduce((acc, val) => acc + val, 0);
return {
count: values.length,
sum,
min: sorted[0],
max: sorted[sorted.length - 1],
avg: sum / values.length,
p50: sorted[Math.floor(sorted.length * 0.5)],
p95: sorted[Math.floor(sorted.length * 0.95)],
p99: sorted[Math.floor(sorted.length * 0.99)],
};
}
/**
* Get summary statistics for all metrics
*/
getSummary() {
const summary = {};
// Group metrics by type
const metricsByType = new Map();
for (const metric of this.metrics) {
if (!metricsByType.has(metric.type)) {
metricsByType.set(metric.type, []);
}
metricsByType.get(metric.type).push(metric.value);
}
// Calculate stats for each type
for (const [type, values] of metricsByType.entries()) {
summary[type] = this.calculateStats(values);
}
return summary;
}
/**
* Get active session count
*/
getActiveSessionCount() {
return this.sessionStartTimes.size;
}
/**
* Get breakpoint hit count for a specific breakpoint
*/
getBreakpointHitCount(breakpointId) {
return this.breakpointHitCounts.get(breakpointId) || 0;
}
/**
* Get all breakpoint hit counts
*/
getAllBreakpointHitCounts() {
return new Map(this.breakpointHitCounts);
}
/**
* Get error count for a specific error type
*/
getErrorCount(errorType) {
return this.errorCounts.get(errorType) || 0;
}
/**
* Get all error counts
*/
getAllErrorCounts() {
return new Map(this.errorCounts);
}
/**
* Get total error count
*/
getTotalErrorCount() {
let total = 0;
for (const count of this.errorCounts.values()) {
total += count;
}
return total;
}
/**
* Clear all metrics
*/
clearMetrics() {
this.metrics = [];
this.sessionStartTimes.clear();
this.breakpointHitCounts.clear();
this.operationStartTimes.clear();
this.errorCounts.clear();
}
/**
* Export metrics in a format suitable for external monitoring systems
*/
exportMetrics() {
return {
metrics: this.getAllMetrics(),
summary: this.getSummary(),
activeSessionCount: this.getActiveSessionCount(),
breakpointHitCounts: Object.fromEntries(this.breakpointHitCounts),
errorCounts: Object.fromEntries(this.errorCounts),
totalErrors: this.getTotalErrorCount(),
};
}
/**
* Get metrics endpoint data (for HTTP endpoint)
*/
getMetricsEndpointData() {
const data = this.exportMetrics();
return JSON.stringify(data, null, 2);
}
}
exports.MetricsCollector = MetricsCollector;
//# sourceMappingURL=metrics-collector.js.map