@push.rocks/smartproxy 19.6.6 → 19.6.7

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.
Files changed (41) hide show
  1. package/dist_ts/proxies/smart-proxy/connection-manager.d.ts +4 -7
  2. package/dist_ts/proxies/smart-proxy/connection-manager.js +22 -22
  3. package/dist_ts/proxies/smart-proxy/http-proxy-bridge.d.ts +4 -3
  4. package/dist_ts/proxies/smart-proxy/http-proxy-bridge.js +9 -9
  5. package/dist_ts/proxies/smart-proxy/metrics-collector.d.ts +68 -56
  6. package/dist_ts/proxies/smart-proxy/metrics-collector.js +226 -176
  7. package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +5 -0
  8. package/dist_ts/proxies/smart-proxy/models/metrics-types.d.ts +94 -48
  9. package/dist_ts/proxies/smart-proxy/nftables-manager.d.ts +4 -4
  10. package/dist_ts/proxies/smart-proxy/nftables-manager.js +6 -6
  11. package/dist_ts/proxies/smart-proxy/port-manager.d.ts +4 -7
  12. package/dist_ts/proxies/smart-proxy/port-manager.js +6 -9
  13. package/dist_ts/proxies/smart-proxy/route-connection-handler.d.ts +4 -15
  14. package/dist_ts/proxies/smart-proxy/route-connection-handler.js +128 -128
  15. package/dist_ts/proxies/smart-proxy/security-manager.d.ts +3 -3
  16. package/dist_ts/proxies/smart-proxy/security-manager.js +9 -9
  17. package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +20 -13
  18. package/dist_ts/proxies/smart-proxy/smart-proxy.js +16 -13
  19. package/dist_ts/proxies/smart-proxy/throughput-tracker.d.ts +36 -0
  20. package/dist_ts/proxies/smart-proxy/throughput-tracker.js +117 -0
  21. package/dist_ts/proxies/smart-proxy/timeout-manager.d.ts +4 -3
  22. package/dist_ts/proxies/smart-proxy/timeout-manager.js +16 -16
  23. package/dist_ts/proxies/smart-proxy/tls-manager.d.ts +3 -3
  24. package/dist_ts/proxies/smart-proxy/tls-manager.js +12 -12
  25. package/package.json +1 -1
  26. package/readme.hints.md +0 -0
  27. package/readme.md +239 -73
  28. package/readme.plan.md +364 -0
  29. package/ts/proxies/smart-proxy/connection-manager.ts +23 -21
  30. package/ts/proxies/smart-proxy/http-proxy-bridge.ts +9 -8
  31. package/ts/proxies/smart-proxy/metrics-collector.ts +277 -189
  32. package/ts/proxies/smart-proxy/models/interfaces.ts +7 -0
  33. package/ts/proxies/smart-proxy/models/metrics-types.ts +93 -41
  34. package/ts/proxies/smart-proxy/nftables-manager.ts +5 -5
  35. package/ts/proxies/smart-proxy/port-manager.ts +6 -14
  36. package/ts/proxies/smart-proxy/route-connection-handler.ts +136 -136
  37. package/ts/proxies/smart-proxy/security-manager.ts +8 -8
  38. package/ts/proxies/smart-proxy/smart-proxy.ts +26 -35
  39. package/ts/proxies/smart-proxy/throughput-tracker.ts +144 -0
  40. package/ts/proxies/smart-proxy/timeout-manager.ts +16 -15
  41. package/ts/proxies/smart-proxy/tls-manager.ts +11 -11
@@ -2,8 +2,8 @@
2
2
  * Manages timeouts and inactivity tracking for connections
3
3
  */
4
4
  export class TimeoutManager {
5
- constructor(settings) {
6
- this.settings = settings;
5
+ constructor(smartProxy) {
6
+ this.smartProxy = smartProxy;
7
7
  }
8
8
  /**
9
9
  * Ensure timeout values don't exceed Node.js max safe integer
@@ -34,14 +34,14 @@ export class TimeoutManager {
34
34
  * Calculate effective inactivity timeout based on connection type
35
35
  */
36
36
  getEffectiveInactivityTimeout(record) {
37
- let effectiveTimeout = this.settings.inactivityTimeout || 14400000; // 4 hours default
37
+ let effectiveTimeout = this.smartProxy.settings.inactivityTimeout || 14400000; // 4 hours default
38
38
  // For immortal keep-alive connections, use an extremely long timeout
39
- if (record.hasKeepAlive && this.settings.keepAliveTreatment === 'immortal') {
39
+ if (record.hasKeepAlive && this.smartProxy.settings.keepAliveTreatment === 'immortal') {
40
40
  return Number.MAX_SAFE_INTEGER;
41
41
  }
42
42
  // For extended keep-alive connections, apply multiplier
43
- if (record.hasKeepAlive && this.settings.keepAliveTreatment === 'extended') {
44
- const multiplier = this.settings.keepAliveInactivityMultiplier || 6;
43
+ if (record.hasKeepAlive && this.smartProxy.settings.keepAliveTreatment === 'extended') {
44
+ const multiplier = this.smartProxy.settings.keepAliveInactivityMultiplier || 6;
45
45
  effectiveTimeout = effectiveTimeout * multiplier;
46
46
  }
47
47
  return this.ensureSafeTimeout(effectiveTimeout);
@@ -52,19 +52,19 @@ export class TimeoutManager {
52
52
  getEffectiveMaxLifetime(record) {
53
53
  // Use route-specific timeout if available from the routeConfig
54
54
  const baseTimeout = record.routeConfig?.action.advanced?.timeout ||
55
- this.settings.maxConnectionLifetime ||
55
+ this.smartProxy.settings.maxConnectionLifetime ||
56
56
  86400000; // 24 hours default
57
57
  // For immortal keep-alive connections, use an extremely long lifetime
58
- if (record.hasKeepAlive && this.settings.keepAliveTreatment === 'immortal') {
58
+ if (record.hasKeepAlive && this.smartProxy.settings.keepAliveTreatment === 'immortal') {
59
59
  return Number.MAX_SAFE_INTEGER;
60
60
  }
61
61
  // For extended keep-alive connections, use the extended lifetime setting
62
- if (record.hasKeepAlive && this.settings.keepAliveTreatment === 'extended') {
63
- return this.ensureSafeTimeout(this.settings.extendedKeepAliveLifetime || 7 * 24 * 60 * 60 * 1000 // 7 days default
62
+ if (record.hasKeepAlive && this.smartProxy.settings.keepAliveTreatment === 'extended') {
63
+ return this.ensureSafeTimeout(this.smartProxy.settings.extendedKeepAliveLifetime || 7 * 24 * 60 * 60 * 1000 // 7 days default
64
64
  );
65
65
  }
66
66
  // Apply randomization if enabled
67
- if (this.settings.enableRandomizedTimeouts) {
67
+ if (this.smartProxy.settings.enableRandomizedTimeouts) {
68
68
  return this.randomizeTimeout(baseTimeout);
69
69
  }
70
70
  return this.ensureSafeTimeout(baseTimeout);
@@ -97,7 +97,7 @@ export class TimeoutManager {
97
97
  */
98
98
  checkInactivity(record) {
99
99
  // Skip for connections with inactivity check disabled
100
- if (this.settings.disableInactivityCheck) {
100
+ if (this.smartProxy.settings.disableInactivityCheck) {
101
101
  return {
102
102
  isInactive: false,
103
103
  shouldWarn: false,
@@ -106,7 +106,7 @@ export class TimeoutManager {
106
106
  };
107
107
  }
108
108
  // Skip for immortal keep-alive connections
109
- if (record.hasKeepAlive && this.settings.keepAliveTreatment === 'immortal') {
109
+ if (record.hasKeepAlive && this.smartProxy.settings.keepAliveTreatment === 'immortal') {
110
110
  return {
111
111
  isInactive: false,
112
112
  shouldWarn: false,
@@ -135,7 +135,7 @@ export class TimeoutManager {
135
135
  */
136
136
  applySocketTimeouts(record) {
137
137
  // Skip for immortal keep-alive connections
138
- if (record.hasKeepAlive && this.settings.keepAliveTreatment === 'immortal') {
138
+ if (record.hasKeepAlive && this.smartProxy.settings.keepAliveTreatment === 'immortal') {
139
139
  // Disable timeouts completely for immortal connections
140
140
  record.incoming.setTimeout(0);
141
141
  if (record.outgoing) {
@@ -144,11 +144,11 @@ export class TimeoutManager {
144
144
  return;
145
145
  }
146
146
  // Apply normal timeouts
147
- const timeout = this.ensureSafeTimeout(this.settings.socketTimeout || 3600000); // 1 hour default
147
+ const timeout = this.ensureSafeTimeout(this.smartProxy.settings.socketTimeout || 3600000); // 1 hour default
148
148
  record.incoming.setTimeout(timeout);
149
149
  if (record.outgoing) {
150
150
  record.outgoing.setTimeout(timeout);
151
151
  }
152
152
  }
153
153
  }
154
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZW91dC1tYW5hZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvcHJveGllcy9zbWFydC1wcm94eS90aW1lb3V0LW1hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUE7O0dBRUc7QUFDSCxNQUFNLE9BQU8sY0FBYztJQUN6QixZQUFvQixRQUE0QjtRQUE1QixhQUFRLEdBQVIsUUFBUSxDQUFvQjtJQUFHLENBQUM7SUFFcEQ7O09BRUc7SUFDSSxpQkFBaUIsQ0FBQyxPQUFlO1FBQ3RDLE1BQU0sZ0JBQWdCLEdBQUcsVUFBVSxDQUFDLENBQUMsZ0NBQWdDO1FBQ3JFLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxFQUFFLGdCQUFnQixDQUFDLENBQUM7SUFDekQsQ0FBQztJQUVEOztPQUVHO0lBQ0ksZ0JBQWdCLENBQUMsV0FBbUIsRUFBRSxtQkFBMkIsQ0FBQztRQUN2RSxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDNUQsTUFBTSxTQUFTLEdBQUcsZUFBZSxHQUFHLENBQUMsZ0JBQWdCLEdBQUcsR0FBRyxDQUFDLENBQUM7UUFDN0QsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQzNCLGVBQWUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxTQUFTLEdBQUcsQ0FBQyxDQUFDLEdBQUcsU0FBUyxDQUN4RSxDQUFDO0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0ksY0FBYyxDQUFDLE1BQXlCO1FBQzdDLE1BQU0sQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBRWpDLCtCQUErQjtRQUMvQixJQUFJLE1BQU0sQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO1lBQ25DLE1BQU0sQ0FBQyx1QkFBdUIsR0FBRyxLQUFLLENBQUM7UUFDekMsQ0FBQztJ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
154
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZW91dC1tYW5hZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvcHJveGllcy9zbWFydC1wcm94eS90aW1lb3V0LW1hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBR0E7O0dBRUc7QUFDSCxNQUFNLE9BQU8sY0FBYztJQUN6QixZQUFvQixVQUFzQjtRQUF0QixlQUFVLEdBQVYsVUFBVSxDQUFZO0lBQUcsQ0FBQztJQUU5Qzs7T0FFRztJQUNJLGlCQUFpQixDQUFDLE9BQWU7UUFDdEMsTUFBTSxnQkFBZ0IsR0FBRyxVQUFVLENBQUMsQ0FBQyxnQ0FBZ0M7UUFDckUsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztJQUN6RCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxnQkFBZ0IsQ0FBQyxXQUFtQixFQUFFLG1CQUEyQixDQUFDO1FBQ3ZFLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM1RCxNQUFNLFNBQVMsR0FBRyxlQUFlLEdBQUcsQ0FBQyxnQkFBZ0IsR0FBRyxHQUFHLENBQUMsQ0FBQztRQUM3RCxPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FDM0IsZUFBZSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLFNBQVMsR0FBRyxDQUFDLENBQUMsR0FBRyxTQUFTLENBQ3hFLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSSxjQUFjLENBQUMsTUFBeUI7UUFDN0MsTUFBTSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFFakMsK0JBQStCO1FBQy9CLElBQUksTUFBTSxDQUFDLHVCQUF1QixFQUFFLENBQUM7WUFDbkMsTUFBTSxDQUFDLHVCQUF1QixHQUFHLEtBQUssQ0FBQztRQUN6QyxDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0ksNkJBQTZCLENBQUMsTUFBeUI7UUFDNUQsSUFBSSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsSUFBSSxRQUFRLENBQUMsQ0FBQyxrQkFBa0I7UUFFakcscUVBQXFFO1FBQ3JFLElBQUksTUFBTSxDQUFDLFlBQVksSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsS0FBSyxVQUFVLEVBQUUsQ0FBQztZQUN0RixPQUFPLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQztRQUNqQyxDQUFDO1FBRUQsd0RBQXdEO1FBQ3hELElBQUksTUFBTSxDQUFDLFlBQVksSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsS0FBSyxVQUFVLEVBQUUsQ0FBQztZQUN0RixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyw2QkFBNkIsSUFBSSxDQUFDLENBQUM7WUFDL0UsZ0JBQWdCLEdBQUcsZ0JBQWdCLEdBQUcsVUFBVSxDQUFDO1FBQ25ELENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFRDs7T0FFRztJQUNJLHVCQUF1QixDQUFDLE1BQXlCO1FBQ3RELCtEQUErRDtRQUMvRCxNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsV0FBVyxFQUFFLE1BQU0sQ0FBQyxRQUFRLEVBQUUsT0FBTztZQUM1QyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUI7WUFDOUMsUUFBUSxDQUFDLENBQUMsbUJBQW1CO1FBRWpELHNFQUFzRTtRQUN0RSxJQUFJLE1BQU0sQ0FBQyxZQUFZLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsa0JBQWtCLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDdEYsT0FBTyxNQUFNLENBQUMsZ0JBQWdCLENBQUM7UUFDakMsQ0FBQztRQUVELHlFQUF5RTtRQUN6RSxJQUFJLE1BQU0sQ0FBQyxZQUFZLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsa0JBQWtCLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDdEYsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQzNCLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLHlCQUF5QixJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsaUJBQWlCO2FBQ2hHLENBQUM7UUFDSixDQUFDO1FBRUQsaUNBQWlDO1FBQ2pDLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsd0JBQXdCLEVBQUUsQ0FBQztZQUN0RCxPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM1QyxDQUFDO1FBRUQsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDN0MsQ0FBQztJQUVEOzs7T0FHRztJQUNJLHNCQUFzQixDQUMzQixNQUF5QixFQUN6QixTQUE4RDtRQUU5RCwyQkFBMkI7UUFDM0IsSUFBSSxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDeEIsWUFBWSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNwQyxDQUFDO1FBRUQsOEJBQThCO1FBQzlCLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLHVCQUF1QixDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRS9ELHFCQUFxQjtRQUNyQixNQUFNLEtBQUssR0FBRyxVQUFVLENBQUMsR0FBRyxFQUFFO1lBQzVCLDZCQUE2QjtZQUM3QixTQUFTLENBQUMsTUFBTSxFQUFFLG9CQUFvQixDQUFDLENBQUM7UUFDMUMsQ0FBQyxFQUFFLGlCQUFpQixDQUFDLENBQUM7UUFFdEIsbURBQW1EO1FBQ25ELElBQUksS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2hCLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNoQixDQUFDO1FBRUQsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksZUFBZSxDQUFDLE1BQXlCO1FBTTlDLHNEQUFzRDtRQUN0RCxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLHNCQUFzQixFQUFFLENBQUM7WUFDcEQsT0FBTztnQkFDTCxVQUFVLEVBQUUsS0FBSztnQkFDakIsVUFBVSxFQUFFLEtBQUs7Z0JBQ2pCLGNBQWMsRUFBRSxDQUFDO2dCQUNqQixnQkFBZ0IsRUFBRSxDQUFDO2FBQ3BCLENBQUM7UUFDSixDQUFDO1FBRUQsMkNBQTJDO1FBQzNDLElBQUksTUFBTSxDQUFDLFlBQVksSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsS0FBSyxVQUFVLEVBQUUsQ0FBQztZQUN0RixPQUFPO2dCQUNMLFVBQVUsRUFBRSxLQUFLO2dCQUNqQixVQUFVLEVBQUUsS0FBSztnQkFDakIsY0FBYyxFQUFFLENBQUM7Z0JBQ2pCLGdCQUFnQixFQUFFLENBQUM7YUFDcEIsQ0FBQztRQUNKLENBQUM7UUFFRCxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDdkIsTUFBTSxjQUFjLEdBQUcsR0FBRyxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUM7UUFDakQsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsNkJBQTZCLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFcEUsb0JBQW9CO1FBQ3BCLE1BQU0sVUFBVSxHQUFHLGNBQWMsR0FBRyxnQkFBZ0IsQ0FBQztRQUVyRCxtREFBbUQ7UUFDbkQsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLFlBQVk7WUFDbkIsVUFBVTtZQUNWLENBQUMsTUFBTSxDQUFDLHVCQUF1QixDQUFDO1FBRW5ELE9BQU87WUFDTCxVQUFVO1lBQ1YsVUFBVTtZQUNWLGNBQWM7WUFDZCxnQkFBZ0I7U0FDakIsQ0FBQztJQUNKLENBQUM7SUFFRDs7T0FFRztJQUNJLG1CQUFtQixDQUFDLE1BQXlCO1FBQ2xELDJDQUEyQztRQUMzQyxJQUFJLE1BQU0sQ0FBQyxZQUFZLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsa0JBQWtCLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDdEYsdURBQXVEO1lBQ3ZELE1BQU0sQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzlCLElBQUksTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUNwQixNQUFNLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNoQyxDQUFDO1lBQ0QsT0FBTztRQUNULENBQUM7UUFFRCx3QkFBd0I7UUFDeEIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLGFBQWEsSUFBSSxPQUFPLENBQUMsQ0FBQyxDQUFDLGlCQUFpQjtRQUM1RyxNQUFNLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNwQyxJQUFJLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNwQixNQUFNLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN0QyxDQUFDO0lBQ0gsQ0FBQztDQUNGIn0=
@@ -1,4 +1,4 @@
1
- import type { ISmartProxyOptions } from './models/interfaces.js';
1
+ import type { SmartProxy } from './smart-proxy.js';
2
2
  /**
3
3
  * Interface for connection information used for SNI extraction
4
4
  */
@@ -12,8 +12,8 @@ interface IConnectionInfo {
12
12
  * Manages TLS-related operations including SNI extraction and validation
13
13
  */
14
14
  export declare class TlsManager {
15
- private settings;
16
- constructor(settings: ISmartProxyOptions);
15
+ private smartProxy;
16
+ constructor(smartProxy: SmartProxy);
17
17
  /**
18
18
  * Check if a data chunk appears to be a TLS handshake
19
19
  */
@@ -4,8 +4,8 @@ import { SniHandler } from '../../tls/sni/sni-handler.js';
4
4
  * Manages TLS-related operations including SNI extraction and validation
5
5
  */
6
6
  export class TlsManager {
7
- constructor(settings) {
8
- this.settings = settings;
7
+ constructor(smartProxy) {
8
+ this.smartProxy = smartProxy;
9
9
  }
10
10
  /**
11
11
  * Check if a data chunk appears to be a TLS handshake
@@ -24,21 +24,21 @@ export class TlsManager {
24
24
  */
25
25
  extractSNI(chunk, connInfo, previousDomain) {
26
26
  // Use the SniHandler to process the TLS packet
27
- return SniHandler.processTlsPacket(chunk, connInfo, this.settings.enableTlsDebugLogging || false, previousDomain);
27
+ return SniHandler.processTlsPacket(chunk, connInfo, this.smartProxy.settings.enableTlsDebugLogging || false, previousDomain);
28
28
  }
29
29
  /**
30
30
  * Handle session resumption attempts
31
31
  */
32
32
  handleSessionResumption(chunk, connectionId, hasSNI) {
33
33
  // Skip if session tickets are allowed
34
- if (this.settings.allowSessionTicket !== false) {
34
+ if (this.smartProxy.settings.allowSessionTicket !== false) {
35
35
  return { shouldBlock: false };
36
36
  }
37
37
  // Check for session resumption attempt
38
- const resumptionInfo = SniHandler.hasSessionResumption(chunk, this.settings.enableTlsDebugLogging || false);
38
+ const resumptionInfo = SniHandler.hasSessionResumption(chunk, this.smartProxy.settings.enableTlsDebugLogging || false);
39
39
  // If this is a resumption attempt without SNI, block it
40
40
  if (resumptionInfo.isResumption && !hasSNI && !resumptionInfo.hasSNI) {
41
- if (this.settings.enableTlsDebugLogging) {
41
+ if (this.smartProxy.settings.enableTlsDebugLogging) {
42
42
  console.log(`[${connectionId}] Session resumption detected without SNI and allowSessionTicket=false. ` +
43
43
  `Terminating connection to force new TLS handshake.`);
44
44
  }
@@ -59,19 +59,19 @@ export class TlsManager {
59
59
  }
60
60
  try {
61
61
  // Extract SNI with renegotiation support
62
- const newSNI = SniHandler.extractSNIWithResumptionSupport(chunk, connInfo, this.settings.enableTlsDebugLogging || false);
62
+ const newSNI = SniHandler.extractSNIWithResumptionSupport(chunk, connInfo, this.smartProxy.settings.enableTlsDebugLogging || false);
63
63
  // Skip if no SNI was found
64
64
  if (!newSNI)
65
65
  return { hasMismatch: false };
66
66
  // Check for SNI mismatch
67
67
  if (newSNI !== expectedDomain) {
68
- if (this.settings.enableTlsDebugLogging) {
68
+ if (this.smartProxy.settings.enableTlsDebugLogging) {
69
69
  console.log(`[${connectionId}] Renegotiation with different SNI: ${expectedDomain} -> ${newSNI}. ` +
70
70
  `Terminating connection - SNI domain switching is not allowed.`);
71
71
  }
72
72
  return { hasMismatch: true, extractedSNI: newSNI };
73
73
  }
74
- else if (this.settings.enableTlsDebugLogging) {
74
+ else if (this.smartProxy.settings.enableTlsDebugLogging) {
75
75
  console.log(`[${connectionId}] Renegotiation detected with same SNI: ${newSNI}. Allowing.`);
76
76
  }
77
77
  }
@@ -108,9 +108,9 @@ export class TlsManager {
108
108
  return result;
109
109
  }
110
110
  // Check for session resumption
111
- const resumptionInfo = SniHandler.hasSessionResumption(chunk, this.settings.enableTlsDebugLogging || false);
111
+ const resumptionInfo = SniHandler.hasSessionResumption(chunk, this.smartProxy.settings.enableTlsDebugLogging || false);
112
112
  // Extract SNI
113
- const sni = SniHandler.extractSNI(chunk, this.settings.enableTlsDebugLogging || false);
113
+ const sni = SniHandler.extractSNI(chunk, this.smartProxy.settings.enableTlsDebugLogging || false);
114
114
  // Update result
115
115
  result.isRenewal = resumptionInfo.isResumption;
116
116
  result.hasSNI = !!sni;
@@ -129,4 +129,4 @@ export class TlsManager {
129
129
  }
130
130
  }
131
131
  }
132
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGxzLW1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9wcm94aWVzL3NtYXJ0LXByb3h5L3Rscy1tYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFFNUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBWTFEOztHQUVHO0FBQ0gsTUFBTSxPQUFPLFVBQVU7SUFDckIsWUFBb0IsUUFBNEI7UUFBNUIsYUFBUSxHQUFSLFFBQVEsQ0FBb0I7SUFBRyxDQUFDO0lBRXBEOztPQUVHO0lBQ0ksY0FBYyxDQUFDLEtBQWE7UUFDakMsT0FBTyxVQUFVLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFFRDs7T0FFRztJQUNJLGFBQWEsQ0FBQyxLQUFhO1FBQ2hDLE9BQU8sVUFBVSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN6QyxDQUFDO0lBRUQ7O09BRUc7SUFDSSxVQUFVLENBQ2YsS0FBYSxFQUNiLFFBQXlCLEVBQ3pCLGNBQXVCO1FBRXZCLCtDQUErQztRQUMvQyxPQUFPLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FDaEMsS0FBSyxFQUNMLFFBQVEsRUFDUixJQUFJLENBQUMsUUFBUSxDQUFDLHFCQUFxQixJQUFJLEtBQUssRUFDNUMsY0FBYyxDQUNmLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSSx1QkFBdUIsQ0FDNUIsS0FBYSxFQUNiLFlBQW9CLEVBQ3BCLE1BQWU7UUFFZixzQ0FBc0M7UUFDdEMsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLGtCQUFrQixLQUFLLEtBQUssRUFBRSxDQUFDO1lBQy9DLE9BQU8sRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUM7UUFDaEMsQ0FBQztRQUVELHVDQUF1QztRQUN2QyxNQUFNLGNBQWMsR0FBRyxVQUFVLENBQUMsb0JBQW9CLENB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
132
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGxzLW1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9wcm94aWVzL3NtYXJ0LXByb3h5L3Rscy1tYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFDNUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBYTFEOztHQUVHO0FBQ0gsTUFBTSxPQUFPLFVBQVU7SUFDckIsWUFBb0IsVUFBc0I7UUFBdEIsZUFBVSxHQUFWLFVBQVUsQ0FBWTtJQUFHLENBQUM7SUFFOUM7O09BRUc7SUFDSSxjQUFjLENBQUMsS0FBYTtRQUNqQyxPQUFPLFVBQVUsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUVEOztPQUVHO0lBQ0ksYUFBYSxDQUFDLEtBQWE7UUFDaEMsT0FBTyxVQUFVLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3pDLENBQUM7SUFFRDs7T0FFRztJQUNJLFVBQVUsQ0FDZixLQUFhLEVBQ2IsUUFBeUIsRUFDekIsY0FBdUI7UUFFdkIsK0NBQStDO1FBQy9DLE9BQU8sVUFBVSxDQUFDLGdCQUFnQixDQUNoQyxLQUFLLEVBQ0wsUUFBUSxFQUNSLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLHFCQUFxQixJQUFJLEtBQUssRUFDdkQsY0FBYyxDQUNmLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSSx1QkFBdUIsQ0FDNUIsS0FBYSxFQUNiLFlBQW9CLEVBQ3BCLE1BQWU7UUFFZixzQ0FBc0M7UUFDdEMsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsS0FBSyxLQUFLLEVBQUUsQ0FBQztZQUMxRCxPQUFPLEVBQUUsV0FBVyxFQUFFLEtBQUssRUFBRSxDQUFDO1FBQ2hDLENBQUM7UUFFRCx1Q0FBdUM7UUFDdkMsTUFBTSxjQUFjLEdBQUcs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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@push.rocks/smartproxy",
3
- "version": "19.6.6",
3
+ "version": "19.6.7",
4
4
  "private": false,
5
5
  "description": "A powerful proxy package with unified route-based configuration for high traffic management. Features include SSL/TLS support, flexible routing patterns, WebSocket handling, advanced security options, and automatic ACME certificate management.",
6
6
  "main": "dist_ts/index.js",
File without changes
package/readme.md CHANGED
@@ -1576,150 +1576,316 @@ Available helper functions:
1576
1576
 
1577
1577
  ## Metrics and Monitoring
1578
1578
 
1579
- SmartProxy includes a comprehensive metrics collection system that provides real-time insights into proxy performance, connection statistics, and throughput data.
1579
+ 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.
1580
1580
 
1581
- ### Getting Metrics
1581
+ ### Enabling Metrics
1582
1582
 
1583
1583
  ```typescript
1584
- const proxy = new SmartProxy({ /* config */ });
1584
+ const proxy = new SmartProxy({
1585
+ // Enable metrics collection
1586
+ metrics: {
1587
+ enabled: true,
1588
+ sampleIntervalMs: 1000, // Sample throughput every second
1589
+ retentionSeconds: 3600 // Keep 1 hour of history
1590
+ },
1591
+ routes: [/* your routes */]
1592
+ });
1593
+
1585
1594
  await proxy.start();
1595
+ ```
1586
1596
 
1587
- // Access metrics through the getStats() method
1588
- const stats = proxy.getStats();
1597
+ ### Getting Metrics
1589
1598
 
1590
- // Get current active connections
1591
- console.log(`Active connections: ${stats.getActiveConnections()}`);
1599
+ ```typescript
1600
+ // Access metrics through the getMetrics() method
1601
+ const metrics = proxy.getMetrics();
1592
1602
 
1593
- // Get total connections since start
1594
- console.log(`Total connections: ${stats.getTotalConnections()}`);
1603
+ // The metrics object provides grouped methods for different categories
1604
+ ```
1595
1605
 
1596
- // Get requests per second (RPS)
1597
- console.log(`Current RPS: ${stats.getRequestsPerSecond()}`);
1606
+ ### Connection Metrics
1598
1607
 
1599
- // Get throughput data
1600
- const throughput = stats.getThroughput();
1601
- console.log(`Bytes received: ${throughput.bytesIn}`);
1602
- console.log(`Bytes sent: ${throughput.bytesOut}`);
1608
+ Monitor active connections, total connections, and connection distribution:
1609
+
1610
+ ```typescript
1611
+ // Get current active connections
1612
+ console.log(`Active connections: ${metrics.connections.active()}`);
1613
+
1614
+ // Get total connections since start
1615
+ console.log(`Total connections: ${metrics.connections.total()}`);
1603
1616
 
1604
1617
  // Get connections by route
1605
- const routeConnections = stats.getConnectionsByRoute();
1618
+ const routeConnections = metrics.connections.byRoute();
1606
1619
  for (const [route, count] of routeConnections) {
1607
1620
  console.log(`Route ${route}: ${count} connections`);
1608
1621
  }
1609
1622
 
1610
1623
  // Get connections by IP address
1611
- const ipConnections = stats.getConnectionsByIP();
1624
+ const ipConnections = metrics.connections.byIP();
1612
1625
  for (const [ip, count] of ipConnections) {
1613
1626
  console.log(`IP ${ip}: ${count} connections`);
1614
1627
  }
1628
+
1629
+ // Get top IPs by connection count
1630
+ const topIPs = metrics.connections.topIPs(10);
1631
+ topIPs.forEach(({ ip, count }) => {
1632
+ console.log(`${ip}: ${count} connections`);
1633
+ });
1615
1634
  ```
1616
1635
 
1617
- ### Available Metrics
1636
+ ### Throughput Metrics
1618
1637
 
1619
- The `IProxyStats` interface provides the following methods:
1638
+ Real-time and historical throughput data with customizable time windows:
1620
1639
 
1621
- - `getActiveConnections()`: Current number of active connections
1622
- - `getTotalConnections()`: Total connections handled since proxy start
1623
- - `getRequestsPerSecond()`: Current requests per second (1-minute average)
1624
- - `getThroughput()`: Total bytes transferred (in/out)
1625
- - `getConnectionsByRoute()`: Connection count per route
1626
- - `getConnectionsByIP()`: Connection count per client IP
1640
+ ```typescript
1641
+ // Get instant throughput (last 1 second)
1642
+ const instant = metrics.throughput.instant();
1643
+ console.log(`Current: ${instant.in} bytes/sec in, ${instant.out} bytes/sec out`);
1644
+
1645
+ // Get recent throughput (last 10 seconds average)
1646
+ const recent = metrics.throughput.recent();
1647
+ console.log(`Recent: ${recent.in} bytes/sec in, ${recent.out} bytes/sec out`);
1648
+
1649
+ // Get average throughput (last 60 seconds)
1650
+ const average = metrics.throughput.average();
1651
+ console.log(`Average: ${average.in} bytes/sec in, ${average.out} bytes/sec out`);
1652
+
1653
+ // Get custom time window (e.g., last 5 minutes)
1654
+ const custom = metrics.throughput.custom(300);
1655
+ console.log(`5-min avg: ${custom.in} bytes/sec in, ${custom.out} bytes/sec out`);
1656
+
1657
+ // Get throughput history for graphing
1658
+ const history = metrics.throughput.history(300); // Last 5 minutes
1659
+ history.forEach(point => {
1660
+ console.log(`${new Date(point.timestamp)}: ${point.in} in, ${point.out} out`);
1661
+ });
1662
+
1663
+ // Get throughput by route
1664
+ const routeThroughput = metrics.throughput.byRoute(60); // Last 60 seconds
1665
+ routeThroughput.forEach((stats, route) => {
1666
+ console.log(`Route ${route}: ${stats.in} in, ${stats.out} out bytes/sec`);
1667
+ });
1627
1668
 
1628
- Additional extended methods available:
1669
+ // Get throughput by IP
1670
+ const ipThroughput = metrics.throughput.byIP(60);
1671
+ ipThroughput.forEach((stats, ip) => {
1672
+ console.log(`IP ${ip}: ${stats.in} in, ${stats.out} out bytes/sec`);
1673
+ });
1674
+ ```
1629
1675
 
1630
- - `getThroughputRate()`: Bytes per second rate for the last minute
1631
- - `getTopIPs(limit?: number)`: Get top IPs by connection count
1632
- - `isIPBlocked(ip: string, maxConnectionsPerIP: number)`: Check if an IP has reached the connection limit
1676
+ ### Request Metrics
1633
1677
 
1634
- ### Extended Metrics Example
1678
+ Track request rates:
1635
1679
 
1636
1680
  ```typescript
1637
- const stats = proxy.getStats() as any; // Extended methods are available
1681
+ // Get requests per second
1682
+ console.log(`RPS: ${metrics.requests.perSecond()}`);
1638
1683
 
1639
- // Get throughput rate
1640
- const rate = stats.getThroughputRate();
1641
- console.log(`Incoming: ${rate.bytesInPerSec} bytes/sec`);
1642
- console.log(`Outgoing: ${rate.bytesOutPerSec} bytes/sec`);
1684
+ // Get requests per minute
1685
+ console.log(`RPM: ${metrics.requests.perMinute()}`);
1643
1686
 
1644
- // Get top 10 IPs by connection count
1645
- const topIPs = stats.getTopIPs(10);
1646
- topIPs.forEach(({ ip, connections }) => {
1647
- console.log(`${ip}: ${connections} connections`);
1648
- });
1687
+ // Get total requests
1688
+ console.log(`Total requests: ${metrics.requests.total()}`);
1689
+ ```
1649
1690
 
1650
- // Check if an IP should be rate limited
1651
- if (stats.isIPBlocked('192.168.1.100', 100)) {
1652
- console.log('IP has too many connections');
1653
- }
1691
+ ### Cumulative Totals
1692
+
1693
+ Track total bytes transferred and connections:
1694
+
1695
+ ```typescript
1696
+ // Get total bytes
1697
+ console.log(`Total bytes in: ${metrics.totals.bytesIn()}`);
1698
+ console.log(`Total bytes out: ${metrics.totals.bytesOut()}`);
1699
+ console.log(`Total connections: ${metrics.totals.connections()}`);
1654
1700
  ```
1655
1701
 
1656
- ### Monitoring Example
1702
+ ### Performance Percentiles
1703
+
1704
+ Get percentile statistics (when implemented):
1657
1705
 
1658
1706
  ```typescript
1659
- // Create a monitoring loop
1707
+ // Connection duration percentiles
1708
+ const durations = metrics.percentiles.connectionDuration();
1709
+ console.log(`Connection durations - P50: ${durations.p50}ms, P95: ${durations.p95}ms, P99: ${durations.p99}ms`);
1710
+
1711
+ // Bytes transferred percentiles
1712
+ const bytes = metrics.percentiles.bytesTransferred();
1713
+ console.log(`Bytes in - P50: ${bytes.in.p50}, P95: ${bytes.in.p95}, P99: ${bytes.in.p99}`);
1714
+ console.log(`Bytes out - P50: ${bytes.out.p50}, P95: ${bytes.out.p95}, P99: ${bytes.out.p99}`);
1715
+ ```
1716
+
1717
+ ### Complete Monitoring Example
1718
+
1719
+ ```typescript
1720
+ // Create a monitoring dashboard
1660
1721
  setInterval(() => {
1661
- const stats = proxy.getStats();
1722
+ const metrics = proxy.getMetrics();
1662
1723
 
1663
1724
  // Log key metrics
1664
1725
  console.log({
1665
1726
  timestamp: new Date().toISOString(),
1666
- activeConnections: stats.getActiveConnections(),
1667
- rps: stats.getRequestsPerSecond(),
1668
- throughput: stats.getThroughput()
1727
+ connections: {
1728
+ active: metrics.connections.active(),
1729
+ total: metrics.connections.total()
1730
+ },
1731
+ throughput: {
1732
+ instant: metrics.throughput.instant(),
1733
+ average: metrics.throughput.average()
1734
+ },
1735
+ requests: {
1736
+ rps: metrics.requests.perSecond(),
1737
+ total: metrics.requests.total()
1738
+ },
1739
+ totals: {
1740
+ bytesIn: metrics.totals.bytesIn(),
1741
+ bytesOut: metrics.totals.bytesOut()
1742
+ }
1669
1743
  });
1670
1744
 
1671
- // Check for high connection counts from specific IPs
1672
- const ipConnections = stats.getConnectionsByIP();
1673
- for (const [ip, count] of ipConnections) {
1745
+ // Alert on high connection counts
1746
+ const topIPs = metrics.connections.topIPs(5);
1747
+ topIPs.forEach(({ ip, count }) => {
1674
1748
  if (count > 100) {
1675
1749
  console.warn(`High connection count from ${ip}: ${count}`);
1676
1750
  }
1751
+ });
1752
+
1753
+ // Alert on high throughput
1754
+ const instant = metrics.throughput.instant();
1755
+ if (instant.in > 100_000_000) { // 100 MB/s
1756
+ console.warn(`High incoming throughput: ${instant.in} bytes/sec`);
1677
1757
  }
1678
1758
  }, 10000); // Every 10 seconds
1679
1759
  ```
1680
1760
 
1681
1761
  ### Exporting Metrics
1682
1762
 
1683
- You can export metrics in various formats for external monitoring systems:
1763
+ Export metrics in various formats for external monitoring systems:
1684
1764
 
1685
1765
  ```typescript
1686
1766
  // Export as JSON
1687
1767
  app.get('/metrics.json', (req, res) => {
1688
- const stats = proxy.getStats();
1768
+ const metrics = proxy.getMetrics();
1689
1769
  res.json({
1690
- activeConnections: stats.getActiveConnections(),
1691
- totalConnections: stats.getTotalConnections(),
1692
- requestsPerSecond: stats.getRequestsPerSecond(),
1693
- throughput: stats.getThroughput(),
1694
- connectionsByRoute: Object.fromEntries(stats.getConnectionsByRoute()),
1695
- connectionsByIP: Object.fromEntries(stats.getConnectionsByIP())
1770
+ connections: {
1771
+ active: metrics.connections.active(),
1772
+ total: metrics.connections.total(),
1773
+ byRoute: Object.fromEntries(metrics.connections.byRoute()),
1774
+ byIP: Object.fromEntries(metrics.connections.byIP())
1775
+ },
1776
+ throughput: {
1777
+ instant: metrics.throughput.instant(),
1778
+ recent: metrics.throughput.recent(),
1779
+ average: metrics.throughput.average()
1780
+ },
1781
+ requests: {
1782
+ perSecond: metrics.requests.perSecond(),
1783
+ perMinute: metrics.requests.perMinute(),
1784
+ total: metrics.requests.total()
1785
+ },
1786
+ totals: {
1787
+ bytesIn: metrics.totals.bytesIn(),
1788
+ bytesOut: metrics.totals.bytesOut(),
1789
+ connections: metrics.totals.connections()
1790
+ }
1696
1791
  });
1697
1792
  });
1698
1793
 
1699
1794
  // Export as Prometheus format
1700
1795
  app.get('/metrics', (req, res) => {
1701
- const stats = proxy.getStats();
1796
+ const metrics = proxy.getMetrics();
1797
+ const instant = metrics.throughput.instant();
1798
+
1702
1799
  res.set('Content-Type', 'text/plain');
1703
1800
  res.send(`
1704
- # HELP smartproxy_active_connections Current active connections
1705
- # TYPE smartproxy_active_connections gauge
1706
- smartproxy_active_connections ${stats.getActiveConnections()}
1801
+ # HELP smartproxy_connections_active Current active connections
1802
+ # TYPE smartproxy_connections_active gauge
1803
+ smartproxy_connections_active ${metrics.connections.active()}
1804
+
1805
+ # HELP smartproxy_connections_total Total connections since start
1806
+ # TYPE smartproxy_connections_total counter
1807
+ smartproxy_connections_total ${metrics.connections.total()}
1808
+
1809
+ # HELP smartproxy_throughput_bytes_per_second Current throughput in bytes per second
1810
+ # TYPE smartproxy_throughput_bytes_per_second gauge
1811
+ smartproxy_throughput_bytes_per_second{direction="in"} ${instant.in}
1812
+ smartproxy_throughput_bytes_per_second{direction="out"} ${instant.out}
1707
1813
 
1708
1814
  # HELP smartproxy_requests_per_second Current requests per second
1709
1815
  # TYPE smartproxy_requests_per_second gauge
1710
- smartproxy_requests_per_second ${stats.getRequestsPerSecond()}
1816
+ smartproxy_requests_per_second ${metrics.requests.perSecond()}
1711
1817
 
1712
- # HELP smartproxy_bytes_in Total bytes received
1713
- # TYPE smartproxy_bytes_in counter
1714
- smartproxy_bytes_in ${stats.getThroughput().bytesIn}
1715
-
1716
- # HELP smartproxy_bytes_out Total bytes sent
1717
- # TYPE smartproxy_bytes_out counter
1718
- smartproxy_bytes_out ${stats.getThroughput().bytesOut}
1818
+ # HELP smartproxy_bytes_total Total bytes transferred
1819
+ # TYPE smartproxy_bytes_total counter
1820
+ smartproxy_bytes_total{direction="in"} ${metrics.totals.bytesIn()}
1821
+ smartproxy_bytes_total{direction="out"} ${metrics.totals.bytesOut()}
1719
1822
  `);
1720
1823
  });
1721
1824
  ```
1722
1825
 
1826
+ ### Metrics API Reference
1827
+
1828
+ The metrics API is organized into logical groups:
1829
+
1830
+ ```typescript
1831
+ interface IMetrics {
1832
+ connections: {
1833
+ active(): number;
1834
+ total(): number;
1835
+ byRoute(): Map<string, number>;
1836
+ byIP(): Map<string, number>;
1837
+ topIPs(limit?: number): Array<{ ip: string; count: number }>;
1838
+ };
1839
+
1840
+ throughput: {
1841
+ instant(): IThroughputData; // Last 1 second
1842
+ recent(): IThroughputData; // Last 10 seconds
1843
+ average(): IThroughputData; // Last 60 seconds
1844
+ custom(seconds: number): IThroughputData;
1845
+ history(seconds: number): Array<IThroughputHistoryPoint>;
1846
+ byRoute(windowSeconds?: number): Map<string, IThroughputData>;
1847
+ byIP(windowSeconds?: number): Map<string, IThroughputData>;
1848
+ };
1849
+
1850
+ requests: {
1851
+ perSecond(): number;
1852
+ perMinute(): number;
1853
+ total(): number;
1854
+ };
1855
+
1856
+ totals: {
1857
+ bytesIn(): number;
1858
+ bytesOut(): number;
1859
+ connections(): number;
1860
+ };
1861
+
1862
+ percentiles: {
1863
+ connectionDuration(): { p50: number; p95: number; p99: number };
1864
+ bytesTransferred(): {
1865
+ in: { p50: number; p95: number; p99: number };
1866
+ out: { p50: number; p95: number; p99: number };
1867
+ };
1868
+ };
1869
+ }
1870
+ ```
1871
+
1872
+ Where `IThroughputData` is:
1873
+ ```typescript
1874
+ interface IThroughputData {
1875
+ in: number; // Bytes per second incoming
1876
+ out: number; // Bytes per second outgoing
1877
+ }
1878
+ ```
1879
+
1880
+ And `IThroughputHistoryPoint` is:
1881
+ ```typescript
1882
+ interface IThroughputHistoryPoint {
1883
+ timestamp: number; // Unix timestamp in milliseconds
1884
+ in: number; // Bytes per second at this point
1885
+ out: number; // Bytes per second at this point
1886
+ }
1887
+ ```
1888
+
1723
1889
  ## Other Components
1724
1890
 
1725
1891
  While SmartProxy provides a unified API for most needs, you can also use individual components: