@push.rocks/smartproxy 19.5.26 → 19.6.0
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/dist_ts/plugins.d.ts +2 -1
- package/dist_ts/plugins.js +3 -2
- package/dist_ts/proxies/smart-proxy/metrics-collector.d.ts +79 -0
- package/dist_ts/proxies/smart-proxy/metrics-collector.js +235 -0
- package/dist_ts/proxies/smart-proxy/models/index.d.ts +1 -0
- package/dist_ts/proxies/smart-proxy/models/index.js +2 -1
- package/dist_ts/proxies/smart-proxy/models/metrics-types.d.ts +55 -0
- package/dist_ts/proxies/smart-proxy/models/metrics-types.js +2 -0
- package/dist_ts/proxies/smart-proxy/route-connection-handler.d.ts +2 -1
- package/dist_ts/proxies/smart-proxy/route-connection-handler.js +9 -1
- package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +12 -2
- package/dist_ts/proxies/smart-proxy/smart-proxy.js +17 -1
- package/package.json +18 -8
- package/readme.md +118 -0
- package/readme.metrics.md +591 -0
- package/ts/plugins.ts +2 -0
- package/ts/proxies/smart-proxy/metrics-collector.ts +285 -0
- package/ts/proxies/smart-proxy/models/index.ts +1 -0
- package/ts/proxies/smart-proxy/models/metrics-types.ts +54 -0
- package/ts/proxies/smart-proxy/route-connection-handler.ts +13 -0
- package/ts/proxies/smart-proxy/smart-proxy.ts +27 -2
package/dist_ts/plugins.d.ts
CHANGED
|
@@ -23,7 +23,8 @@ import * as smartacmeHandlers from '@push.rocks/smartacme/dist_ts/handlers/index
|
|
|
23
23
|
import * as smartlog from '@push.rocks/smartlog';
|
|
24
24
|
import * as smartlogDestinationLocal from '@push.rocks/smartlog/destination-local';
|
|
25
25
|
import * as taskbuffer from '@push.rocks/taskbuffer';
|
|
26
|
-
|
|
26
|
+
import * as smartrx from '@push.rocks/smartrx';
|
|
27
|
+
export { lik, smartdelay, smartrequest, smartpromise, smartstring, smartfile, smartcrypto, smartacme, smartacmePlugins, smartacmeHandlers, smartlog, smartlogDestinationLocal, taskbuffer, smartrx, };
|
|
27
28
|
import prettyMs from 'pretty-ms';
|
|
28
29
|
import * as ws from 'ws';
|
|
29
30
|
import wsDefault from 'ws';
|
package/dist_ts/plugins.js
CHANGED
|
@@ -26,11 +26,12 @@ import * as smartacmeHandlers from '@push.rocks/smartacme/dist_ts/handlers/index
|
|
|
26
26
|
import * as smartlog from '@push.rocks/smartlog';
|
|
27
27
|
import * as smartlogDestinationLocal from '@push.rocks/smartlog/destination-local';
|
|
28
28
|
import * as taskbuffer from '@push.rocks/taskbuffer';
|
|
29
|
-
|
|
29
|
+
import * as smartrx from '@push.rocks/smartrx';
|
|
30
|
+
export { lik, smartdelay, smartrequest, smartpromise, smartstring, smartfile, smartcrypto, smartacme, smartacmePlugins, smartacmeHandlers, smartlog, smartlogDestinationLocal, taskbuffer, smartrx, };
|
|
30
31
|
// third party scope
|
|
31
32
|
import prettyMs from 'pretty-ms';
|
|
32
33
|
import * as ws from 'ws';
|
|
33
34
|
import wsDefault from 'ws';
|
|
34
35
|
import { minimatch } from 'minimatch';
|
|
35
36
|
export { prettyMs, ws, wsDefault, minimatch };
|
|
36
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
37
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsb0JBQW9CO0FBQ3BCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFDdEMsT0FBTyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDekIsT0FBTyxLQUFLLElBQUksTUFBTSxNQUFNLENBQUM7QUFDN0IsT0FBTyxLQUFLLEtBQUssTUFBTSxPQUFPLENBQUM7QUFDL0IsT0FBTyxLQUFLLEdBQUcsTUFBTSxLQUFLLENBQUM7QUFDM0IsT0FBTyxLQUFLLElBQUksTUFBTSxNQUFNLENBQUM7QUFDN0IsT0FBTyxLQUFLLEdBQUcsTUFBTSxLQUFLLENBQUM7QUFDM0IsT0FBTyxLQUFLLEdBQUcsTUFBTSxLQUFLLENBQUM7QUFDM0IsT0FBTyxLQUFLLEtBQUssTUFBTSxPQUFPLENBQUM7QUFFL0IsT0FBTyxFQUFFLFlBQVksRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLENBQUM7QUFFckUsZ0JBQWdCO0FBQ2hCLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFFNUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxDQUFDO0FBRW5CLGtCQUFrQjtBQUNsQixPQUFPLEtBQUssR0FBRyxNQUFNLGlCQUFpQixDQUFDO0FBQ3ZDLE9BQU8sS0FBSyxVQUFVLE1BQU0sd0JBQXdCLENBQUM7QUFDckQsT0FBTyxLQUFLLFlBQVksTUFBTSwwQkFBMEIsQ0FBQztBQUN6RCxPQUFPLEtBQUssWUFBWSxNQUFNLDBCQUEwQixDQUFDO0FBQ3pELE9BQU8sS0FBSyxXQUFXLE1BQU0seUJBQXlCLENBQUM7QUFDdkQsT0FBTyxLQUFLLFNBQVMsTUFBTSx1QkFBdUIsQ0FBQztBQUNuRCxPQUFPLEtBQUssV0FBVyxNQUFNLHlCQUF5QixDQUFDO0FBQ3ZELE9BQU8sS0FBSyxTQUFTLE1BQU0sdUJBQXVCLENBQUM7QUFDbkQsT0FBTyxLQUFLLGdCQUFnQixNQUFNLG9EQUFvRCxDQUFDO0FBQ3ZGLE9BQU8sS0FBSyxpQkFBaUIsTUFBTSxpREFBaUQsQ0FBQztBQUNyRixPQUFPLEtBQUssUUFBUSxNQUFNLHNCQUFzQixDQUFDO0FBQ2pELE9BQU8sS0FBSyx3QkFBd0IsTUFBTSx3Q0FBd0MsQ0FBQztBQUNuRixPQUFPLEtBQUssVUFBVSxNQUFNLHdCQUF3QixDQUFDO0FBQ3JELE9BQU8sS0FBSyxPQUFPLE1BQU0scUJBQXFCLENBQUM7QUFFL0MsT0FBTyxFQUNMLEdBQUcsRUFDSCxVQUFVLEVBQ1YsWUFBWSxFQUNaLFlBQVksRUFDWixXQUFXLEVBQ1gsU0FBUyxFQUNULFdBQVcsRUFDWCxTQUFTLEVBQ1QsZ0JBQWdCLEVBQ2hCLGlCQUFpQixFQUNqQixRQUFRLEVBQ1Isd0JBQXdCLEVBQ3hCLFVBQVUsRUFDVixPQUFPLEdBQ1IsQ0FBQztBQUVGLG9CQUFvQjtBQUNwQixPQUFPLFFBQVEsTUFBTSxXQUFXLENBQUM7QUFDakMsT0FBTyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDekIsT0FBTyxTQUFTLE1BQU0sSUFBSSxDQUFDO0FBQzNCLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFdEMsT0FBTyxFQUFFLFFBQVEsRUFBRSxFQUFFLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxDQUFDIn0=
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { SmartProxy } from './smart-proxy.js';
|
|
2
|
+
import type { IProxyStatsExtended } from './models/metrics-types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Collects and computes metrics for SmartProxy on-demand
|
|
5
|
+
*/
|
|
6
|
+
export declare class MetricsCollector implements IProxyStatsExtended {
|
|
7
|
+
private smartProxy;
|
|
8
|
+
private requestTimestamps;
|
|
9
|
+
private readonly RPS_WINDOW_SIZE;
|
|
10
|
+
private cachedMetrics;
|
|
11
|
+
private readonly CACHE_TTL;
|
|
12
|
+
private connectionSubscription?;
|
|
13
|
+
constructor(smartProxy: SmartProxy);
|
|
14
|
+
/**
|
|
15
|
+
* Get the current number of active connections
|
|
16
|
+
*/
|
|
17
|
+
getActiveConnections(): number;
|
|
18
|
+
/**
|
|
19
|
+
* Get connection counts grouped by route name
|
|
20
|
+
*/
|
|
21
|
+
getConnectionsByRoute(): Map<string, number>;
|
|
22
|
+
/**
|
|
23
|
+
* Get connection counts grouped by IP address
|
|
24
|
+
*/
|
|
25
|
+
getConnectionsByIP(): Map<string, number>;
|
|
26
|
+
/**
|
|
27
|
+
* Get the total number of connections since proxy start
|
|
28
|
+
*/
|
|
29
|
+
getTotalConnections(): number;
|
|
30
|
+
/**
|
|
31
|
+
* Get the current requests per second rate
|
|
32
|
+
*/
|
|
33
|
+
getRequestsPerSecond(): number;
|
|
34
|
+
/**
|
|
35
|
+
* Record a new request for RPS tracking
|
|
36
|
+
*/
|
|
37
|
+
recordRequest(): void;
|
|
38
|
+
/**
|
|
39
|
+
* Get total throughput (bytes transferred)
|
|
40
|
+
*/
|
|
41
|
+
getThroughput(): {
|
|
42
|
+
bytesIn: number;
|
|
43
|
+
bytesOut: number;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Get throughput rate (bytes per second) for last minute
|
|
47
|
+
*/
|
|
48
|
+
getThroughputRate(): {
|
|
49
|
+
bytesInPerSec: number;
|
|
50
|
+
bytesOutPerSec: number;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Get top IPs by connection count
|
|
54
|
+
*/
|
|
55
|
+
getTopIPs(limit?: number): Array<{
|
|
56
|
+
ip: string;
|
|
57
|
+
connections: number;
|
|
58
|
+
}>;
|
|
59
|
+
/**
|
|
60
|
+
* Check if an IP has reached the connection limit
|
|
61
|
+
*/
|
|
62
|
+
isIPBlocked(ip: string, maxConnectionsPerIP: number): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Clean up old request timestamps
|
|
65
|
+
*/
|
|
66
|
+
private cleanupOldRequests;
|
|
67
|
+
/**
|
|
68
|
+
* Start the metrics collector and set up subscriptions
|
|
69
|
+
*/
|
|
70
|
+
start(): void;
|
|
71
|
+
/**
|
|
72
|
+
* Stop the metrics collector and clean up resources
|
|
73
|
+
*/
|
|
74
|
+
stop(): void;
|
|
75
|
+
/**
|
|
76
|
+
* Alias for stop() for backward compatibility
|
|
77
|
+
*/
|
|
78
|
+
destroy(): void;
|
|
79
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import { logger } from '../../core/utils/logger.js';
|
|
3
|
+
/**
|
|
4
|
+
* Collects and computes metrics for SmartProxy on-demand
|
|
5
|
+
*/
|
|
6
|
+
export class MetricsCollector {
|
|
7
|
+
constructor(smartProxy) {
|
|
8
|
+
this.smartProxy = smartProxy;
|
|
9
|
+
// RPS tracking (the only state we need to maintain)
|
|
10
|
+
this.requestTimestamps = [];
|
|
11
|
+
this.RPS_WINDOW_SIZE = 60000; // 1 minute window
|
|
12
|
+
// Optional caching for performance
|
|
13
|
+
this.cachedMetrics = { timestamp: 0 };
|
|
14
|
+
this.CACHE_TTL = 1000; // 1 second cache
|
|
15
|
+
// Subscription will be set up in start() method
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Get the current number of active connections
|
|
19
|
+
*/
|
|
20
|
+
getActiveConnections() {
|
|
21
|
+
return this.smartProxy.connectionManager.getConnectionCount();
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get connection counts grouped by route name
|
|
25
|
+
*/
|
|
26
|
+
getConnectionsByRoute() {
|
|
27
|
+
const now = Date.now();
|
|
28
|
+
// Return cached value if fresh
|
|
29
|
+
if (this.cachedMetrics.connectionsByRoute &&
|
|
30
|
+
now - this.cachedMetrics.timestamp < this.CACHE_TTL) {
|
|
31
|
+
return new Map(this.cachedMetrics.connectionsByRoute);
|
|
32
|
+
}
|
|
33
|
+
// Compute fresh value
|
|
34
|
+
const routeCounts = new Map();
|
|
35
|
+
const connections = this.smartProxy.connectionManager.getConnections();
|
|
36
|
+
if (this.smartProxy.settings?.enableDetailedLogging) {
|
|
37
|
+
logger.log('debug', `MetricsCollector: Computing route connections`, {
|
|
38
|
+
totalConnections: connections.size,
|
|
39
|
+
component: 'metrics'
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
for (const [_, record] of connections) {
|
|
43
|
+
// Try different ways to get the route name
|
|
44
|
+
const routeName = record.routeName ||
|
|
45
|
+
record.routeConfig?.name ||
|
|
46
|
+
record.routeConfig?.routeName ||
|
|
47
|
+
'unknown';
|
|
48
|
+
if (this.smartProxy.settings?.enableDetailedLogging) {
|
|
49
|
+
logger.log('debug', `MetricsCollector: Connection route info`, {
|
|
50
|
+
connectionId: record.id,
|
|
51
|
+
routeName,
|
|
52
|
+
hasRouteConfig: !!record.routeConfig,
|
|
53
|
+
routeConfigName: record.routeConfig?.name,
|
|
54
|
+
routeConfigKeys: record.routeConfig ? Object.keys(record.routeConfig) : [],
|
|
55
|
+
component: 'metrics'
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const current = routeCounts.get(routeName) || 0;
|
|
59
|
+
routeCounts.set(routeName, current + 1);
|
|
60
|
+
}
|
|
61
|
+
// Cache and return
|
|
62
|
+
this.cachedMetrics.connectionsByRoute = routeCounts;
|
|
63
|
+
this.cachedMetrics.timestamp = now;
|
|
64
|
+
return new Map(routeCounts);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get connection counts grouped by IP address
|
|
68
|
+
*/
|
|
69
|
+
getConnectionsByIP() {
|
|
70
|
+
const now = Date.now();
|
|
71
|
+
// Return cached value if fresh
|
|
72
|
+
if (this.cachedMetrics.connectionsByIP &&
|
|
73
|
+
now - this.cachedMetrics.timestamp < this.CACHE_TTL) {
|
|
74
|
+
return new Map(this.cachedMetrics.connectionsByIP);
|
|
75
|
+
}
|
|
76
|
+
// Compute fresh value
|
|
77
|
+
const ipCounts = new Map();
|
|
78
|
+
for (const [_, record] of this.smartProxy.connectionManager.getConnections()) {
|
|
79
|
+
const ip = record.remoteIP;
|
|
80
|
+
const current = ipCounts.get(ip) || 0;
|
|
81
|
+
ipCounts.set(ip, current + 1);
|
|
82
|
+
}
|
|
83
|
+
// Cache and return
|
|
84
|
+
this.cachedMetrics.connectionsByIP = ipCounts;
|
|
85
|
+
this.cachedMetrics.timestamp = now;
|
|
86
|
+
return new Map(ipCounts);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get the total number of connections since proxy start
|
|
90
|
+
*/
|
|
91
|
+
getTotalConnections() {
|
|
92
|
+
// Get from termination stats
|
|
93
|
+
const stats = this.smartProxy.connectionManager.getTerminationStats();
|
|
94
|
+
let total = this.smartProxy.connectionManager.getConnectionCount(); // Add active connections
|
|
95
|
+
// Add all terminated connections
|
|
96
|
+
for (const reason in stats.incoming) {
|
|
97
|
+
total += stats.incoming[reason];
|
|
98
|
+
}
|
|
99
|
+
return total;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get the current requests per second rate
|
|
103
|
+
*/
|
|
104
|
+
getRequestsPerSecond() {
|
|
105
|
+
const now = Date.now();
|
|
106
|
+
const windowStart = now - this.RPS_WINDOW_SIZE;
|
|
107
|
+
// Clean old timestamps
|
|
108
|
+
this.requestTimestamps = this.requestTimestamps.filter(ts => ts > windowStart);
|
|
109
|
+
// Calculate RPS based on window
|
|
110
|
+
const requestsInWindow = this.requestTimestamps.length;
|
|
111
|
+
return requestsInWindow / (this.RPS_WINDOW_SIZE / 1000);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Record a new request for RPS tracking
|
|
115
|
+
*/
|
|
116
|
+
recordRequest() {
|
|
117
|
+
this.requestTimestamps.push(Date.now());
|
|
118
|
+
// Prevent unbounded growth
|
|
119
|
+
if (this.requestTimestamps.length > 10000) {
|
|
120
|
+
this.cleanupOldRequests();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Get total throughput (bytes transferred)
|
|
125
|
+
*/
|
|
126
|
+
getThroughput() {
|
|
127
|
+
let bytesIn = 0;
|
|
128
|
+
let bytesOut = 0;
|
|
129
|
+
// Sum bytes from all active connections
|
|
130
|
+
for (const [_, record] of this.smartProxy.connectionManager.getConnections()) {
|
|
131
|
+
bytesIn += record.bytesReceived;
|
|
132
|
+
bytesOut += record.bytesSent;
|
|
133
|
+
}
|
|
134
|
+
return { bytesIn, bytesOut };
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Get throughput rate (bytes per second) for last minute
|
|
138
|
+
*/
|
|
139
|
+
getThroughputRate() {
|
|
140
|
+
const now = Date.now();
|
|
141
|
+
let recentBytesIn = 0;
|
|
142
|
+
let recentBytesOut = 0;
|
|
143
|
+
// Calculate bytes transferred in last minute from active connections
|
|
144
|
+
for (const [_, record] of this.smartProxy.connectionManager.getConnections()) {
|
|
145
|
+
const connectionAge = now - record.incomingStartTime;
|
|
146
|
+
if (connectionAge < 60000) { // Connection started within last minute
|
|
147
|
+
recentBytesIn += record.bytesReceived;
|
|
148
|
+
recentBytesOut += record.bytesSent;
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
// For older connections, estimate rate based on average
|
|
152
|
+
const rate = connectionAge / 60000;
|
|
153
|
+
recentBytesIn += record.bytesReceived / rate;
|
|
154
|
+
recentBytesOut += record.bytesSent / rate;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
bytesInPerSec: Math.round(recentBytesIn / 60),
|
|
159
|
+
bytesOutPerSec: Math.round(recentBytesOut / 60)
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Get top IPs by connection count
|
|
164
|
+
*/
|
|
165
|
+
getTopIPs(limit = 10) {
|
|
166
|
+
const ipCounts = this.getConnectionsByIP();
|
|
167
|
+
const sorted = Array.from(ipCounts.entries())
|
|
168
|
+
.sort((a, b) => b[1] - a[1])
|
|
169
|
+
.slice(0, limit)
|
|
170
|
+
.map(([ip, connections]) => ({ ip, connections }));
|
|
171
|
+
return sorted;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Check if an IP has reached the connection limit
|
|
175
|
+
*/
|
|
176
|
+
isIPBlocked(ip, maxConnectionsPerIP) {
|
|
177
|
+
const ipCounts = this.getConnectionsByIP();
|
|
178
|
+
const currentConnections = ipCounts.get(ip) || 0;
|
|
179
|
+
return currentConnections >= maxConnectionsPerIP;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Clean up old request timestamps
|
|
183
|
+
*/
|
|
184
|
+
cleanupOldRequests() {
|
|
185
|
+
const cutoff = Date.now() - this.RPS_WINDOW_SIZE;
|
|
186
|
+
this.requestTimestamps = this.requestTimestamps.filter(ts => ts > cutoff);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Start the metrics collector and set up subscriptions
|
|
190
|
+
*/
|
|
191
|
+
start() {
|
|
192
|
+
if (!this.smartProxy.routeConnectionHandler) {
|
|
193
|
+
throw new Error('MetricsCollector: RouteConnectionHandler not available');
|
|
194
|
+
}
|
|
195
|
+
// Subscribe to the newConnectionSubject from RouteConnectionHandler
|
|
196
|
+
this.connectionSubscription = this.smartProxy.routeConnectionHandler.newConnectionSubject.subscribe({
|
|
197
|
+
next: (record) => {
|
|
198
|
+
this.recordRequest();
|
|
199
|
+
// Optional: Log connection details
|
|
200
|
+
if (this.smartProxy.settings?.enableDetailedLogging) {
|
|
201
|
+
logger.log('debug', `MetricsCollector: New connection recorded`, {
|
|
202
|
+
connectionId: record.id,
|
|
203
|
+
remoteIP: record.remoteIP,
|
|
204
|
+
routeName: record.routeConfig?.name || 'unknown',
|
|
205
|
+
component: 'metrics'
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
error: (err) => {
|
|
210
|
+
logger.log('error', `MetricsCollector: Error in connection subscription`, {
|
|
211
|
+
error: err.message,
|
|
212
|
+
component: 'metrics'
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
logger.log('debug', 'MetricsCollector started', { component: 'metrics' });
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Stop the metrics collector and clean up resources
|
|
220
|
+
*/
|
|
221
|
+
stop() {
|
|
222
|
+
if (this.connectionSubscription) {
|
|
223
|
+
this.connectionSubscription.unsubscribe();
|
|
224
|
+
this.connectionSubscription = undefined;
|
|
225
|
+
}
|
|
226
|
+
logger.log('debug', 'MetricsCollector stopped', { component: 'metrics' });
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Alias for stop() for backward compatibility
|
|
230
|
+
*/
|
|
231
|
+
destroy() {
|
|
232
|
+
this.stop();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy1jb2xsZWN0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9wcm94aWVzL3NtYXJ0LXByb3h5L21ldHJpY3MtY29sbGVjdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFHNUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRXBEOztHQUVHO0FBQ0gsTUFBTSxPQUFPLGdCQUFnQjtJQWlCM0IsWUFDVSxVQUFzQjtRQUF0QixlQUFVLEdBQVYsVUFBVSxDQUFZO1FBakJoQyxvREFBb0Q7UUFDNUMsc0JBQWlCLEdBQWEsRUFBRSxDQUFDO1FBQ3hCLG9CQUFlLEdBQUcsS0FBSyxDQUFDLENBQUMsa0JBQWtCO1FBRTVELG1DQUFtQztRQUMzQixrQkFBYSxHQUlqQixFQUFFLFNBQVMsRUFBRSxDQUFDLEVBQUUsQ0FBQztRQUVKLGNBQVMsR0FBRyxJQUFJLENBQUMsQ0FBQyxpQkFBaUI7UUFRbEQsZ0RBQWdEO0lBQ2xELENBQUM7SUFFRDs7T0FFRztJQUNJLG9CQUFvQjtRQUN6QixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsaUJBQWlCLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztJQUNoRSxDQUFDO0lBRUQ7O09BRUc7SUFDSSxxQkFBcUI7UUFDMUIsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBRXZCLCtCQUErQjtRQUMvQixJQUFJLElBQUksQ0FBQyxhQUFhLENBQUMsa0JBQWtCO1lBQ3JDLEdBQUcsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDeEQsT0FBTyxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFDeEQsQ0FBQztRQUVELHNCQUFzQjtRQUN0QixNQUFNLFdBQVcsR0FBRyxJQUFJLEdBQUcsRUFBa0IsQ0FBQztRQUM5QyxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLGlCQUFpQixDQUFDLGNBQWMsRUFBRSxDQUFDO1FBRXZFLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUUscUJBQXFCLEVBQUUsQ0FBQztZQUNwRCxNQUFNLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSwrQ0FBK0MsRUFBRTtnQkFDbkUsZ0JBQWdCLEVBQUUsV0FBVyxDQUFDLElBQUk7Z0JBQ2xDLFNBQVMsRUFBRSxTQUFTO2FBQ3JCLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxLQUFLLE1BQU0sQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLElBQUksV0FBVyxFQUFFLENBQUM7WUFDdEMsMkNBQTJDO1lBQzNDLE1BQU0sU0FBUyxHQUFJLE1BQWMsQ0FBQyxTQUFTO2dCQUMxQixNQUFNLENBQUMsV0FBVyxFQUFFLElBQUk7Z0JBQ3ZCLE1BQU0sQ0FBQyxXQUFtQixFQUFFLFNBQVM7Z0JBQ3RDLFNBQVMsQ0FBQztZQUUzQixJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLHFCQUFxQixFQUFFLENBQUM7Z0JBQ3BELE1BQU0sQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLHlDQUF5QyxFQUFFO29CQUM3RCxZQUFZLEVBQUUsTUFBTSxDQUFDLEVBQUU7b0JBQ3ZCLFNBQVM7b0JBQ1QsY0FBYyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsV0FBVztvQkFDcEMsZUFBZSxFQUFFLE1BQU0sQ0FBQyxXQUFXLEVBQUUsSUFBSTtvQkFDekMsZUFBZSxFQUFFLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO29CQUMxRSxTQUFTLEVBQUUsU0FBUztpQkFDckIsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztZQUVELE1BQU0sT0FBTyxHQUFHLFdBQVcsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2hELFdBQVcsQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLE9BQU8sR0FBRyxDQUFDLENBQUMsQ0FBQztRQUMxQyxDQUFDO1FBRUQsbUJBQW1CO1FBQ25CLElBQUksQ0FBQyxhQUFhLENBQUMsa0JBQWtCLEdBQUcsV0FBVyxDQUFDO1FBQ3BELElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxHQUFHLEdBQUcsQ0FBQztRQUNuQyxPQUFPLElBQUksR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQzlCLENBQUM7SUFFRDs7T0FFRztJQUNJLGtCQUFrQjtRQUN2QixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFFdkIsK0JBQStCO1FBQy9CLElBQUksSUFBSSxDQUFDLGFBQWEsQ0FBQyxlQUFlO1lBQ2xDLEdBQUcsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDeEQsT0FBTyxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQ3JELENBQUM7UUFFRCxzQkFBc0I7UUFDdEIsTUFBTSxRQUFRLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7UUFDM0MsS0FBSyxNQUFNLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsaUJBQWlCLENBQUMsY0FBYyxFQUFFLEVBQUUsQ0FBQztZQUM3RSxNQUFNLEVBQUUsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDO1lBQzNCLE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3RDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLE9BQU8sR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNoQyxDQUFDO1FBRUQsbUJBQW1CO1FBQ25CLElBQUksQ0FBQyxhQUFhLENBQUMsZUFBZSxHQUFHLFFBQVEsQ0FBQztRQUM5QyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsR0FBRyxHQUFHLENBQUM7UUFDbkMsT0FBTyxJQUFJLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUMzQixDQUFDO0lBRUQ7O09BRUc7SUFDSSxtQkFBbUI7UUFDeEIsNkJBQTZCO1FBQzdCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsaUJBQWlCLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztRQUN0RSxJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLGlCQUFpQixDQUFDLGtCQUFrQixFQUFFLENBQUMsQ0FBQyx5QkFBeUI7UUFFN0YsaUNBQWlDO1FBQ2pDLEtBQUssTUFBTSxNQUFNLElBQUksS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ3BDLEtBQUssSUFBSSxLQUFLLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ2xDLENBQUM7UUFFRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRDs7T0FFRztJQUNJLG9CQUFvQjtRQUN6QixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDdkIsTUFBTSxXQUFXLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUM7UUFFL0MsdUJBQXVCO1FBQ3ZCLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFHLFdBQVcsQ0FBQyxDQUFDO1FBRS9FLGdDQUFnQztRQUNoQyxNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLENBQUM7UUFDdkQsT0FBTyxnQkFBZ0IsR0FBRyxDQUFDLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUVEOztPQUVHO0lBQ0ksYUFBYTtRQUNsQixJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1FBRXhDLDJCQUEyQjtRQUMzQixJQUFJLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLEdBQUcsS0FBSyxFQUFFLENBQUM7WUFDMUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFDNUIsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNJLGFBQWE7UUFDbEIsSUFBSSxPQUFPLEdBQUcsQ0FBQyxDQUFDO1FBQ2hCLElBQUksUUFBUSxHQUFHLENBQUMsQ0FBQztRQUVqQix3Q0FBd0M7UUFDeEMsS0FBSyxNQUFNLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsaUJBQWlCLENBQUMsY0FBYyxFQUFFLEVBQUUsQ0FBQztZQUM3RSxPQUFPLElBQUksTUFBTSxDQUFDLGFBQWEsQ0FBQztZQUNoQyxRQUFRLElBQUksTUFBTSxDQUFDLFNBQVMsQ0FBQztRQUMvQixDQUFDO1FBRUQsT0FBTyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsQ0FBQztJQUMvQixDQUFDO0lBRUQ7O09BRUc7SUFDSSxpQkFBaUI7UUFDdEIsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ3ZCLElBQUksYUFBYSxHQUFHLENBQUMsQ0FBQztRQUN0QixJQUFJLGNBQWMsR0FBRyxDQUFDLENBQUM7UUFFdkIscUVBQXFFO1FBQ3JFLEtBQUssTUFBTSxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLGlCQUFpQixDQUFDLGNBQWMsRUFBRSxFQUFFLENBQUM7WUFDN0UsTUFBTSxhQUFhLEdBQUcsR0FBRyxHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQztZQUNyRCxJQUFJLGFBQWEsR0FBRyxLQUFLLEVBQUUsQ0FBQyxDQUFDLHdDQUF3QztnQkFDbkUsYUFBYSxJQUFJLE1BQU0sQ0FBQyxhQUFhLENBQUM7Z0JBQ3RDLGNBQWMsSUFBSSxNQUFNLENBQUMsU0FBUyxDQUFDO1lBQ3JDLENBQUM7aUJBQU0sQ0FBQztnQkFDTix3REFBd0Q7Z0JBQ3hELE1BQU0sSUFBSSxHQUFHLGFBQWEsR0FBRyxLQUFLLENBQUM7Z0JBQ25DLGFBQWEsSUFBSSxNQUFNLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQztnQkFDN0MsY0FBYyxJQUFJLE1BQU0sQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDO1lBQzVDLENBQUM7UUFDSCxDQUFDO1FBRUQsT0FBTztZQUNMLGFBQWEsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsR0FBRyxFQUFFLENBQUM7WUFDN0MsY0FBYyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsY0FBYyxHQUFHLEVBQUUsQ0FBQztTQUNoRCxDQUFDO0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0ksU0FBUyxDQUFDLFFBQWdCLEVBQUU7UUFDakMsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFDM0MsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUM7YUFDMUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUMzQixLQUFLLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQzthQUNmLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLFdBQVcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUVyRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRUQ7O09BRUc7SUFDSSxXQUFXLENBQUMsRUFBVSxFQUFFLG1CQUEyQjtRQUN4RCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUMzQyxNQUFNLGtCQUFrQixHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2pELE9BQU8sa0JBQWtCLElBQUksbUJBQW1CLENBQUM7SUFDbkQsQ0FBQztJQUVEOztPQUVHO0lBQ0ssa0JBQWtCO1FBQ3hCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDO1FBQ2pELElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFHLE1BQU0sQ0FBQyxDQUFDO0lBQzVFLENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUs7UUFDVixJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1lBQzVDLE1BQU0sSUFBSSxLQUFLLENBQUMsd0RBQXdELENBQUMsQ0FBQztRQUM1RSxDQUFDO1FBRUQsb0VBQW9FO1FBQ3BFLElBQUksQ0FBQyxzQkFBc0IsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLHNCQUFzQixDQUFDLG9CQUFvQixDQUFDLFNBQVMsQ0FBQztZQUNsRyxJQUFJLEVBQUUsQ0FBQyxNQUFNLEVBQUUsRUFBRTtnQkFDZixJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7Z0JBRXJCLG1DQUFtQztnQkFDbkMsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRSxxQkFBcUIsRUFBRSxDQUFDO29CQUNwRCxNQUFNLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSwyQ0FBMkMsRUFBRTt3QkFDL0QsWUFBWSxFQUFFLE1BQU0sQ0FBQyxFQUFFO3dCQUN2QixRQUFRLEVBQUUsTUFBTSxDQUFDLFFBQVE7d0JBQ3pCLFNBQVMsRUFBRSxNQUFNLENBQUMsV0FBVyxFQUFFLElBQUksSUFBSSxTQUFTO3dCQUNoRCxTQUFTLEVBQUUsU0FBUztxQkFDckIsQ0FBQyxDQUFDO2dCQUNMLENBQUM7WUFDSCxDQUFDO1lBQ0QsS0FBSyxFQUFFLENBQUMsR0FBRyxFQUFFLEVBQUU7Z0JBQ2IsTUFBTSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsb0RBQW9ELEVBQUU7b0JBQ3hFLEtBQUssRUFBRSxHQUFHLENBQUMsT0FBTztvQkFDbEIsU0FBUyxFQUFFLFNBQVM7aUJBQ3JCLENBQUMsQ0FBQztZQUNMLENBQUM7U0FDRixDQUFDLENBQUM7UUFFSCxNQUFNLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDO0lBQzVFLENBQUM7SUFFRDs7T0FFRztJQUNJLElBQUk7UUFDVCxJQUFJLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1lBQ2hDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUMxQyxJQUFJLENBQUMsc0JBQXNCLEdBQUcsU0FBUyxDQUFDO1FBQzFDLENBQUM7UUFFRCxNQUFNLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDO0lBQzVFLENBQUM7SUFFRDs7T0FFRztJQUNJLE9BQU87UUFDWixJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDZCxDQUFDO0NBQ0YifQ==
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export * from './route-types.js';
|
|
2
|
-
|
|
2
|
+
export * from './metrics-types.js';
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9wcm94aWVzL3NtYXJ0LXByb3h5L21vZGVscy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFLQSxjQUFjLGtCQUFrQixDQUFDO0FBQ2pDLGNBQWMsb0JBQW9CLENBQUMifQ==
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface for proxy statistics and metrics
|
|
3
|
+
*/
|
|
4
|
+
export interface IProxyStats {
|
|
5
|
+
/**
|
|
6
|
+
* Get the current number of active connections
|
|
7
|
+
*/
|
|
8
|
+
getActiveConnections(): number;
|
|
9
|
+
/**
|
|
10
|
+
* Get connection counts grouped by route name
|
|
11
|
+
*/
|
|
12
|
+
getConnectionsByRoute(): Map<string, number>;
|
|
13
|
+
/**
|
|
14
|
+
* Get connection counts grouped by IP address
|
|
15
|
+
*/
|
|
16
|
+
getConnectionsByIP(): Map<string, number>;
|
|
17
|
+
/**
|
|
18
|
+
* Get the total number of connections since proxy start
|
|
19
|
+
*/
|
|
20
|
+
getTotalConnections(): number;
|
|
21
|
+
/**
|
|
22
|
+
* Get the current requests per second rate
|
|
23
|
+
*/
|
|
24
|
+
getRequestsPerSecond(): number;
|
|
25
|
+
/**
|
|
26
|
+
* Get total throughput (bytes transferred)
|
|
27
|
+
*/
|
|
28
|
+
getThroughput(): {
|
|
29
|
+
bytesIn: number;
|
|
30
|
+
bytesOut: number;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Extended interface for additional metrics helpers
|
|
35
|
+
*/
|
|
36
|
+
export interface IProxyStatsExtended extends IProxyStats {
|
|
37
|
+
/**
|
|
38
|
+
* Get throughput rate (bytes per second) for last minute
|
|
39
|
+
*/
|
|
40
|
+
getThroughputRate(): {
|
|
41
|
+
bytesInPerSec: number;
|
|
42
|
+
bytesOutPerSec: number;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Get top IPs by connection count
|
|
46
|
+
*/
|
|
47
|
+
getTopIPs(limit?: number): Array<{
|
|
48
|
+
ip: string;
|
|
49
|
+
connections: number;
|
|
50
|
+
}>;
|
|
51
|
+
/**
|
|
52
|
+
* Check if an IP has reached the connection limit
|
|
53
|
+
*/
|
|
54
|
+
isIPBlocked(ip: string, maxConnectionsPerIP: number): boolean;
|
|
55
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as plugins from '../../plugins.js';
|
|
2
|
-
import type { ISmartProxyOptions } from './models/interfaces.js';
|
|
2
|
+
import type { IConnectionRecord, ISmartProxyOptions } from './models/interfaces.js';
|
|
3
3
|
import { ConnectionManager } from './connection-manager.js';
|
|
4
4
|
import { SecurityManager } from './security-manager.js';
|
|
5
5
|
import { TlsManager } from './tls-manager.js';
|
|
@@ -18,6 +18,7 @@ export declare class RouteConnectionHandler {
|
|
|
18
18
|
private routeManager;
|
|
19
19
|
private settings;
|
|
20
20
|
private routeContextCache;
|
|
21
|
+
newConnectionSubject: plugins.smartrx.rxjs.Subject<IConnectionRecord>;
|
|
21
22
|
constructor(settings: ISmartProxyOptions, connectionManager: ConnectionManager, securityManager: SecurityManager, tlsManager: TlsManager, httpProxyBridge: HttpProxyBridge, timeoutManager: TimeoutManager, routeManager: RouteManager);
|
|
22
23
|
/**
|
|
23
24
|
* Create a route context object for port and host mapping functions
|