fix(security): critical security and stability fixes
This commit is contained in:
@@ -33,6 +33,11 @@ export class MetricsCollector implements IMetrics {
|
||||
private readonly sampleIntervalMs: number;
|
||||
private readonly retentionSeconds: number;
|
||||
|
||||
// Track connection durations for percentile calculations
|
||||
private connectionDurations: number[] = [];
|
||||
private bytesInArray: number[] = [];
|
||||
private bytesOutArray: number[] = [];
|
||||
|
||||
constructor(
|
||||
private smartProxy: SmartProxy,
|
||||
config?: {
|
||||
@@ -211,21 +216,39 @@ export class MetricsCollector implements IMetrics {
|
||||
}
|
||||
};
|
||||
|
||||
// Percentiles implementation (placeholder for now)
|
||||
// Helper to calculate percentiles from an array
|
||||
private calculatePercentile(arr: number[], percentile: number): number {
|
||||
if (arr.length === 0) return 0;
|
||||
const sorted = [...arr].sort((a, b) => a - b);
|
||||
const index = Math.floor((sorted.length - 1) * percentile);
|
||||
return sorted[index];
|
||||
}
|
||||
|
||||
// Percentiles implementation
|
||||
public percentiles = {
|
||||
connectionDuration: (): { p50: number; p95: number; p99: number } => {
|
||||
// TODO: Implement percentile calculations
|
||||
return { p50: 0, p95: 0, p99: 0 };
|
||||
return {
|
||||
p50: this.calculatePercentile(this.connectionDurations, 0.5),
|
||||
p95: this.calculatePercentile(this.connectionDurations, 0.95),
|
||||
p99: this.calculatePercentile(this.connectionDurations, 0.99)
|
||||
};
|
||||
},
|
||||
|
||||
bytesTransferred: (): {
|
||||
in: { p50: number; p95: number; p99: number };
|
||||
out: { p50: number; p95: number; p99: number };
|
||||
} => {
|
||||
// TODO: Implement percentile calculations
|
||||
return {
|
||||
in: { p50: 0, p95: 0, p99: 0 },
|
||||
out: { p50: 0, p95: 0, p99: 0 }
|
||||
in: {
|
||||
p50: this.calculatePercentile(this.bytesInArray, 0.5),
|
||||
p95: this.calculatePercentile(this.bytesInArray, 0.95),
|
||||
p99: this.calculatePercentile(this.bytesInArray, 0.99)
|
||||
},
|
||||
out: {
|
||||
p50: this.calculatePercentile(this.bytesOutArray, 0.5),
|
||||
p95: this.calculatePercentile(this.bytesOutArray, 0.95),
|
||||
p99: this.calculatePercentile(this.bytesOutArray, 0.99)
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -298,6 +321,30 @@ export class MetricsCollector implements IMetrics {
|
||||
* Clean up tracking for a closed connection
|
||||
*/
|
||||
public removeConnection(connectionId: string): void {
|
||||
const tracker = this.connectionByteTrackers.get(connectionId);
|
||||
if (tracker) {
|
||||
// Calculate connection duration
|
||||
const duration = Date.now() - tracker.startTime;
|
||||
|
||||
// Add to arrays for percentile calculations (bounded to prevent memory growth)
|
||||
const MAX_SAMPLES = 5000;
|
||||
|
||||
this.connectionDurations.push(duration);
|
||||
if (this.connectionDurations.length > MAX_SAMPLES) {
|
||||
this.connectionDurations.shift();
|
||||
}
|
||||
|
||||
this.bytesInArray.push(tracker.bytesIn);
|
||||
if (this.bytesInArray.length > MAX_SAMPLES) {
|
||||
this.bytesInArray.shift();
|
||||
}
|
||||
|
||||
this.bytesOutArray.push(tracker.bytesOut);
|
||||
if (this.bytesOutArray.length > MAX_SAMPLES) {
|
||||
this.bytesOutArray.shift();
|
||||
}
|
||||
}
|
||||
|
||||
this.connectionByteTrackers.delete(connectionId);
|
||||
}
|
||||
|
||||
@@ -349,6 +396,11 @@ export class MetricsCollector implements IMetrics {
|
||||
}
|
||||
}, this.sampleIntervalMs);
|
||||
|
||||
// Unref the interval so it doesn't keep the process alive
|
||||
if (this.samplingInterval.unref) {
|
||||
this.samplingInterval.unref();
|
||||
}
|
||||
|
||||
// Subscribe to new connections
|
||||
this.connectionSubscription = this.smartProxy.routeConnectionHandler.newConnectionSubject.subscribe({
|
||||
next: (record) => {
|
||||
|
Reference in New Issue
Block a user