Skip to content

Commit 6627db4

Browse files
wip
Signed-off-by: Patrick José Pereira <patrickelectric@gmail.com>
1 parent 4f07075 commit 6627db4

File tree

2 files changed

+69
-79
lines changed

2 files changed

+69
-79
lines changed

core/frontend/src/views/ServiceManagerView.vue

Lines changed: 41 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@
458458
<template v-if="service_metrics">
459459
<!-- Current Values Summary -->
460460
<v-row class="mb-4">
461-
<v-col cols="6" sm="4" md="2">
461+
<v-col cols="6" sm="4">
462462
<v-card outlined class="text-center pa-3">
463463
<div class="text-h6 primary--text">
464464
{{ (service_metrics.cpu_percent ?? 0).toFixed(1) }}%
@@ -468,7 +468,7 @@
468468
</div>
469469
</v-card>
470470
</v-col>
471-
<v-col cols="6" sm="4" md="2">
471+
<v-col cols="6" sm="4">
472472
<v-card outlined class="text-center pa-3">
473473
<div class="text-h6 success--text">
474474
{{ (service_metrics.memory_mb ?? 0).toFixed(1) }} MB
@@ -478,7 +478,7 @@
478478
</div>
479479
</v-card>
480480
</v-col>
481-
<v-col cols="6" sm="4" md="2">
481+
<v-col cols="6" sm="4">
482482
<v-card outlined class="text-center pa-3">
483483
<div class="text-h6 info--text">
484484
{{ (service_metrics.swap_mb ?? 0).toFixed(1) }} MB
@@ -488,27 +488,17 @@
488488
</div>
489489
</v-card>
490490
</v-col>
491-
<v-col cols="6" sm="4" md="2">
491+
<v-col cols="6" sm="6">
492492
<v-card outlined class="text-center pa-3">
493493
<div class="text-h6 warning--text">
494-
{{ (service_metrics.io_read_rate_mbps ?? 0).toFixed(2) }} MB/s
494+
{{ formatDiskRate(service_metrics.io_read_rate_mbps, service_metrics.io_write_rate_mbps) }}
495495
</div>
496496
<div class="text-caption grey--text">
497-
Disk Read
497+
Disk I/O
498498
</div>
499499
</v-card>
500500
</v-col>
501-
<v-col cols="6" sm="4" md="2">
502-
<v-card outlined class="text-center pa-3">
503-
<div class="text-h6" style="color: #9C27B0">
504-
{{ (service_metrics.io_write_rate_mbps ?? 0).toFixed(2) }} MB/s
505-
</div>
506-
<div class="text-caption grey--text">
507-
Disk Write
508-
</div>
509-
</v-card>
510-
</v-col>
511-
<v-col cols="6" sm="4" md="2">
501+
<v-col cols="6" sm="6">
512502
<v-card outlined class="text-center pa-3">
513503
<div class="text-h6" style="color: #00BCD4">
514504
{{ formatNetRate(service_metrics.net_rx_rate_mbps, service_metrics.net_tx_rate_mbps) }}
@@ -540,16 +530,18 @@
540530
</div>
541531
</v-card>
542532

543-
<!-- Memory Chart -->
533+
<!-- Memory & Swap Chart -->
544534
<v-card outlined class="mb-4 pa-3">
545535
<div class="d-flex align-center mb-2">
546536
<v-icon small color="success" class="mr-2">
547537
mdi-memory
548538
</v-icon>
549-
<span class="text-subtitle-2">Memory Usage</span>
539+
<span class="text-subtitle-2">Memory & Swap</span>
550540
<v-spacer />
551-
<span class="text-caption grey--text">
552-
Peak: {{ (service_metrics.memory_peak_mb ?? 0).toFixed(1) }} MB
541+
<span class="text-caption">
542+
Peak:
543+
<span class="success--text">RAM {{ (service_metrics.memory_peak_mb ?? 0).toFixed(1) }} MB</span> /
544+
<span class="info--text">Swap {{ (service_metrics.swap_peak_mb ?? 0).toFixed(1) }} MB</span>
553545
</span>
554546
</div>
555547
<apexchart
@@ -564,30 +556,6 @@
564556
</div>
565557
</v-card>
566558

567-
<!-- Swap Chart -->
568-
<v-card outlined class="mb-4 pa-3">
569-
<div class="d-flex align-center mb-2">
570-
<v-icon small color="info" class="mr-2">
571-
mdi-swap-horizontal
572-
</v-icon>
573-
<span class="text-subtitle-2">Swap Usage</span>
574-
<v-spacer />
575-
<span class="text-caption grey--text">
576-
Peak: {{ (service_metrics.swap_peak_mb ?? 0).toFixed(1) }} MB
577-
</span>
578-
</div>
579-
<apexchart
580-
v-if="metrics_history.length > 1"
581-
type="area"
582-
height="150"
583-
:options="swapChartOptions"
584-
:series="swapChartSeries"
585-
/>
586-
<div v-else class="text-center grey--text py-4">
587-
Collecting data...
588-
</div>
589-
</v-card>
590-
591559
<!-- Disk I/O Chart -->
592560
<v-card outlined class="mb-4 pa-3">
593561
<div class="d-flex align-center mb-2">
@@ -596,9 +564,10 @@
596564
</v-icon>
597565
<span class="text-subtitle-2">Disk I/O</span>
598566
<v-spacer />
599-
<span class="text-caption grey--text">
600-
Total: R {{ (service_metrics.io_read_mb ?? 0).toFixed(1) }} MB /
601-
W {{ (service_metrics.io_write_mb ?? 0).toFixed(1) }} MB
567+
<span class="text-caption">
568+
Total:
569+
<span class="warning--text">R {{ (service_metrics.io_read_mb ?? 0).toFixed(1) }} MB</span> /
570+
<span style="color: #9C27B0">W {{ (service_metrics.io_write_mb ?? 0).toFixed(1) }} MB</span>
602571
</span>
603572
</div>
604573
<apexchart
@@ -621,9 +590,10 @@
621590
</v-icon>
622591
<span class="text-subtitle-2">Network I/O</span>
623592
<v-spacer />
624-
<span class="text-caption grey--text">
625-
Total: RX {{ (service_metrics.net_rx_mb ?? 0).toFixed(1) }} MB /
626-
TX {{ (service_metrics.net_tx_mb ?? 0).toFixed(1) }} MB
593+
<span class="text-caption">
594+
Total:
595+
<span style="color: #00BCD4">RX {{ (service_metrics.net_rx_mb ?? 0).toFixed(1) }} MB</span> /
596+
<span style="color: #E91E63">TX {{ (service_metrics.net_tx_mb ?? 0).toFixed(1) }} MB</span>
627597
</span>
628598
</div>
629599
<apexchart
@@ -801,19 +771,25 @@ export default Vue.extend({
801771
memoryChartOptions(): Record<string, unknown> {
802772
return {
803773
...this.baseChartOptions,
804-
colors: ['#4CAF50'],
774+
colors: ['#4CAF50', '#2196F3'],
805775
yaxis: {
806776
min: 0,
807777
labels: { formatter: (val: number) => `${val.toFixed(0)} MB` },
808-
title: { text: 'Memory MB' },
778+
title: { text: 'MB' },
809779
},
810780
}
811781
},
812782
memoryChartSeries(): { name: string; data: [number, number][] }[] {
813-
return [{
814-
name: 'Memory',
815-
data: this.metrics_history.map((m) => [new Date(m.timestamp).getTime(), m.memory_mb ?? 0]),
816-
}]
783+
return [
784+
{
785+
name: 'RAM',
786+
data: this.metrics_history.map((m) => [new Date(m.timestamp).getTime(), m.memory_mb ?? 0]),
787+
},
788+
{
789+
name: 'Swap',
790+
data: this.metrics_history.map((m) => [new Date(m.timestamp).getTime(), m.swap_mb ?? 0]),
791+
},
792+
]
817793
},
818794
ioChartOptions(): Record<string, unknown> {
819795
return {
@@ -838,23 +814,6 @@ export default Vue.extend({
838814
},
839815
]
840816
},
841-
swapChartOptions(): Record<string, unknown> {
842-
return {
843-
...this.baseChartOptions,
844-
colors: ['#2196F3'],
845-
yaxis: {
846-
min: 0,
847-
labels: { formatter: (val: number) => `${val.toFixed(0)} MB` },
848-
title: { text: 'Swap MB' },
849-
},
850-
}
851-
},
852-
swapChartSeries(): { name: string; data: [number, number][] }[] {
853-
return [{
854-
name: 'Swap',
855-
data: this.metrics_history.map((m) => [new Date(m.timestamp).getTime(), m.swap_mb ?? 0]),
856-
}]
857-
},
858817
networkChartOptions(): Record<string, unknown> {
859818
return {
860819
...this.baseChartOptions,
@@ -904,11 +863,18 @@ export default Vue.extend({
904863
},
905864
906865
methods: {
866+
formatDiskRate(read?: number, write?: number): string {
867+
const r = read ?? 0
868+
const w = write ?? 0
869+
if (r < 0.01 && w < 0.01) return '0'
870+
return `R ${r.toFixed(2)} / W ${w.toFixed(2)} MB/s`
871+
},
872+
907873
formatNetRate(rx?: number, tx?: number): string {
908874
const rxVal = rx ?? 0
909875
const txVal = tx ?? 0
910876
if (rxVal < 0.01 && txVal < 0.01) return '0'
911-
return `${rxVal.toFixed(1)}/${txVal.toFixed(1)}`
877+
return `RX ${rxVal.toFixed(2)} / TX ${txVal.toFixed(2)} MB/s`
912878
},
913879
914880
async fetchServices(): Promise<void> {

core/services/service_manager/service_manager/metrics.py

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,14 @@ class PreviousSample:
8585
net_tx_bytes: int = 0
8686

8787

88+
@dataclass
89+
class PeakValues:
90+
"""Tracked peak values for a service."""
91+
92+
memory_bytes: int = 0
93+
swap_bytes: int = 0
94+
95+
8896
class MetricsSampler:
8997
"""Periodic metrics collection for running services."""
9098

@@ -99,6 +107,7 @@ def __init__(
99107
self._interval = interval_sec
100108
self._current: dict[str, ServiceMetrics] = {}
101109
self._previous: dict[str, PreviousSample] = {}
110+
self._peaks: dict[str, PeakValues] = {}
102111

103112
async def run(self, shutdown_event: asyncio.Event) -> None:
104113
"""Main sampling loop."""
@@ -130,6 +139,7 @@ async def _sample_all(self) -> None:
130139
if name not in running_names:
131140
del self._current[name]
132141
self._previous.pop(name, None)
142+
self._peaks.pop(name, None)
133143

134144
# Sample each running service
135145
for state in running:
@@ -227,13 +237,22 @@ def _compute_cgroup_metrics( # type: ignore[no-untyped-def]
227237
net_tx_bytes=net_tx_bytes,
228238
)
229239

240+
# Track peaks ourselves if cgroups don't provide them
241+
peaks = self._peaks.setdefault(name, PeakValues())
242+
peaks.memory_bytes = max(peaks.memory_bytes, cgroup_metrics.memory_current)
243+
peaks.swap_bytes = max(peaks.swap_bytes, cgroup_metrics.swap_current)
244+
245+
# Use cgroup peaks if available, otherwise use our tracked peaks
246+
memory_peak = cgroup_metrics.memory_peak if cgroup_metrics.memory_peak > 0 else peaks.memory_bytes
247+
swap_peak = cgroup_metrics.swap_peak if cgroup_metrics.swap_peak > 0 else peaks.swap_bytes
248+
230249
return ServiceMetrics(
231250
timestamp=datetime.now(timezone.utc),
232251
cpu_percent=max(0.0, cpu_percent),
233252
memory_bytes=cgroup_metrics.memory_current,
234-
memory_peak_bytes=cgroup_metrics.memory_peak,
253+
memory_peak_bytes=memory_peak,
235254
swap_bytes=cgroup_metrics.swap_current,
236-
swap_peak_bytes=cgroup_metrics.swap_peak,
255+
swap_peak_bytes=swap_peak,
237256
io_read_bytes=cgroup_metrics.io_read_bytes,
238257
io_write_bytes=cgroup_metrics.io_write_bytes,
239258
io_read_rate=max(0.0, io_read_rate),
@@ -347,13 +366,18 @@ async def _sample_from_proc(self, name: str, pid: int) -> ServiceMetrics | None:
347366
net_tx_bytes=net_tx_bytes,
348367
)
349368

369+
# Track peaks ourselves since /proc doesn't provide them
370+
peaks = self._peaks.setdefault(name, PeakValues())
371+
peaks.memory_bytes = max(peaks.memory_bytes, memory_bytes)
372+
peaks.swap_bytes = max(peaks.swap_bytes, swap_bytes)
373+
350374
return ServiceMetrics(
351375
timestamp=datetime.now(timezone.utc),
352376
cpu_percent=max(0.0, cpu_percent),
353377
memory_bytes=memory_bytes,
354-
memory_peak_bytes=0, # Not available from /proc
378+
memory_peak_bytes=peaks.memory_bytes,
355379
swap_bytes=swap_bytes,
356-
swap_peak_bytes=0, # Not available from /proc
380+
swap_peak_bytes=peaks.swap_bytes,
357381
io_read_bytes=io_read_bytes,
358382
io_write_bytes=io_write_bytes,
359383
io_read_rate=max(0.0, io_read_rate),

0 commit comments

Comments
 (0)