Skip to content

Commit 7d85a2d

Browse files
committed
feat: add network speed display for nodes and fix log timestamp ordering
1 parent 59245b3 commit 7d85a2d

File tree

8 files changed

+55
-26
lines changed

8 files changed

+55
-26
lines changed

dashboard/public/statics/locales/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,7 @@
11011101
"usersTable.total": "Total",
11021102
"statistics.system": "System",
11031103
"statistics.totalTraffic": "Total Traffic",
1104+
"statistics.networkSpeed": "Network Speed",
11041105
"statistics.ramUsage": "RAM Usage",
11051106
"statistics.cpuUsage": "CPU Usage",
11061107
"statistics.cores": "cores",

dashboard/public/statics/locales/fa.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,7 @@
944944
"usersTable.total": "مجموع",
945945
"statistics.system": "سیستم",
946946
"statistics.totalTraffic": "کل ترافیک",
947+
"statistics.networkSpeed": "سرعت شبکه",
947948
"statistics.ramUsage": "مصرف رم",
948949
"statistics.cpuUsage": "مصرف پردازنده",
949950
"statistics.cores": "هسته",

dashboard/public/statics/locales/ru.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,7 @@
810810
"usersTable.total": "Всего",
811811
"statistics.system": "Система",
812812
"statistics.totalTraffic": "Общий трафик",
813+
"statistics.networkSpeed": "Скорость сети",
813814
"statistics.ramUsage": "Использование RAM",
814815
"statistics.cpuUsage": "Использование CPU",
815816
"statistics.cores": "ядер",

dashboard/public/statics/locales/zh.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,7 @@
846846
"usersTable.total": "总共",
847847
"statistics.system": "系统",
848848
"statistics.totalTraffic": "总流量",
849+
"statistics.networkSpeed": "网络速度",
849850
"statistics.ramUsage": "RAM 使用情况",
850851
"statistics.cpuUsage": "CPU 使用情况",
851852
"statistics.cores": "核心",

dashboard/src/components/goal-progress.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,4 @@ export function GoalProgress() {
101101
)
102102
}
103103

104+

dashboard/src/components/statistics/SystemStatisticsSection.tsx

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Card, CardContent } from '@/components/ui/card'
22
import { SystemStats, NodeRealtimeStats } from '@/service/api'
33
import { useTranslation } from 'react-i18next'
4-
import { Cpu, MemoryStick, Database, Upload, Download } from 'lucide-react'
4+
import { Cpu, MemoryStick, Database, Upload, Download, Activity } from 'lucide-react'
55
import { cn } from '@/lib/utils'
66
import useDirDetection from '@/hooks/use-dir-detection'
77
import { formatBytes } from '@/utils/formatByte'
@@ -14,45 +14,41 @@ export default function SystemStatisticsSection({ currentStats }: SystemStatisti
1414
const { t } = useTranslation()
1515
const dir = useDirDetection()
1616

17+
// Helper to check if stats are from a node (realtime stats)
18+
const isNodeStats = (stats: SystemStats | NodeRealtimeStats): stats is NodeRealtimeStats => {
19+
return 'incoming_bandwidth_speed' in stats
20+
}
21+
1722
const getTotalTrafficValue = () => {
1823
if (!currentStats) return 0
1924

20-
if ('incoming_bandwidth' in currentStats && 'outgoing_bandwidth' in currentStats) {
25+
if (isNodeStats(currentStats)) {
26+
// Node stats - use bandwidth speed
27+
return Number(currentStats.incoming_bandwidth_speed) + Number(currentStats.outgoing_bandwidth_speed)
28+
} else {
2129
// Master server stats - use total traffic
22-
const stats = currentStats as SystemStats
23-
return Number(stats.incoming_bandwidth) + Number(stats.outgoing_bandwidth)
24-
} else if ('incoming_bandwidth_speed' in currentStats && 'outgoing_bandwidth_speed' in currentStats) {
25-
// Node stats - for now, use speed values as proxy
26-
// Note: In a real implementation, you might want to accumulate these values over time
27-
const stats = currentStats as NodeRealtimeStats
28-
return Number(stats.incoming_bandwidth_speed) + Number(stats.outgoing_bandwidth_speed)
30+
return Number(currentStats.incoming_bandwidth) + Number(currentStats.outgoing_bandwidth)
2931
}
30-
31-
return 0
3232
}
3333

3434
const getIncomingBandwidth = () => {
3535
if (!currentStats) return 0
3636

37-
if ('incoming_bandwidth' in currentStats) {
38-
return Number(currentStats.incoming_bandwidth) || 0
39-
} else if ('incoming_bandwidth_speed' in currentStats) {
37+
if (isNodeStats(currentStats)) {
4038
return Number(currentStats.incoming_bandwidth_speed) || 0
39+
} else {
40+
return Number(currentStats.incoming_bandwidth) || 0
4141
}
42-
43-
return 0
4442
}
4543

4644
const getOutgoingBandwidth = () => {
4745
if (!currentStats) return 0
4846

49-
if ('outgoing_bandwidth' in currentStats) {
50-
return Number(currentStats.outgoing_bandwidth) || 0
51-
} else if ('outgoing_bandwidth_speed' in currentStats) {
47+
if (isNodeStats(currentStats)) {
5248
return Number(currentStats.outgoing_bandwidth_speed) || 0
49+
} else {
50+
return Number(currentStats.outgoing_bandwidth) || 0
5351
}
54-
55-
return 0
5652
}
5753

5854
const getMemoryUsage = () => {
@@ -170,7 +166,7 @@ export default function SystemStatisticsSection({ currentStats }: SystemStatisti
170166
</Card>
171167
</div>
172168

173-
{/* Total Traffic with Incoming/Outgoing Details */}
169+
{/* Total Traffic / Network Speed (depends on whether it's master or node stats) */}
174170
<div className="h-full w-full animate-fade-in" style={{ animationDuration: '600ms', animationDelay: '250ms' }}>
175171
<Card dir={dir} className="group relative h-full w-full overflow-hidden rounded-lg border transition-all duration-300 hover:shadow-lg">
176172
<div
@@ -184,18 +180,31 @@ export default function SystemStatisticsSection({ currentStats }: SystemStatisti
184180
<div className="mb-2 flex items-start justify-between sm:mb-3">
185181
<div className="flex items-center gap-2 sm:gap-3">
186182
<div className="rounded-lg bg-primary/10 p-1.5 sm:p-2">
187-
<Database className="h-4 w-4 text-primary sm:h-5 sm:w-5" />
183+
{currentStats && isNodeStats(currentStats) ? (
184+
<Activity className="h-4 w-4 text-primary sm:h-5 sm:w-5" />
185+
) : (
186+
<Database className="h-4 w-4 text-primary sm:h-5 sm:w-5" />
187+
)}
188188
</div>
189189
<div className="min-w-0 flex-1">
190-
<p className="truncate text-xs font-medium text-muted-foreground sm:text-sm">{t('statistics.totalTraffic')}</p>
190+
<p className="truncate text-xs font-medium text-muted-foreground sm:text-sm">
191+
{currentStats && isNodeStats(currentStats) ? t('statistics.networkSpeed') : t('statistics.totalTraffic')}
192+
</p>
191193
</div>
192194
</div>
193195
</div>
194196

195197
<div className="flex items-end justify-between gap-2">
196198
<div className="flex min-w-0 flex-1 items-center gap-1 sm:gap-2">
197199
<span dir="ltr" className="truncate text-xl font-bold transition-all duration-300 sm:text-2xl lg:text-3xl">
198-
{formatBytes(getTotalTrafficValue() || 0, 1)}
200+
{currentStats && isNodeStats(currentStats) ? (
201+
<>
202+
{formatBytes(getTotalTrafficValue() || 0, 1)}
203+
<span className="text-base font-normal text-muted-foreground sm:text-lg">/s</span>
204+
</>
205+
) : (
206+
formatBytes(getTotalTrafficValue() || 0, 1)
207+
)}
199208
</span>
200209
</div>
201210

@@ -205,12 +214,14 @@ export default function SystemStatisticsSection({ currentStats }: SystemStatisti
205214
<Download className="h-3 w-3" />
206215
<span dir="ltr" className="font-medium">
207216
{formatBytes(getIncomingBandwidth() || 0, 1)}
217+
{currentStats && isNodeStats(currentStats) && <span className="text-[10px]">/s</span>}
208218
</span>
209219
</div>
210220
<div className="flex items-center gap-1 rounded-md bg-muted/50 px-1.5 py-1 text-blue-600 dark:text-blue-400">
211221
<Upload className="h-3 w-3" />
212222
<span dir="ltr" className="font-medium">
213223
{formatBytes(getOutgoingBandwidth() || 0, 1)}
224+
{currentStats && isNodeStats(currentStats) && <span className="text-[10px]">/s</span>}
214225
</span>
215226
</div>
216227
</div>

dashboard/src/hooks/use-goal.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ export function useCurrentGoal() {
2626
})
2727
}
2828

29+

dashboard/src/pages/_dashboard.nodes.logs.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,19 @@ export default function NodeLogs() {
246246

247247
useEffect(() => {
248248
const logs = parseLogs(rawLogs.join('\n'))
249-
const filtered = handleFilter(logs)
249+
250+
// Sort logs by their extracted timestamps (not SSE arrival time)
251+
const sortedLogs = logs.sort((a, b) => {
252+
// Logs without timestamps go to the end
253+
if (!a.timestamp && !b.timestamp) return 0
254+
if (!a.timestamp) return 1
255+
if (!b.timestamp) return -1
256+
257+
// Sort by actual log timestamp
258+
return a.timestamp.getTime() - b.timestamp.getTime()
259+
})
260+
261+
const filtered = handleFilter(sortedLogs)
250262
setFilteredLogs(filtered)
251263
}, [rawLogs, search, lines, since, typeFilter])
252264

0 commit comments

Comments
 (0)