diff --git a/changelog.md b/changelog.md index d043ac9..8f3bc13 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,14 @@ # Changelog +## 2026-02-13 - 5.2.0 - feat(monitoring) +add throughput metrics and expose them in ops UI + +- MetricsManager now reports bytesInPerSecond and bytesOutPerSecond as part of throughput +- Extended IServerStats with requestsPerSecond and throughput {bytesIn, bytesOut, bytesInPerSecond, bytesOutPerSecond} +- Stats handler updated to include requestsPerSecond and throughput; fallback stats initialize throughput fields to zero +- Web UI ops overview displays Throughput In/Out (bits/s) and total bytes with new formatting helper +- Bumped dependency @push.rocks/smartproxy to ^23.1.6 + ## 2026-02-13 - 5.1.0 - feat(acme) Integrate SmartAcme DNS-01 handling and add certificate provisioning for SmartProxy diff --git a/package.json b/package.json index 57d4be2..cff8639 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "@push.rocks/smartnetwork": "^4.4.0", "@push.rocks/smartpath": "^6.0.0", "@push.rocks/smartpromise": "^4.2.3", - "@push.rocks/smartproxy": "^23.1.5", + "@push.rocks/smartproxy": "^23.1.6", "@push.rocks/smartradius": "^1.1.1", "@push.rocks/smartrequest": "^5.0.1", "@push.rocks/smartrx": "^3.0.10", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5deeb78..a6aa853 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -75,8 +75,8 @@ importers: specifier: ^4.2.3 version: 4.2.3 '@push.rocks/smartproxy': - specifier: ^23.1.5 - version: 23.1.5(@push.rocks/smartserve@2.0.1)(socks@2.8.7) + specifier: ^23.1.6 + version: 23.1.6(@push.rocks/smartserve@2.0.1)(socks@2.8.7) '@push.rocks/smartradius': specifier: ^1.1.1 version: 1.1.1 @@ -1040,8 +1040,8 @@ packages: '@push.rocks/smartpromise@4.2.3': resolution: {integrity: sha512-Ycg/TJR+tMt+S3wSFurOpEoW6nXv12QBtKXgBcjMZ4RsdO28geN46U09osPn9N9WuwQy1PkmTV5J/V4F9U8qEw==} - '@push.rocks/smartproxy@23.1.5': - resolution: {integrity: sha512-Ak8jUm0XMQgHO57syoP+DkeKiw4GQwq4uQuLxoUj42w95a0liOQ3WQTKoHHNlbRjlCzFjszHXNh+D+7GW1IlXA==} + '@push.rocks/smartproxy@23.1.6': + resolution: {integrity: sha512-cwTK4d7vOP0nEZzkZSg9Ua7R+J7SIGId9G815GNTRYYZP20TZbvmWDZW/1gf2lw3AuAy2MRIJMPO2BZ7JnZckw==} '@push.rocks/smartpuppeteer@2.0.5': resolution: {integrity: sha512-yK/qSeWVHIGWRp3c8S5tfdGP6WCKllZC4DR8d8CQlEjszOSBmHtlTdyyqOMBZ/BA4kd+eU5f3A1r4K2tGYty1g==} @@ -6441,7 +6441,7 @@ snapshots: '@push.rocks/smartpromise@4.2.3': {} - '@push.rocks/smartproxy@23.1.5(@push.rocks/smartserve@2.0.1)(socks@2.8.7)': + '@push.rocks/smartproxy@23.1.6(@push.rocks/smartserve@2.0.1)(socks@2.8.7)': dependencies: '@push.rocks/lik': 6.2.2 '@push.rocks/smartacme': 8.0.0(@push.rocks/smartserve@2.0.1)(socks@2.8.7) diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 03f4e3a..4c7415a 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@serve.zone/dcrouter', - version: '5.1.0', + version: '5.2.0', description: 'A multifaceted routing service handling mail and SMS delivery functions.' } diff --git a/ts/monitoring/classes.metricsmanager.ts b/ts/monitoring/classes.metricsmanager.ts index 427fe1f..6820ff7 100644 --- a/ts/monitoring/classes.metricsmanager.ts +++ b/ts/monitoring/classes.metricsmanager.ts @@ -147,8 +147,10 @@ export class MetricsManager { requestsPerSecond: proxyMetrics ? proxyMetrics.requests.perSecond() : 0, throughput: proxyMetrics ? { bytesIn: proxyMetrics.totals.bytesIn(), - bytesOut: proxyMetrics.totals.bytesOut() - } : { bytesIn: 0, bytesOut: 0 }, + bytesOut: proxyMetrics.totals.bytesOut(), + bytesInPerSecond: proxyMetrics.throughput.instant().in, + bytesOutPerSecond: proxyMetrics.throughput.instant().out, + } : { bytesIn: 0, bytesOut: 0, bytesInPerSecond: 0, bytesOutPerSecond: 0 }, }; }); } diff --git a/ts/opsserver/handlers/stats.handler.ts b/ts/opsserver/handlers/stats.handler.ts index a582613..0421611 100644 --- a/ts/opsserver/handlers/stats.handler.ts +++ b/ts/opsserver/handlers/stats.handler.ts @@ -27,6 +27,8 @@ export class StatsHandler { cpuUsage: stats.cpuUsage, activeConnections: stats.activeConnections, totalConnections: stats.totalConnections, + requestsPerSecond: stats.requestsPerSecond, + throughput: stats.throughput, }, history: dataArg.includeHistory ? stats.history : undefined, }; @@ -191,6 +193,8 @@ export class StatsHandler { cpuUsage: stats.cpuUsage, activeConnections: stats.activeConnections, totalConnections: stats.totalConnections, + requestsPerSecond: stats.requestsPerSecond, + throughput: stats.throughput, }; }) ); @@ -301,6 +305,7 @@ export class StatsHandler { requestsPerSecond: number; activeConnections: number; totalConnections: number; + throughput: interfaces.data.IServerStats['throughput']; history: Array<{ timestamp: number; value: number; @@ -316,15 +321,16 @@ export class StatsHandler { requestsPerSecond: serverStats.requestsPerSecond, activeConnections: serverStats.activeConnections, totalConnections: serverStats.totalConnections, + throughput: serverStats.throughput, history: [], // TODO: Implement history tracking }; } - + // Fallback to basic stats if MetricsManager not available const uptime = process.uptime(); const memUsage = process.memoryUsage(); const cpuUsage = plugins.os.loadavg()[0] * 100 / plugins.os.cpus().length; - + return { uptime, cpuUsage: { @@ -340,6 +346,7 @@ export class StatsHandler { requestsPerSecond: 0, activeConnections: 0, totalConnections: 0, + throughput: { bytesIn: 0, bytesOut: 0, bytesInPerSecond: 0, bytesOutPerSecond: 0 }, history: [], }; } diff --git a/ts_interfaces/data/stats.ts b/ts_interfaces/data/stats.ts index ce60c83..71e867f 100644 --- a/ts_interfaces/data/stats.ts +++ b/ts_interfaces/data/stats.ts @@ -17,6 +17,13 @@ export interface IServerStats { }; activeConnections: number; totalConnections: number; + requestsPerSecond: number; + throughput: { + bytesIn: number; + bytesOut: number; + bytesInPerSecond: number; + bytesOutPerSecond: number; + }; } export interface IEmailStats { diff --git a/ts_web/00_commitinfo_data.ts b/ts_web/00_commitinfo_data.ts index 03f4e3a..4c7415a 100644 --- a/ts_web/00_commitinfo_data.ts +++ b/ts_web/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@serve.zone/dcrouter', - version: '5.1.0', + version: '5.2.0', description: 'A multifaceted routing service handling mail and SMS delivery functions.' } diff --git a/ts_web/elements/ops-view-overview.ts b/ts_web/elements/ops-view-overview.ts index c4a5a83..52e3072 100644 --- a/ts_web/elements/ops-view-overview.ts +++ b/ts_web/elements/ops-view-overview.ts @@ -126,12 +126,26 @@ export class OpsViewOverview extends DeesElement { const units = ['B', 'KB', 'MB', 'GB', 'TB']; let size = bytes; let unitIndex = 0; - + while (size >= 1024 && unitIndex < units.length - 1) { size /= 1024; unitIndex++; } - + + return `${size.toFixed(1)} ${units[unitIndex]}`; + } + + private formatBitsPerSecond(bytesPerSecond: number): string { + const bitsPerSecond = bytesPerSecond * 8; + const units = ['bit/s', 'kbit/s', 'Mbit/s', 'Gbit/s']; + let size = bitsPerSecond; + let unitIndex = 0; + + while (size >= 1000 && unitIndex < units.length - 1) { + size /= 1000; + unitIndex++; + } + return `${size.toFixed(1)} ${units[unitIndex]}`; } @@ -162,6 +176,24 @@ export class OpsViewOverview extends DeesElement { color: '#3b82f6', description: `Total: ${this.statsState.serverStats.totalConnections}`, }, + { + id: 'throughputIn', + title: 'Throughput In', + value: this.formatBitsPerSecond(this.statsState.serverStats.throughput?.bytesInPerSecond || 0), + type: 'text', + icon: 'download', + color: '#22c55e', + description: `Total: ${this.formatBytes(this.statsState.serverStats.throughput?.bytesIn || 0)}`, + }, + { + id: 'throughputOut', + title: 'Throughput Out', + value: this.formatBitsPerSecond(this.statsState.serverStats.throughput?.bytesOutPerSecond || 0), + type: 'text', + icon: 'upload', + color: '#8b5cf6', + description: `Total: ${this.formatBytes(this.statsState.serverStats.throughput?.bytesOut || 0)}`, + }, { id: 'cpu', title: 'CPU Usage',