fix(tests): fix tests
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"expiryDate": "2025-09-20T22:26:01.547Z",
|
"expiryDate": "2025-09-20T22:46:46.609Z",
|
||||||
"issueDate": "2025-06-22T22:26:01.547Z",
|
"issueDate": "2025-06-22T22:46:46.609Z",
|
||||||
"savedAt": "2025-06-22T22:26:01.548Z"
|
"savedAt": "2025-06-22T22:46:46.610Z"
|
||||||
}
|
}
|
318
readme.md
318
readme.md
@ -1576,150 +1576,316 @@ Available helper functions:
|
|||||||
|
|
||||||
## Metrics and Monitoring
|
## Metrics and Monitoring
|
||||||
|
|
||||||
SmartProxy includes a comprehensive metrics collection system that provides real-time insights into proxy performance, connection statistics, and throughput data.
|
SmartProxy includes a comprehensive metrics collection system that provides real-time insights into proxy performance, connection statistics, and throughput data. The metrics system uses a clean, grouped API design for intuitive access to different metric categories.
|
||||||
|
|
||||||
|
### Enabling Metrics
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const proxy = new SmartProxy({
|
||||||
|
// Enable metrics collection
|
||||||
|
metrics: {
|
||||||
|
enabled: true,
|
||||||
|
sampleIntervalMs: 1000, // Sample throughput every second
|
||||||
|
retentionSeconds: 3600 // Keep 1 hour of history
|
||||||
|
},
|
||||||
|
routes: [/* your routes */]
|
||||||
|
});
|
||||||
|
|
||||||
|
await proxy.start();
|
||||||
|
```
|
||||||
|
|
||||||
### Getting Metrics
|
### Getting Metrics
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
const proxy = new SmartProxy({ /* config */ });
|
// Access metrics through the getMetrics() method
|
||||||
await proxy.start();
|
const metrics = proxy.getMetrics();
|
||||||
|
|
||||||
// Access metrics through the getStats() method
|
// The metrics object provides grouped methods for different categories
|
||||||
const stats = proxy.getStats();
|
```
|
||||||
|
|
||||||
|
### Connection Metrics
|
||||||
|
|
||||||
|
Monitor active connections, total connections, and connection distribution:
|
||||||
|
|
||||||
|
```typescript
|
||||||
// Get current active connections
|
// Get current active connections
|
||||||
console.log(`Active connections: ${stats.getActiveConnections()}`);
|
console.log(`Active connections: ${metrics.connections.active()}`);
|
||||||
|
|
||||||
// Get total connections since start
|
// Get total connections since start
|
||||||
console.log(`Total connections: ${stats.getTotalConnections()}`);
|
console.log(`Total connections: ${metrics.connections.total()}`);
|
||||||
|
|
||||||
// Get requests per second (RPS)
|
|
||||||
console.log(`Current RPS: ${stats.getRequestsPerSecond()}`);
|
|
||||||
|
|
||||||
// Get throughput data
|
|
||||||
const throughput = stats.getThroughput();
|
|
||||||
console.log(`Bytes received: ${throughput.bytesIn}`);
|
|
||||||
console.log(`Bytes sent: ${throughput.bytesOut}`);
|
|
||||||
|
|
||||||
// Get connections by route
|
// Get connections by route
|
||||||
const routeConnections = stats.getConnectionsByRoute();
|
const routeConnections = metrics.connections.byRoute();
|
||||||
for (const [route, count] of routeConnections) {
|
for (const [route, count] of routeConnections) {
|
||||||
console.log(`Route ${route}: ${count} connections`);
|
console.log(`Route ${route}: ${count} connections`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get connections by IP address
|
// Get connections by IP address
|
||||||
const ipConnections = stats.getConnectionsByIP();
|
const ipConnections = metrics.connections.byIP();
|
||||||
for (const [ip, count] of ipConnections) {
|
for (const [ip, count] of ipConnections) {
|
||||||
console.log(`IP ${ip}: ${count} connections`);
|
console.log(`IP ${ip}: ${count} connections`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get top IPs by connection count
|
||||||
|
const topIPs = metrics.connections.topIPs(10);
|
||||||
|
topIPs.forEach(({ ip, count }) => {
|
||||||
|
console.log(`${ip}: ${count} connections`);
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
### Available Metrics
|
### Throughput Metrics
|
||||||
|
|
||||||
The `IProxyStats` interface provides the following methods:
|
Real-time and historical throughput data with customizable time windows:
|
||||||
|
|
||||||
- `getActiveConnections()`: Current number of active connections
|
|
||||||
- `getTotalConnections()`: Total connections handled since proxy start
|
|
||||||
- `getRequestsPerSecond()`: Current requests per second (1-minute average)
|
|
||||||
- `getThroughput()`: Total bytes transferred (in/out)
|
|
||||||
- `getConnectionsByRoute()`: Connection count per route
|
|
||||||
- `getConnectionsByIP()`: Connection count per client IP
|
|
||||||
|
|
||||||
Additional extended methods available:
|
|
||||||
|
|
||||||
- `getThroughputRate()`: Bytes per second rate for the last minute
|
|
||||||
- `getTopIPs(limit?: number)`: Get top IPs by connection count
|
|
||||||
- `isIPBlocked(ip: string, maxConnectionsPerIP: number)`: Check if an IP has reached the connection limit
|
|
||||||
|
|
||||||
### Extended Metrics Example
|
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
const stats = proxy.getStats() as any; // Extended methods are available
|
// Get instant throughput (last 1 second)
|
||||||
|
const instant = metrics.throughput.instant();
|
||||||
|
console.log(`Current: ${instant.in} bytes/sec in, ${instant.out} bytes/sec out`);
|
||||||
|
|
||||||
// Get throughput rate
|
// Get recent throughput (last 10 seconds average)
|
||||||
const rate = stats.getThroughputRate();
|
const recent = metrics.throughput.recent();
|
||||||
console.log(`Incoming: ${rate.bytesInPerSec} bytes/sec`);
|
console.log(`Recent: ${recent.in} bytes/sec in, ${recent.out} bytes/sec out`);
|
||||||
console.log(`Outgoing: ${rate.bytesOutPerSec} bytes/sec`);
|
|
||||||
|
|
||||||
// Get top 10 IPs by connection count
|
// Get average throughput (last 60 seconds)
|
||||||
const topIPs = stats.getTopIPs(10);
|
const average = metrics.throughput.average();
|
||||||
topIPs.forEach(({ ip, connections }) => {
|
console.log(`Average: ${average.in} bytes/sec in, ${average.out} bytes/sec out`);
|
||||||
console.log(`${ip}: ${connections} connections`);
|
|
||||||
|
// Get custom time window (e.g., last 5 minutes)
|
||||||
|
const custom = metrics.throughput.custom(300);
|
||||||
|
console.log(`5-min avg: ${custom.in} bytes/sec in, ${custom.out} bytes/sec out`);
|
||||||
|
|
||||||
|
// Get throughput history for graphing
|
||||||
|
const history = metrics.throughput.history(300); // Last 5 minutes
|
||||||
|
history.forEach(point => {
|
||||||
|
console.log(`${new Date(point.timestamp)}: ${point.in} in, ${point.out} out`);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check if an IP should be rate limited
|
// Get throughput by route
|
||||||
if (stats.isIPBlocked('192.168.1.100', 100)) {
|
const routeThroughput = metrics.throughput.byRoute(60); // Last 60 seconds
|
||||||
console.log('IP has too many connections');
|
routeThroughput.forEach((stats, route) => {
|
||||||
}
|
console.log(`Route ${route}: ${stats.in} in, ${stats.out} out bytes/sec`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get throughput by IP
|
||||||
|
const ipThroughput = metrics.throughput.byIP(60);
|
||||||
|
ipThroughput.forEach((stats, ip) => {
|
||||||
|
console.log(`IP ${ip}: ${stats.in} in, ${stats.out} out bytes/sec`);
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
### Monitoring Example
|
### Request Metrics
|
||||||
|
|
||||||
|
Track request rates:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// Create a monitoring loop
|
// Get requests per second
|
||||||
|
console.log(`RPS: ${metrics.requests.perSecond()}`);
|
||||||
|
|
||||||
|
// Get requests per minute
|
||||||
|
console.log(`RPM: ${metrics.requests.perMinute()}`);
|
||||||
|
|
||||||
|
// Get total requests
|
||||||
|
console.log(`Total requests: ${metrics.requests.total()}`);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cumulative Totals
|
||||||
|
|
||||||
|
Track total bytes transferred and connections:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Get total bytes
|
||||||
|
console.log(`Total bytes in: ${metrics.totals.bytesIn()}`);
|
||||||
|
console.log(`Total bytes out: ${metrics.totals.bytesOut()}`);
|
||||||
|
console.log(`Total connections: ${metrics.totals.connections()}`);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Performance Percentiles
|
||||||
|
|
||||||
|
Get percentile statistics (when implemented):
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Connection duration percentiles
|
||||||
|
const durations = metrics.percentiles.connectionDuration();
|
||||||
|
console.log(`Connection durations - P50: ${durations.p50}ms, P95: ${durations.p95}ms, P99: ${durations.p99}ms`);
|
||||||
|
|
||||||
|
// Bytes transferred percentiles
|
||||||
|
const bytes = metrics.percentiles.bytesTransferred();
|
||||||
|
console.log(`Bytes in - P50: ${bytes.in.p50}, P95: ${bytes.in.p95}, P99: ${bytes.in.p99}`);
|
||||||
|
console.log(`Bytes out - P50: ${bytes.out.p50}, P95: ${bytes.out.p95}, P99: ${bytes.out.p99}`);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Complete Monitoring Example
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Create a monitoring dashboard
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
const stats = proxy.getStats();
|
const metrics = proxy.getMetrics();
|
||||||
|
|
||||||
// Log key metrics
|
// Log key metrics
|
||||||
console.log({
|
console.log({
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
activeConnections: stats.getActiveConnections(),
|
connections: {
|
||||||
rps: stats.getRequestsPerSecond(),
|
active: metrics.connections.active(),
|
||||||
throughput: stats.getThroughput()
|
total: metrics.connections.total()
|
||||||
|
},
|
||||||
|
throughput: {
|
||||||
|
instant: metrics.throughput.instant(),
|
||||||
|
average: metrics.throughput.average()
|
||||||
|
},
|
||||||
|
requests: {
|
||||||
|
rps: metrics.requests.perSecond(),
|
||||||
|
total: metrics.requests.total()
|
||||||
|
},
|
||||||
|
totals: {
|
||||||
|
bytesIn: metrics.totals.bytesIn(),
|
||||||
|
bytesOut: metrics.totals.bytesOut()
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check for high connection counts from specific IPs
|
// Alert on high connection counts
|
||||||
const ipConnections = stats.getConnectionsByIP();
|
const topIPs = metrics.connections.topIPs(5);
|
||||||
for (const [ip, count] of ipConnections) {
|
topIPs.forEach(({ ip, count }) => {
|
||||||
if (count > 100) {
|
if (count > 100) {
|
||||||
console.warn(`High connection count from ${ip}: ${count}`);
|
console.warn(`High connection count from ${ip}: ${count}`);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Alert on high throughput
|
||||||
|
const instant = metrics.throughput.instant();
|
||||||
|
if (instant.in > 100_000_000) { // 100 MB/s
|
||||||
|
console.warn(`High incoming throughput: ${instant.in} bytes/sec`);
|
||||||
}
|
}
|
||||||
}, 10000); // Every 10 seconds
|
}, 10000); // Every 10 seconds
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exporting Metrics
|
### Exporting Metrics
|
||||||
|
|
||||||
You can export metrics in various formats for external monitoring systems:
|
Export metrics in various formats for external monitoring systems:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// Export as JSON
|
// Export as JSON
|
||||||
app.get('/metrics.json', (req, res) => {
|
app.get('/metrics.json', (req, res) => {
|
||||||
const stats = proxy.getStats();
|
const metrics = proxy.getMetrics();
|
||||||
res.json({
|
res.json({
|
||||||
activeConnections: stats.getActiveConnections(),
|
connections: {
|
||||||
totalConnections: stats.getTotalConnections(),
|
active: metrics.connections.active(),
|
||||||
requestsPerSecond: stats.getRequestsPerSecond(),
|
total: metrics.connections.total(),
|
||||||
throughput: stats.getThroughput(),
|
byRoute: Object.fromEntries(metrics.connections.byRoute()),
|
||||||
connectionsByRoute: Object.fromEntries(stats.getConnectionsByRoute()),
|
byIP: Object.fromEntries(metrics.connections.byIP())
|
||||||
connectionsByIP: Object.fromEntries(stats.getConnectionsByIP())
|
},
|
||||||
|
throughput: {
|
||||||
|
instant: metrics.throughput.instant(),
|
||||||
|
recent: metrics.throughput.recent(),
|
||||||
|
average: metrics.throughput.average()
|
||||||
|
},
|
||||||
|
requests: {
|
||||||
|
perSecond: metrics.requests.perSecond(),
|
||||||
|
perMinute: metrics.requests.perMinute(),
|
||||||
|
total: metrics.requests.total()
|
||||||
|
},
|
||||||
|
totals: {
|
||||||
|
bytesIn: metrics.totals.bytesIn(),
|
||||||
|
bytesOut: metrics.totals.bytesOut(),
|
||||||
|
connections: metrics.totals.connections()
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Export as Prometheus format
|
// Export as Prometheus format
|
||||||
app.get('/metrics', (req, res) => {
|
app.get('/metrics', (req, res) => {
|
||||||
const stats = proxy.getStats();
|
const metrics = proxy.getMetrics();
|
||||||
|
const instant = metrics.throughput.instant();
|
||||||
|
|
||||||
res.set('Content-Type', 'text/plain');
|
res.set('Content-Type', 'text/plain');
|
||||||
res.send(`
|
res.send(`
|
||||||
# HELP smartproxy_active_connections Current active connections
|
# HELP smartproxy_connections_active Current active connections
|
||||||
# TYPE smartproxy_active_connections gauge
|
# TYPE smartproxy_connections_active gauge
|
||||||
smartproxy_active_connections ${stats.getActiveConnections()}
|
smartproxy_connections_active ${metrics.connections.active()}
|
||||||
|
|
||||||
|
# HELP smartproxy_connections_total Total connections since start
|
||||||
|
# TYPE smartproxy_connections_total counter
|
||||||
|
smartproxy_connections_total ${metrics.connections.total()}
|
||||||
|
|
||||||
|
# HELP smartproxy_throughput_bytes_per_second Current throughput in bytes per second
|
||||||
|
# TYPE smartproxy_throughput_bytes_per_second gauge
|
||||||
|
smartproxy_throughput_bytes_per_second{direction="in"} ${instant.in}
|
||||||
|
smartproxy_throughput_bytes_per_second{direction="out"} ${instant.out}
|
||||||
|
|
||||||
# HELP smartproxy_requests_per_second Current requests per second
|
# HELP smartproxy_requests_per_second Current requests per second
|
||||||
# TYPE smartproxy_requests_per_second gauge
|
# TYPE smartproxy_requests_per_second gauge
|
||||||
smartproxy_requests_per_second ${stats.getRequestsPerSecond()}
|
smartproxy_requests_per_second ${metrics.requests.perSecond()}
|
||||||
|
|
||||||
# HELP smartproxy_bytes_in Total bytes received
|
# HELP smartproxy_bytes_total Total bytes transferred
|
||||||
# TYPE smartproxy_bytes_in counter
|
# TYPE smartproxy_bytes_total counter
|
||||||
smartproxy_bytes_in ${stats.getThroughput().bytesIn}
|
smartproxy_bytes_total{direction="in"} ${metrics.totals.bytesIn()}
|
||||||
|
smartproxy_bytes_total{direction="out"} ${metrics.totals.bytesOut()}
|
||||||
# HELP smartproxy_bytes_out Total bytes sent
|
|
||||||
# TYPE smartproxy_bytes_out counter
|
|
||||||
smartproxy_bytes_out ${stats.getThroughput().bytesOut}
|
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Metrics API Reference
|
||||||
|
|
||||||
|
The metrics API is organized into logical groups:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface IMetrics {
|
||||||
|
connections: {
|
||||||
|
active(): number;
|
||||||
|
total(): number;
|
||||||
|
byRoute(): Map<string, number>;
|
||||||
|
byIP(): Map<string, number>;
|
||||||
|
topIPs(limit?: number): Array<{ ip: string; count: number }>;
|
||||||
|
};
|
||||||
|
|
||||||
|
throughput: {
|
||||||
|
instant(): IThroughputData; // Last 1 second
|
||||||
|
recent(): IThroughputData; // Last 10 seconds
|
||||||
|
average(): IThroughputData; // Last 60 seconds
|
||||||
|
custom(seconds: number): IThroughputData;
|
||||||
|
history(seconds: number): Array<IThroughputHistoryPoint>;
|
||||||
|
byRoute(windowSeconds?: number): Map<string, IThroughputData>;
|
||||||
|
byIP(windowSeconds?: number): Map<string, IThroughputData>;
|
||||||
|
};
|
||||||
|
|
||||||
|
requests: {
|
||||||
|
perSecond(): number;
|
||||||
|
perMinute(): number;
|
||||||
|
total(): number;
|
||||||
|
};
|
||||||
|
|
||||||
|
totals: {
|
||||||
|
bytesIn(): number;
|
||||||
|
bytesOut(): number;
|
||||||
|
connections(): number;
|
||||||
|
};
|
||||||
|
|
||||||
|
percentiles: {
|
||||||
|
connectionDuration(): { p50: number; p95: number; p99: number };
|
||||||
|
bytesTransferred(): {
|
||||||
|
in: { p50: number; p95: number; p99: number };
|
||||||
|
out: { p50: number; p95: number; p99: number };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Where `IThroughputData` is:
|
||||||
|
```typescript
|
||||||
|
interface IThroughputData {
|
||||||
|
in: number; // Bytes per second incoming
|
||||||
|
out: number; // Bytes per second outgoing
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
And `IThroughputHistoryPoint` is:
|
||||||
|
```typescript
|
||||||
|
interface IThroughputHistoryPoint {
|
||||||
|
timestamp: number; // Unix timestamp in milliseconds
|
||||||
|
in: number; // Bytes per second at this point
|
||||||
|
out: number; // Bytes per second at this point
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Other Components
|
## Other Components
|
||||||
|
|
||||||
While SmartProxy provides a unified API for most needs, you can also use individual components:
|
While SmartProxy provides a unified API for most needs, you can also use individual components:
|
||||||
|
@ -311,11 +311,17 @@ smartproxy_connection_duration_seconds_count 850
|
|||||||
- Provide clear migration guide in documentation
|
- Provide clear migration guide in documentation
|
||||||
|
|
||||||
### Implementation Approach
|
### Implementation Approach
|
||||||
1. Create new `ThroughputTracker` class for time-series data
|
1. ✅ Create new `ThroughputTracker` class for time-series data
|
||||||
2. Implement new `IMetrics` interface with clean API
|
2. ✅ Implement new `IMetrics` interface with clean API
|
||||||
3. Replace `MetricsCollector` implementation entirely
|
3. ✅ Replace `MetricsCollector` implementation entirely
|
||||||
4. Update all references to use new API
|
4. ✅ Update all references to use new API
|
||||||
5. Add comprehensive tests for accuracy validation
|
5. ⚠️ Add comprehensive tests for accuracy validation (partial)
|
||||||
|
|
||||||
|
### Additional Refactoring Completed
|
||||||
|
- Refactored all SmartProxy components to use cleaner dependency pattern
|
||||||
|
- Components now receive only `SmartProxy` instance instead of individual dependencies
|
||||||
|
- Access to other components via `this.smartProxy.componentName`
|
||||||
|
- Significantly simplified constructor signatures across the codebase
|
||||||
|
|
||||||
## 9. Success Metrics
|
## 9. Success Metrics
|
||||||
|
|
||||||
|
@ -30,10 +30,27 @@ tap.test('cleanup queue bug - verify queue processing handles more than batch si
|
|||||||
const mockConnections: any[] = [];
|
const mockConnections: any[] = [];
|
||||||
|
|
||||||
for (let i = 0; i < 150; i++) {
|
for (let i = 0; i < 150; i++) {
|
||||||
|
// Create mock socket objects with necessary methods
|
||||||
|
const mockIncoming = {
|
||||||
|
destroyed: true,
|
||||||
|
writable: false,
|
||||||
|
remoteAddress: '127.0.0.1',
|
||||||
|
removeAllListeners: () => {},
|
||||||
|
destroy: () => {},
|
||||||
|
end: () => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockOutgoing = {
|
||||||
|
destroyed: true,
|
||||||
|
writable: false,
|
||||||
|
destroy: () => {},
|
||||||
|
end: () => {}
|
||||||
|
};
|
||||||
|
|
||||||
const mockRecord = {
|
const mockRecord = {
|
||||||
id: `mock-${i}`,
|
id: `mock-${i}`,
|
||||||
incoming: { destroyed: true, remoteAddress: '127.0.0.1' },
|
incoming: mockIncoming,
|
||||||
outgoing: { destroyed: true },
|
outgoing: mockOutgoing,
|
||||||
connectionClosed: false,
|
connectionClosed: false,
|
||||||
incomingStartTime: Date.now(),
|
incomingStartTime: Date.now(),
|
||||||
lastActivity: Date.now(),
|
lastActivity: Date.now(),
|
||||||
@ -66,9 +83,17 @@ tap.test('cleanup queue bug - verify queue processing handles more than batch si
|
|||||||
// Wait for cleanup to complete
|
// Wait for cleanup to complete
|
||||||
console.log('\n--- Waiting for cleanup batches to process ---');
|
console.log('\n--- Waiting for cleanup batches to process ---');
|
||||||
|
|
||||||
// The first batch should process immediately (100 connections)
|
// The cleanup happens in batches, wait for all to complete
|
||||||
// Then additional batches should be scheduled
|
let waitTime = 0;
|
||||||
await new Promise(resolve => setTimeout(resolve, 500));
|
while (cm.getConnectionCount() > 0 || cm.cleanupQueue.size > 0) {
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 100));
|
||||||
|
waitTime += 100;
|
||||||
|
if (waitTime > 5000) {
|
||||||
|
console.log('Timeout waiting for cleanup to complete');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(`Cleanup completed in ${waitTime}ms`);
|
||||||
|
|
||||||
// Check final state
|
// Check final state
|
||||||
const finalCount = cm.getConnectionCount();
|
const finalCount = cm.getConnectionCount();
|
||||||
@ -85,6 +110,7 @@ tap.test('cleanup queue bug - verify queue processing handles more than batch si
|
|||||||
expect(stats.incoming.test_cleanup).toEqual(150);
|
expect(stats.incoming.test_cleanup).toEqual(150);
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
|
console.log('\n--- Stopping proxy ---');
|
||||||
await proxy.stop();
|
await proxy.stop();
|
||||||
|
|
||||||
console.log('\n✓ Test complete: Cleanup queue now correctly processes all connections');
|
console.log('\n✓ Test complete: Cleanup queue now correctly processes all connections');
|
||||||
|
@ -105,6 +105,13 @@ export interface ISmartProxyOptions {
|
|||||||
useHttpProxy?: number[]; // Array of ports to forward to HttpProxy
|
useHttpProxy?: number[]; // Array of ports to forward to HttpProxy
|
||||||
httpProxyPort?: number; // Port where HttpProxy is listening (default: 8443)
|
httpProxyPort?: number; // Port where HttpProxy is listening (default: 8443)
|
||||||
|
|
||||||
|
// Metrics configuration
|
||||||
|
metrics?: {
|
||||||
|
enabled?: boolean;
|
||||||
|
sampleIntervalMs?: number;
|
||||||
|
retentionSeconds?: number;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global ACME configuration options for SmartProxy
|
* Global ACME configuration options for SmartProxy
|
||||||
*
|
*
|
||||||
|
@ -201,7 +201,10 @@ export class SmartProxy extends plugins.EventEmitter {
|
|||||||
this.acmeStateManager = new AcmeStateManager();
|
this.acmeStateManager = new AcmeStateManager();
|
||||||
|
|
||||||
// Initialize metrics collector with reference to this SmartProxy instance
|
// Initialize metrics collector with reference to this SmartProxy instance
|
||||||
this.metricsCollector = new MetricsCollector(this);
|
this.metricsCollector = new MetricsCollector(this, {
|
||||||
|
sampleIntervalMs: this.settings.metrics?.sampleIntervalMs,
|
||||||
|
retentionSeconds: this.settings.metrics?.retentionSeconds
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user