@push.rocks/smartproxy 19.6.6 → 19.6.8
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/core/models/wrapped-socket.d.ts +4 -0
- package/dist_ts/core/models/wrapped-socket.js +18 -1
- package/dist_ts/core/routing/matchers/path.js +3 -2
- package/dist_ts/proxies/smart-proxy/connection-manager.d.ts +4 -7
- package/dist_ts/proxies/smart-proxy/connection-manager.js +22 -22
- package/dist_ts/proxies/smart-proxy/http-proxy-bridge.d.ts +4 -3
- package/dist_ts/proxies/smart-proxy/http-proxy-bridge.js +9 -9
- package/dist_ts/proxies/smart-proxy/metrics-collector.d.ts +68 -56
- package/dist_ts/proxies/smart-proxy/metrics-collector.js +252 -176
- package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +6 -1
- package/dist_ts/proxies/smart-proxy/models/metrics-types.d.ts +99 -47
- package/dist_ts/proxies/smart-proxy/nftables-manager.d.ts +4 -4
- package/dist_ts/proxies/smart-proxy/nftables-manager.js +6 -6
- package/dist_ts/proxies/smart-proxy/port-manager.d.ts +4 -7
- package/dist_ts/proxies/smart-proxy/port-manager.js +6 -9
- package/dist_ts/proxies/smart-proxy/route-connection-handler.d.ts +4 -15
- package/dist_ts/proxies/smart-proxy/route-connection-handler.js +133 -130
- package/dist_ts/proxies/smart-proxy/security-manager.d.ts +3 -3
- package/dist_ts/proxies/smart-proxy/security-manager.js +9 -9
- package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +20 -13
- package/dist_ts/proxies/smart-proxy/smart-proxy.js +16 -13
- package/dist_ts/proxies/smart-proxy/throughput-tracker.d.ts +36 -0
- package/dist_ts/proxies/smart-proxy/throughput-tracker.js +117 -0
- package/dist_ts/proxies/smart-proxy/timeout-manager.d.ts +5 -4
- package/dist_ts/proxies/smart-proxy/timeout-manager.js +20 -16
- package/dist_ts/proxies/smart-proxy/tls-manager.d.ts +3 -3
- package/dist_ts/proxies/smart-proxy/tls-manager.js +12 -12
- package/dist_ts/routing/router/http-router.js +2 -2
- package/package.json +1 -1
- package/readme.hints.md +0 -0
- package/readme.md +239 -73
- package/readme.plan.md +364 -0
- package/ts/core/models/wrapped-socket.ts +18 -0
- package/ts/core/routing/matchers/path.ts +2 -1
- package/ts/proxies/smart-proxy/connection-manager.ts +23 -21
- package/ts/proxies/smart-proxy/http-proxy-bridge.ts +9 -8
- package/ts/proxies/smart-proxy/metrics-collector.ts +305 -188
- package/ts/proxies/smart-proxy/models/interfaces.ts +8 -1
- package/ts/proxies/smart-proxy/models/metrics-types.ts +99 -41
- package/ts/proxies/smart-proxy/nftables-manager.ts +5 -5
- package/ts/proxies/smart-proxy/port-manager.ts +6 -14
- package/ts/proxies/smart-proxy/route-connection-handler.ts +141 -138
- package/ts/proxies/smart-proxy/security-manager.ts +8 -8
- package/ts/proxies/smart-proxy/smart-proxy.ts +26 -35
- package/ts/proxies/smart-proxy/throughput-tracker.ts +144 -0
- package/ts/proxies/smart-proxy/timeout-manager.ts +22 -16
- package/ts/proxies/smart-proxy/tls-manager.ts +11 -11
- package/ts/routing/router/http-router.ts +1 -1
|
@@ -1,211 +1,283 @@
|
|
|
1
1
|
import * as plugins from '../../plugins.js';
|
|
2
|
+
import { ThroughputTracker } from './throughput-tracker.js';
|
|
2
3
|
import { logger } from '../../core/utils/logger.js';
|
|
3
4
|
/**
|
|
4
|
-
* Collects and
|
|
5
|
+
* Collects and provides metrics for SmartProxy with clean API
|
|
5
6
|
*/
|
|
6
7
|
export class MetricsCollector {
|
|
7
|
-
constructor(smartProxy) {
|
|
8
|
+
constructor(smartProxy, config) {
|
|
8
9
|
this.smartProxy = smartProxy;
|
|
9
|
-
//
|
|
10
|
+
// Request tracking
|
|
10
11
|
this.requestTimestamps = [];
|
|
11
|
-
this.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
this.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
routeConfigName: record.routeConfig?.name,
|
|
55
|
-
routeConfigKeys: record.routeConfig ? Object.keys(record.routeConfig) : [],
|
|
56
|
-
component: 'metrics'
|
|
57
|
-
});
|
|
12
|
+
this.totalRequests = 0;
|
|
13
|
+
// Connection byte tracking for per-route/IP metrics
|
|
14
|
+
this.connectionByteTrackers = new Map();
|
|
15
|
+
// Connection metrics implementation
|
|
16
|
+
this.connections = {
|
|
17
|
+
active: () => {
|
|
18
|
+
return this.smartProxy.connectionManager.getConnectionCount();
|
|
19
|
+
},
|
|
20
|
+
total: () => {
|
|
21
|
+
const stats = this.smartProxy.connectionManager.getTerminationStats();
|
|
22
|
+
let total = this.smartProxy.connectionManager.getConnectionCount();
|
|
23
|
+
for (const reason in stats.incoming) {
|
|
24
|
+
total += stats.incoming[reason];
|
|
25
|
+
}
|
|
26
|
+
return total;
|
|
27
|
+
},
|
|
28
|
+
byRoute: () => {
|
|
29
|
+
const routeCounts = new Map();
|
|
30
|
+
const connections = this.smartProxy.connectionManager.getConnections();
|
|
31
|
+
for (const [_, record] of connections) {
|
|
32
|
+
const routeName = record.routeName ||
|
|
33
|
+
record.routeConfig?.name ||
|
|
34
|
+
'unknown';
|
|
35
|
+
const current = routeCounts.get(routeName) || 0;
|
|
36
|
+
routeCounts.set(routeName, current + 1);
|
|
37
|
+
}
|
|
38
|
+
return routeCounts;
|
|
39
|
+
},
|
|
40
|
+
byIP: () => {
|
|
41
|
+
const ipCounts = new Map();
|
|
42
|
+
for (const [_, record] of this.smartProxy.connectionManager.getConnections()) {
|
|
43
|
+
const ip = record.remoteIP;
|
|
44
|
+
const current = ipCounts.get(ip) || 0;
|
|
45
|
+
ipCounts.set(ip, current + 1);
|
|
46
|
+
}
|
|
47
|
+
return ipCounts;
|
|
48
|
+
},
|
|
49
|
+
topIPs: (limit = 10) => {
|
|
50
|
+
const ipCounts = this.connections.byIP();
|
|
51
|
+
return Array.from(ipCounts.entries())
|
|
52
|
+
.sort((a, b) => b[1] - a[1])
|
|
53
|
+
.slice(0, limit)
|
|
54
|
+
.map(([ip, count]) => ({ ip, count }));
|
|
58
55
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
56
|
+
};
|
|
57
|
+
// Throughput metrics implementation
|
|
58
|
+
this.throughput = {
|
|
59
|
+
instant: () => {
|
|
60
|
+
return this.throughputTracker.getRate(1);
|
|
61
|
+
},
|
|
62
|
+
recent: () => {
|
|
63
|
+
return this.throughputTracker.getRate(10);
|
|
64
|
+
},
|
|
65
|
+
average: () => {
|
|
66
|
+
return this.throughputTracker.getRate(60);
|
|
67
|
+
},
|
|
68
|
+
custom: (seconds) => {
|
|
69
|
+
return this.throughputTracker.getRate(seconds);
|
|
70
|
+
},
|
|
71
|
+
history: (seconds) => {
|
|
72
|
+
return this.throughputTracker.getHistory(seconds);
|
|
73
|
+
},
|
|
74
|
+
byRoute: (windowSeconds = 60) => {
|
|
75
|
+
const routeThroughput = new Map();
|
|
76
|
+
const now = Date.now();
|
|
77
|
+
const windowStart = now - (windowSeconds * 1000);
|
|
78
|
+
// Aggregate bytes by route with proper time calculation
|
|
79
|
+
const routeData = new Map();
|
|
80
|
+
for (const [_, tracker] of this.connectionByteTrackers) {
|
|
81
|
+
// Only include connections that were active within the window
|
|
82
|
+
if (tracker.lastUpdate > windowStart || tracker.startTime > windowStart) {
|
|
83
|
+
// Calculate the actual duration this connection was active within the window
|
|
84
|
+
const connectionStart = Math.max(tracker.startTime, windowStart);
|
|
85
|
+
const connectionEnd = tracker.lastUpdate;
|
|
86
|
+
const durationInWindow = (connectionEnd - connectionStart) / 1000; // Convert to seconds
|
|
87
|
+
if (durationInWindow > 0) {
|
|
88
|
+
const current = routeData.get(tracker.routeName) || { bytesIn: 0, bytesOut: 0, totalDuration: 0 };
|
|
89
|
+
current.bytesIn += tracker.bytesIn;
|
|
90
|
+
current.bytesOut += tracker.bytesOut;
|
|
91
|
+
current.totalDuration += durationInWindow;
|
|
92
|
+
routeData.set(tracker.routeName, current);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Convert to rates (bytes per second)
|
|
97
|
+
for (const [route, data] of routeData) {
|
|
98
|
+
if (data.totalDuration > 0) {
|
|
99
|
+
routeThroughput.set(route, {
|
|
100
|
+
in: Math.round(data.bytesIn / data.totalDuration),
|
|
101
|
+
out: Math.round(data.bytesOut / data.totalDuration)
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return routeThroughput;
|
|
106
|
+
},
|
|
107
|
+
byIP: (windowSeconds = 60) => {
|
|
108
|
+
const ipThroughput = new Map();
|
|
109
|
+
const now = Date.now();
|
|
110
|
+
const windowStart = now - (windowSeconds * 1000);
|
|
111
|
+
// Aggregate bytes by IP with proper time calculation
|
|
112
|
+
const ipData = new Map();
|
|
113
|
+
for (const [_, tracker] of this.connectionByteTrackers) {
|
|
114
|
+
// Only include connections that were active within the window
|
|
115
|
+
if (tracker.lastUpdate > windowStart || tracker.startTime > windowStart) {
|
|
116
|
+
// Calculate the actual duration this connection was active within the window
|
|
117
|
+
const connectionStart = Math.max(tracker.startTime, windowStart);
|
|
118
|
+
const connectionEnd = tracker.lastUpdate;
|
|
119
|
+
const durationInWindow = (connectionEnd - connectionStart) / 1000; // Convert to seconds
|
|
120
|
+
if (durationInWindow > 0) {
|
|
121
|
+
const current = ipData.get(tracker.remoteIP) || { bytesIn: 0, bytesOut: 0, totalDuration: 0 };
|
|
122
|
+
current.bytesIn += tracker.bytesIn;
|
|
123
|
+
current.bytesOut += tracker.bytesOut;
|
|
124
|
+
current.totalDuration += durationInWindow;
|
|
125
|
+
ipData.set(tracker.remoteIP, current);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Convert to rates (bytes per second)
|
|
130
|
+
for (const [ip, data] of ipData) {
|
|
131
|
+
if (data.totalDuration > 0) {
|
|
132
|
+
ipThroughput.set(ip, {
|
|
133
|
+
in: Math.round(data.bytesIn / data.totalDuration),
|
|
134
|
+
out: Math.round(data.bytesOut / data.totalDuration)
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return ipThroughput;
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
// Request metrics implementation
|
|
142
|
+
this.requests = {
|
|
143
|
+
perSecond: () => {
|
|
144
|
+
const now = Date.now();
|
|
145
|
+
const oneSecondAgo = now - 1000;
|
|
146
|
+
// Clean old timestamps
|
|
147
|
+
this.requestTimestamps = this.requestTimestamps.filter(ts => ts > now - 60000);
|
|
148
|
+
// Count requests in last second
|
|
149
|
+
const recentRequests = this.requestTimestamps.filter(ts => ts > oneSecondAgo);
|
|
150
|
+
return recentRequests.length;
|
|
151
|
+
},
|
|
152
|
+
perMinute: () => {
|
|
153
|
+
const now = Date.now();
|
|
154
|
+
const oneMinuteAgo = now - 60000;
|
|
155
|
+
// Count requests in last minute
|
|
156
|
+
const recentRequests = this.requestTimestamps.filter(ts => ts > oneMinuteAgo);
|
|
157
|
+
return recentRequests.length;
|
|
158
|
+
},
|
|
159
|
+
total: () => {
|
|
160
|
+
return this.totalRequests;
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
// Totals implementation
|
|
164
|
+
this.totals = {
|
|
165
|
+
bytesIn: () => {
|
|
166
|
+
let total = 0;
|
|
167
|
+
// Sum from all active connections
|
|
168
|
+
for (const [_, record] of this.smartProxy.connectionManager.getConnections()) {
|
|
169
|
+
total += record.bytesReceived;
|
|
170
|
+
}
|
|
171
|
+
// TODO: Add historical data from terminated connections
|
|
172
|
+
return total;
|
|
173
|
+
},
|
|
174
|
+
bytesOut: () => {
|
|
175
|
+
let total = 0;
|
|
176
|
+
// Sum from all active connections
|
|
177
|
+
for (const [_, record] of this.smartProxy.connectionManager.getConnections()) {
|
|
178
|
+
total += record.bytesSent;
|
|
179
|
+
}
|
|
180
|
+
// TODO: Add historical data from terminated connections
|
|
181
|
+
return total;
|
|
182
|
+
},
|
|
183
|
+
connections: () => {
|
|
184
|
+
return this.connections.total();
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
// Percentiles implementation (placeholder for now)
|
|
188
|
+
this.percentiles = {
|
|
189
|
+
connectionDuration: () => {
|
|
190
|
+
// TODO: Implement percentile calculations
|
|
191
|
+
return { p50: 0, p95: 0, p99: 0 };
|
|
192
|
+
},
|
|
193
|
+
bytesTransferred: () => {
|
|
194
|
+
// TODO: Implement percentile calculations
|
|
195
|
+
return {
|
|
196
|
+
in: { p50: 0, p95: 0, p99: 0 },
|
|
197
|
+
out: { p50: 0, p95: 0, p99: 0 }
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
this.sampleIntervalMs = config?.sampleIntervalMs || 1000;
|
|
202
|
+
this.retentionSeconds = config?.retentionSeconds || 3600;
|
|
203
|
+
this.throughputTracker = new ThroughputTracker(this.retentionSeconds);
|
|
113
204
|
}
|
|
114
205
|
/**
|
|
115
|
-
* Record a new request
|
|
206
|
+
* Record a new request
|
|
116
207
|
*/
|
|
117
|
-
recordRequest() {
|
|
208
|
+
recordRequest(connectionId, routeName, remoteIP) {
|
|
118
209
|
const now = Date.now();
|
|
119
210
|
this.requestTimestamps.push(now);
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
211
|
+
this.totalRequests++;
|
|
212
|
+
// Initialize byte tracker for this connection
|
|
213
|
+
this.connectionByteTrackers.set(connectionId, {
|
|
214
|
+
connectionId,
|
|
215
|
+
routeName,
|
|
216
|
+
remoteIP,
|
|
217
|
+
bytesIn: 0,
|
|
218
|
+
bytesOut: 0,
|
|
219
|
+
startTime: now,
|
|
220
|
+
lastUpdate: now
|
|
221
|
+
});
|
|
222
|
+
// Cleanup old request timestamps
|
|
223
|
+
if (this.requestTimestamps.length > 5000) {
|
|
224
|
+
// First try to clean up old timestamps (older than 1 minute)
|
|
225
|
+
const cutoff = now - 60000;
|
|
124
226
|
this.requestTimestamps = this.requestTimestamps.filter(ts => ts > cutoff);
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
* Get total throughput (bytes transferred)
|
|
129
|
-
*/
|
|
130
|
-
getThroughput() {
|
|
131
|
-
let bytesIn = 0;
|
|
132
|
-
let bytesOut = 0;
|
|
133
|
-
// Sum bytes from all active connections
|
|
134
|
-
for (const [_, record] of this.smartProxy.connectionManager.getConnections()) {
|
|
135
|
-
bytesIn += record.bytesReceived;
|
|
136
|
-
bytesOut += record.bytesSent;
|
|
137
|
-
}
|
|
138
|
-
return { bytesIn, bytesOut };
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Get throughput rate (bytes per second) for last minute
|
|
142
|
-
*/
|
|
143
|
-
getThroughputRate() {
|
|
144
|
-
const now = Date.now();
|
|
145
|
-
let recentBytesIn = 0;
|
|
146
|
-
let recentBytesOut = 0;
|
|
147
|
-
// Calculate bytes transferred in last minute from active connections
|
|
148
|
-
for (const [_, record] of this.smartProxy.connectionManager.getConnections()) {
|
|
149
|
-
const connectionAge = now - record.incomingStartTime;
|
|
150
|
-
if (connectionAge < 60000) { // Connection started within last minute
|
|
151
|
-
recentBytesIn += record.bytesReceived;
|
|
152
|
-
recentBytesOut += record.bytesSent;
|
|
153
|
-
}
|
|
154
|
-
else {
|
|
155
|
-
// For older connections, estimate rate based on average
|
|
156
|
-
const rate = connectionAge / 60000;
|
|
157
|
-
recentBytesIn += record.bytesReceived / rate;
|
|
158
|
-
recentBytesOut += record.bytesSent / rate;
|
|
227
|
+
// If still too many, enforce hard cap of 5000 most recent
|
|
228
|
+
if (this.requestTimestamps.length > 5000) {
|
|
229
|
+
this.requestTimestamps = this.requestTimestamps.slice(-5000);
|
|
159
230
|
}
|
|
160
231
|
}
|
|
161
|
-
return {
|
|
162
|
-
bytesInPerSec: Math.round(recentBytesIn / 60),
|
|
163
|
-
bytesOutPerSec: Math.round(recentBytesOut / 60)
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* Get top IPs by connection count
|
|
168
|
-
*/
|
|
169
|
-
getTopIPs(limit = 10) {
|
|
170
|
-
const ipCounts = this.getConnectionsByIP();
|
|
171
|
-
const sorted = Array.from(ipCounts.entries())
|
|
172
|
-
.sort((a, b) => b[1] - a[1])
|
|
173
|
-
.slice(0, limit)
|
|
174
|
-
.map(([ip, connections]) => ({ ip, connections }));
|
|
175
|
-
return sorted;
|
|
176
232
|
}
|
|
177
233
|
/**
|
|
178
|
-
*
|
|
234
|
+
* Record bytes transferred for a connection
|
|
179
235
|
*/
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
236
|
+
recordBytes(connectionId, bytesIn, bytesOut) {
|
|
237
|
+
// Update global throughput tracker
|
|
238
|
+
this.throughputTracker.recordBytes(bytesIn, bytesOut);
|
|
239
|
+
// Update connection-specific tracker
|
|
240
|
+
const tracker = this.connectionByteTrackers.get(connectionId);
|
|
241
|
+
if (tracker) {
|
|
242
|
+
tracker.bytesIn += bytesIn;
|
|
243
|
+
tracker.bytesOut += bytesOut;
|
|
244
|
+
tracker.lastUpdate = Date.now();
|
|
245
|
+
}
|
|
184
246
|
}
|
|
185
247
|
/**
|
|
186
|
-
* Clean up
|
|
248
|
+
* Clean up tracking for a closed connection
|
|
187
249
|
*/
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
this.requestTimestamps = this.requestTimestamps.filter(ts => ts > cutoff);
|
|
250
|
+
removeConnection(connectionId) {
|
|
251
|
+
this.connectionByteTrackers.delete(connectionId);
|
|
191
252
|
}
|
|
192
253
|
/**
|
|
193
|
-
* Start the metrics collector
|
|
254
|
+
* Start the metrics collector
|
|
194
255
|
*/
|
|
195
256
|
start() {
|
|
196
257
|
if (!this.smartProxy.routeConnectionHandler) {
|
|
197
258
|
throw new Error('MetricsCollector: RouteConnectionHandler not available');
|
|
198
259
|
}
|
|
199
|
-
//
|
|
260
|
+
// Start periodic sampling
|
|
261
|
+
this.samplingInterval = setInterval(() => {
|
|
262
|
+
this.throughputTracker.takeSample();
|
|
263
|
+
// Clean up old connection trackers (connections closed more than 5 minutes ago)
|
|
264
|
+
const cutoff = Date.now() - 300000;
|
|
265
|
+
for (const [id, tracker] of this.connectionByteTrackers) {
|
|
266
|
+
if (tracker.lastUpdate < cutoff) {
|
|
267
|
+
this.connectionByteTrackers.delete(id);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}, this.sampleIntervalMs);
|
|
271
|
+
// Subscribe to new connections
|
|
200
272
|
this.connectionSubscription = this.smartProxy.routeConnectionHandler.newConnectionSubject.subscribe({
|
|
201
273
|
next: (record) => {
|
|
202
|
-
|
|
203
|
-
|
|
274
|
+
const routeName = record.routeConfig?.name || 'unknown';
|
|
275
|
+
this.recordRequest(record.id, routeName, record.remoteIP);
|
|
204
276
|
if (this.smartProxy.settings?.enableDetailedLogging) {
|
|
205
277
|
logger.log('debug', `MetricsCollector: New connection recorded`, {
|
|
206
278
|
connectionId: record.id,
|
|
207
279
|
remoteIP: record.remoteIP,
|
|
208
|
-
routeName
|
|
280
|
+
routeName,
|
|
209
281
|
component: 'metrics'
|
|
210
282
|
});
|
|
211
283
|
}
|
|
@@ -220,9 +292,13 @@ export class MetricsCollector {
|
|
|
220
292
|
logger.log('debug', 'MetricsCollector started', { component: 'metrics' });
|
|
221
293
|
}
|
|
222
294
|
/**
|
|
223
|
-
* Stop the metrics collector
|
|
295
|
+
* Stop the metrics collector
|
|
224
296
|
*/
|
|
225
297
|
stop() {
|
|
298
|
+
if (this.samplingInterval) {
|
|
299
|
+
clearInterval(this.samplingInterval);
|
|
300
|
+
this.samplingInterval = undefined;
|
|
301
|
+
}
|
|
226
302
|
if (this.connectionSubscription) {
|
|
227
303
|
this.connectionSubscription.unsubscribe();
|
|
228
304
|
this.connectionSubscription = undefined;
|
|
@@ -230,10 +306,10 @@ export class MetricsCollector {
|
|
|
230
306
|
logger.log('debug', 'MetricsCollector stopped', { component: 'metrics' });
|
|
231
307
|
}
|
|
232
308
|
/**
|
|
233
|
-
* Alias for stop() for
|
|
309
|
+
* Alias for stop() for compatibility
|
|
234
310
|
*/
|
|
235
311
|
destroy() {
|
|
236
312
|
this.stop();
|
|
237
313
|
}
|
|
238
314
|
}
|
|
239
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy1jb2xsZWN0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9wcm94aWVzL3NtYXJ0LXByb3h5L21ldHJpY3MtY29sbGVjdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFHNUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRXBEOztHQUVHO0FBQ0gsTUFBTSxPQUFPLGdCQUFnQjtJQWtCM0IsWUFDVSxVQUFzQjtRQUF0QixlQUFVLEdBQVYsVUFBVSxDQUFZO1FBbEJoQyxvREFBb0Q7UUFDNUMsc0JBQWlCLEdBQWEsRUFBRSxDQUFDO1FBQ3hCLG9CQUFlLEdBQUcsS0FBSyxDQUFDLENBQUMsa0JBQWtCO1FBQzNDLG1CQUFjLEdBQUcsSUFBSSxDQUFDLENBQUMsNkJBQTZCO1FBRXJFLG1DQUFtQztRQUMzQixrQkFBYSxHQUlqQixFQUFFLFNBQVMsRUFBRSxDQUFDLEVBQUUsQ0FBQztRQUVKLGNBQVMsR0FBRyxJQUFJLENBQUMsQ0FBQyxpQkFBaUI7UUFRbEQsZ0RBQWdEO0lBQ2xELENBQUM7SUFFRDs7T0FFRztJQUNJLG9CQUFvQjtRQUN6QixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsaUJBQWlCLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztJQUNoRSxDQUFDO0lBRUQ7O09BRUc7SUFDSSxxQkFBcUI7UUFDMUIsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBRXZCLCtCQUErQjtRQUMvQixJQUFJLElBQUksQ0FBQyxhQUFhLENBQUMsa0JBQWtCO1lBQ3JDLEdBQUcsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDeEQsT0FBTyxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFD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
|
|
315
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy1jb2xsZWN0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9wcm94aWVzL3NtYXJ0LXByb3h5L21ldHJpY3MtY29sbGVjdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFRNUMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDNUQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRXBEOztHQUVHO0FBQ0gsTUFBTSxPQUFPLGdCQUFnQjtJQW1CM0IsWUFDVSxVQUFzQixFQUM5QixNQUdDO1FBSk8sZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQWhCaEMsbUJBQW1CO1FBQ1gsc0JBQWlCLEdBQWEsRUFBRSxDQUFDO1FBQ2pDLGtCQUFhLEdBQVcsQ0FBQyxDQUFDO1FBRWxDLG9EQUFvRDtRQUM1QywyQkFBc0IsR0FBRyxJQUFJLEdBQUcsRUFBd0IsQ0FBQztRQXNCakUsb0NBQW9DO1FBQzdCLGdCQUFXLEdBQUc7WUFDbkIsTUFBTSxFQUFFLEdBQVcsRUFBRTtnQkFDbkIsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLGlCQUFpQixDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDaEUsQ0FBQztZQUVELEtBQUssRUFBRSxHQUFXLEVBQUU7Z0JBQ2xCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsaUJBQWlCLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztnQkFDdEUsSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxpQkFBaUIsQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO2dCQUVuRSxLQUFLLE1BQU0sTUFBTSxJQUFJLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQztvQkFDcEMsS0FBSyxJQUFJLEtBQUssQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQ2xDLENBQUM7Z0JBRUQs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
|
|
@@ -76,6 +76,11 @@ export interface ISmartProxyOptions {
|
|
|
76
76
|
extendedKeepAliveLifetime?: number;
|
|
77
77
|
useHttpProxy?: number[];
|
|
78
78
|
httpProxyPort?: number;
|
|
79
|
+
metrics?: {
|
|
80
|
+
enabled?: boolean;
|
|
81
|
+
sampleIntervalMs?: number;
|
|
82
|
+
retentionSeconds?: number;
|
|
83
|
+
};
|
|
79
84
|
/**
|
|
80
85
|
* Global ACME configuration options for SmartProxy
|
|
81
86
|
*
|
|
@@ -111,7 +116,7 @@ export interface IConnectionRecord {
|
|
|
111
116
|
outgoingClosedTime?: number;
|
|
112
117
|
lockedDomain?: string;
|
|
113
118
|
connectionClosed: boolean;
|
|
114
|
-
cleanupTimer?: NodeJS.Timeout;
|
|
119
|
+
cleanupTimer?: NodeJS.Timeout | null;
|
|
115
120
|
alertFallbackTimeout?: NodeJS.Timeout;
|
|
116
121
|
lastActivity: number;
|
|
117
122
|
pendingData: Buffer[];
|