fix: command "status" was displaying wrong speed
Massimo Melina committed
Apr 16, 2026 at 14:21 UTC
4fa8c0e601739f0c238236dd08a0e583e36648e1
6 files changed
+18
-21
admin/src/MonitorPage.ts
+4
-7
@@ -55,8 +55,8 @@ function MoreInfo() {
55
.then(yes => yes && apiCall('clear_persistent', { k: ['totalSent', 'totalGot'] })
56
.then(() => alertDialog("Done", 'success'), alertDialog))
57
}),
58
- pair('outSpeed', { label: "Output", render: formatSpeedK, minWidth: '8.5em' }),
59
- pair('inSpeed', { label: "Input", render: formatSpeedK, minWidth: '8.5em' }),
58
+ pair('outSpeedKb', { label: "Output", render: formatSpeedK, minWidth: '8.5em' }),
59
+ pair('inSpeedKb', { label: "Input", render: formatSpeedK, minWidth: '8.5em' }),
60
(allInfo || sm) && pair('ips', { label: "IPs", title: () => "Currently connected" }),
61
(md || allInfo && md || status?.http?.error) && pair('http', { label: "HTTP", render: port }),
62
(md || allInfo && md || status?.https?.error) && pair('https', { label: "HTTPS", render: port }),
@@ -221,15 +221,12 @@ function Connections() {
221
}
222
},
223
{
224
- field: 'outSpeed',
224
+ field: 'outSpeedKb',
225
headerName: "Speed",
226
width: 110,
227
hideUnder: 'sm',
228
type: 'number',
229
- renderCell: ({
230
- value,
231
- row
232
- }) => formatSpeedK(Math.max(value || 0, row.inSpeed || 0) || undefined),
229
+ renderCell: ({ value, row }) => formatSpeedK(Math.max(value || 0, row.inSpeedKb || 0) || undefined),
230
mergeRender: { sent: { fontSize: 'small', textAlign: 'right' } }
231
},
232
{
src/api.monitor.ts
+3
-3
@@ -5,7 +5,7 @@ import { Connection, disconnect, getConnections } from './connections'
5
import { apiAssertTypes, isLocalHost, safeDecodeURIComponent, shortenAgent, wait, wantArray } from './misc'
6
import { ApiHandlers } from './apiMiddleware'
7
import Koa from 'koa'
8
-import { totalGot, totalInSpeed, totalOutSpeed, totalSent } from './throttler'
8
+import { totalGot, totalInSpeedKb, totalOutSpeedKb, totalSent } from './throttler'
9
import { getCurrentUsername } from './auth'
10
import { SendListReadable } from './SendList'
11
import { storedMap } from './persistence'
@@ -94,8 +94,8 @@ export default {
94
while (1) {
95
const filtered = getConnections().filter(x => !ignore(x))
96
yield {
97
- outSpeed: totalOutSpeed,
98
- inSpeed: totalInSpeed,
97
+ outSpeedKb: totalOutSpeedKb,
98
+ inSpeedKb: totalInSpeedKb,
99
sent_got: [totalSent.get(), totalGot.get(), totalGotSentResetTime.get()] as const,
100
connections: filtered.length,
101
ips: _.uniqBy(filtered, x => x.ip).length,
src/commands.ts
+2
-2
@@ -200,8 +200,8 @@ const commands = {
200
const conn = (await apiMonitor.get_connection_stats().next()).value
201
if (conn) {
202
const {sent_got: sg} = conn
203
- console.log(`Speed ↑ ${formatSpeed(conn.outSpeed)} ↓ ${formatSpeed(conn.inSpeed)}`)
204
- console.log(`Transfered ↑ ${formatBytes(sg[0])} ↓ ${formatBytes(sg[1])} since ${formatTimestamp(sg[2])}`)
203
+ console.log(`Speed ↑ ${formatSpeed(conn.outSpeedKb * 1000)} ↓ ${formatSpeed(conn.inSpeedKb * 1000)}`)
204
+ console.log(`Transferred ↑ ${formatBytes(sg[0])} ↓ ${formatBytes(sg[1])} since ${formatTimestamp(sg[2])}`)
205
console.log(`Connections ${conn.connections} (${conn.ips} IPs)`)
206
}
207
}
src/connections.ts
+2
-2
@@ -10,8 +10,8 @@ export class Connection {
10
readonly started = new Date()
11
sent = 0 // socket-scoped, not request-scoped
12
got = 0
13
- outSpeed?: number
14
- inSpeed?: number
13
+ outSpeedKb?: number
14
+ inSpeedKb?: number
15
ctx?: Context // this is set externally, during koa middleware, using updateConnectionForCtx, but only for regular requests; some connections may never have a ctx
16
country?: string
17
private _cachedIp?: string
src/throttler.ts
+5
-5
@@ -56,7 +56,7 @@ export const throttler: Koa.Middleware = async (ctx, next) => {
56
const ts = conn[SymThrStr] as ThrottledStream
57
const outSpeed = roundSpeed(ts.getSpeed())
58
const { state } = ctx
59
- updateConnection(conn, { outSpeed, sent: conn.socket.bytesWritten },
59
+ updateConnection(conn, { outSpeedKb: outSpeed, sent: conn.socket.bytesWritten },
60
{ opProgress: state.opTotal && ((state.opOffset || 0) + (ts.getBytesSent() - offset) / state.opTotal) })
61
/* in case this stream stands still for a while (before the end), we'll have neither 'sent' or 'close' events,
62
* so who will take care to updateConnection? This artificial next-call will ensure just that */
@@ -100,8 +100,8 @@ export function roundSpeed(n: number) {
100
101
export const totalSent = storedMap.singleSync<number>('totalSent', 0)
102
export const totalGot = storedMap.singleSync<number>('totalGot', 0)
103
-export let totalOutSpeed = 0
104
-export let totalInSpeed = 0
103
+export let totalOutSpeedKb = 0
104
+export let totalInSpeedKb = 0
105
106
let lastSent: number | undefined
107
let lastGot: number | undefined
@@ -112,12 +112,12 @@ setInterval(() => {
112
last = now
113
{
114
const v = totalSent.get()
115
- totalOutSpeed = roundSpeed((v - (lastSent ?? v)) / past)
115
+ totalOutSpeedKb = roundSpeed((v - (lastSent ?? v)) / past) // lastSent is bytes, past is milliseconds, so the result is KB/s
116
lastSent = v
117
}
118
{
119
const v = totalGot.get()
120
- totalInSpeed = roundSpeed((v - (lastGot ?? v)) / past)
120
+ totalInSpeedKb = roundSpeed((v - (lastGot ?? v)) / past)
121
lastGot = v
122
}
123
}, 1000)
src/upload.ts
+2
-2
@@ -235,10 +235,10 @@ export function uploadWriter(base: VfsNode, baseUri: string, filename: string, c
235
const h = setInterval(() => {
236
const now = Date.now()
237
const got = bytesGot()
238
- const inSpeed = roundSpeed((got - lastGot) / (now - lastGotTime))
238
+ const inSpeedKb = roundSpeed((got - lastGot) / (now - lastGotTime))
239
lastGot = got
240
lastGotTime = now
241
- updateConnection(conn, { inSpeed, got }, { opProgress: (resume + got) / fullSize })
241
+ updateConnection(conn, { inSpeedKb, got }, { opProgress: (resume + got) / fullSize })
242
}, 1000)
243
const stopTracking = () => clearInterval(h)
244
writeStream.once('close', stopTracking)