UNPKG

@push.rocks/smartproxy

Version:

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.

305 lines 25.1 kB
/** * Adapts Rust JSON metrics to the IMetrics interface. * * Polls the Rust binary periodically via the bridge and caches the result. * All IMetrics getters read from the cache synchronously. * * Rust Metrics JSON fields (camelCase via serde): * activeConnections, totalConnections, bytesIn, bytesOut, * throughputInBytesPerSec, throughputOutBytesPerSec, * routes: { [routeName]: { activeConnections, totalConnections, bytesIn, bytesOut, ... } } */ export class RustMetricsAdapter { bridge; cache = null; pollTimer = null; pollIntervalMs; constructor(bridge, pollIntervalMs = 1000) { this.bridge = bridge; this.pollIntervalMs = pollIntervalMs; } /** * Poll Rust for metrics once. Can be awaited to ensure cache is fresh. */ async poll() { try { this.cache = await this.bridge.getMetrics(); } catch { // Ignore poll errors (bridge may be shutting down) } } startPolling() { if (this.pollTimer) return; // Immediate first poll so cache is populated ASAP this.poll(); this.pollTimer = setInterval(() => { this.poll(); }, this.pollIntervalMs); if (this.pollTimer.unref) { this.pollTimer.unref(); } } stopPolling() { if (this.pollTimer) { clearInterval(this.pollTimer); this.pollTimer = null; } } // --- IMetrics implementation --- connections = { active: () => { return this.cache?.activeConnections ?? 0; }, total: () => { return this.cache?.totalConnections ?? 0; }, byRoute: () => { const result = new Map(); if (this.cache?.routes) { for (const [name, rm] of Object.entries(this.cache.routes)) { result.set(name, rm.activeConnections ?? 0); } } return result; }, byIP: () => { const result = new Map(); if (this.cache?.ips) { for (const [ip, im] of Object.entries(this.cache.ips)) { result.set(ip, im.activeConnections ?? 0); } } return result; }, topIPs: (limit = 10) => { const result = []; if (this.cache?.ips) { for (const [ip, im] of Object.entries(this.cache.ips)) { result.push({ ip, count: im.activeConnections ?? 0 }); } } result.sort((a, b) => b.count - a.count); return result.slice(0, limit); }, domainRequestsByIP: () => { const result = new Map(); if (this.cache?.ips) { for (const [ip, im] of Object.entries(this.cache.ips)) { const dr = im.domainRequests; if (dr && typeof dr === 'object') { const domainMap = new Map(); for (const [domain, count] of Object.entries(dr)) { domainMap.set(domain, count); } if (domainMap.size > 0) { result.set(ip, domainMap); } } } } return result; }, topDomainRequests: (limit = 20) => { const result = []; if (this.cache?.ips) { for (const [ip, im] of Object.entries(this.cache.ips)) { const dr = im.domainRequests; if (dr && typeof dr === 'object') { for (const [domain, count] of Object.entries(dr)) { result.push({ ip, domain, count: count }); } } } } result.sort((a, b) => b.count - a.count); return result.slice(0, limit); }, frontendProtocols: () => { const fp = this.cache?.frontendProtocols; return { h1Active: fp?.h1Active ?? 0, h1Total: fp?.h1Total ?? 0, h2Active: fp?.h2Active ?? 0, h2Total: fp?.h2Total ?? 0, h3Active: fp?.h3Active ?? 0, h3Total: fp?.h3Total ?? 0, wsActive: fp?.wsActive ?? 0, wsTotal: fp?.wsTotal ?? 0, otherActive: fp?.otherActive ?? 0, otherTotal: fp?.otherTotal ?? 0, }; }, backendProtocols: () => { const bp = this.cache?.backendProtocols; return { h1Active: bp?.h1Active ?? 0, h1Total: bp?.h1Total ?? 0, h2Active: bp?.h2Active ?? 0, h2Total: bp?.h2Total ?? 0, h3Active: bp?.h3Active ?? 0, h3Total: bp?.h3Total ?? 0, wsActive: bp?.wsActive ?? 0, wsTotal: bp?.wsTotal ?? 0, otherActive: bp?.otherActive ?? 0, otherTotal: bp?.otherTotal ?? 0, }; }, }; throughput = { instant: () => { return { in: this.cache?.throughputInBytesPerSec ?? 0, out: this.cache?.throughputOutBytesPerSec ?? 0, }; }, recent: () => { return { in: this.cache?.throughputRecentInBytesPerSec ?? 0, out: this.cache?.throughputRecentOutBytesPerSec ?? 0, }; }, average: () => { return this.throughput.instant(); }, custom: (_seconds) => { return this.throughput.instant(); }, history: (seconds) => { if (!this.cache?.throughputHistory) return []; return this.cache.throughputHistory.slice(-seconds).map((p) => ({ timestamp: p.timestampMs, in: p.bytesIn, out: p.bytesOut, })); }, byRoute: (_windowSeconds) => { const result = new Map(); if (this.cache?.routes) { for (const [name, rm] of Object.entries(this.cache.routes)) { result.set(name, { in: rm.throughputInBytesPerSec ?? 0, out: rm.throughputOutBytesPerSec ?? 0, }); } } return result; }, byIP: (_windowSeconds) => { const result = new Map(); if (this.cache?.ips) { for (const [ip, im] of Object.entries(this.cache.ips)) { result.set(ip, { in: im.throughputInBytesPerSec ?? 0, out: im.throughputOutBytesPerSec ?? 0, }); } } return result; }, }; requests = { perSecond: () => { return this.cache?.httpRequestsPerSec ?? 0; }, perMinute: () => { return (this.cache?.httpRequestsPerSecRecent ?? 0) * 60; }, total: () => { return this.cache?.totalHttpRequests ?? this.cache?.totalConnections ?? 0; }, byDomain: () => { const result = new Map(); if (this.cache?.httpDomainRequests) { for (const [domain, metrics] of Object.entries(this.cache.httpDomainRequests)) { result.set(domain, { perSecond: metrics.requestsPerSecond ?? 0, lastMinute: metrics.requestsLastMinute ?? 0, }); } } return result; }, }; totals = { bytesIn: () => { return this.cache?.bytesIn ?? 0; }, bytesOut: () => { return this.cache?.bytesOut ?? 0; }, connections: () => { return this.cache?.totalConnections ?? 0; }, }; backends = { byBackend: () => { const result = new Map(); if (this.cache?.backends) { for (const [key, bm] of Object.entries(this.cache.backends)) { const totalTimeUs = bm.totalConnectTimeUs ?? 0; const count = bm.connectCount ?? 0; const poolHits = bm.poolHits ?? 0; const poolMisses = bm.poolMisses ?? 0; const poolTotal = poolHits + poolMisses; result.set(key, { protocol: bm.protocol ?? 'unknown', activeConnections: bm.activeConnections ?? 0, totalConnections: bm.totalConnections ?? 0, connectErrors: bm.connectErrors ?? 0, handshakeErrors: bm.handshakeErrors ?? 0, requestErrors: bm.requestErrors ?? 0, avgConnectTimeMs: count > 0 ? (totalTimeUs / count) / 1000 : 0, poolHitRate: poolTotal > 0 ? poolHits / poolTotal : 0, h2Failures: bm.h2Failures ?? 0, }); } } return result; }, protocols: () => { const result = new Map(); if (this.cache?.backends) { for (const [key, bm] of Object.entries(this.cache.backends)) { result.set(key, bm.protocol ?? 'unknown'); } } return result; }, topByErrors: (limit = 10) => { const result = []; if (this.cache?.backends) { for (const [key, bm] of Object.entries(this.cache.backends)) { const errors = (bm.connectErrors ?? 0) + (bm.handshakeErrors ?? 0) + (bm.requestErrors ?? 0); if (errors > 0) result.push({ backend: key, errors }); } } result.sort((a, b) => b.errors - a.errors); return result.slice(0, limit); }, detectedProtocols: () => { return this.cache?.detectedProtocols ?? []; }, }; udp = { activeSessions: () => this.cache?.activeUdpSessions ?? 0, totalSessions: () => this.cache?.totalUdpSessions ?? 0, datagramsIn: () => this.cache?.totalDatagramsIn ?? 0, datagramsOut: () => this.cache?.totalDatagramsOut ?? 0, }; percentiles = { connectionDuration: () => { return { p50: 0, p95: 0, p99: 0 }; }, bytesTransferred: () => { return { in: { p50: 0, p95: 0, p99: 0 }, out: { p50: 0, p95: 0, p99: 0 }, }; }, }; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVzdC1tZXRyaWNzLWFkYXB0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9wcm94aWVzL3NtYXJ0LXByb3h5L3J1c3QtbWV0cmljcy1hZGFwdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUlBOzs7Ozs7Ozs7O0dBVUc7QUFDSCxNQUFNLE9BQU8sa0JBQWtCO0lBQ3JCLE1BQU0sQ0FBa0I7SUFDeEIsS0FBSyxHQUFnQyxJQUFJLENBQUM7SUFDMUMsU0FBUyxHQUEwQyxJQUFJLENBQUM7SUFDeEQsY0FBYyxDQUFTO0lBRS9CLFlBQVksTUFBdUIsRUFBRSxjQUFjLEdBQUcsSUFBSTtRQUN4RCxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJQUFJLENBQUMsY0FBYyxHQUFHLGNBQWMsQ0FBQztJQUN2QyxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsSUFBSTtRQUNmLElBQUksQ0FBQztZQUNILElBQUksQ0FBQyxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQzlDLENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUCxtREFBbUQ7UUFDckQsQ0FBQztJQUNILENBQUM7SUFFTSxZQUFZO1FBQ2pCLElBQUksSUFBSSxDQUFDLFNBQVM7WUFBRSxPQUFPO1FBQzNCLGtEQUFrRDtRQUNsRCxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDWixJQUFJLENBQUMsU0FBUyxHQUFHLFdBQVcsQ0FBQyxHQUFHLEVBQUU7WUFDaEMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2QsQ0FBQyxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUN4QixJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDekIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUN6QixDQUFDO0lBQ0gsQ0FBQztJQUVNLFdBQVc7UUFD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