fixes and improvements
This commit is contained in:
@@ -44,7 +44,32 @@ def get_monitoring_overview(
|
||||
) -> dict[str, Any]:
|
||||
"""Return one lightweight monitoring row per configured machine."""
|
||||
machines = store.list_machines()
|
||||
rows = [collect_machine_overview(machine, store) for machine in machines]
|
||||
rows: list[dict[str, Any]] = []
|
||||
for machine in machines:
|
||||
try:
|
||||
rows.append(collect_machine_overview(machine, store))
|
||||
except Exception as exc:
|
||||
logger.exception(
|
||||
"Dashboard monitoring overview failed for machine_id=%s",
|
||||
machine.get("id"),
|
||||
)
|
||||
rows.append({
|
||||
"machine": {k: machine.get(k) for k in ("id", "name", "mode", "enabled", "host", "port", "username", "media_root", "path_prefix", "notes")},
|
||||
"status": "",
|
||||
"status_error": str(exc),
|
||||
"metrics_error": str(exc),
|
||||
"disk_error": str(exc),
|
||||
"sample_count": 0,
|
||||
"latest_sample": None,
|
||||
"cpu_summary": None,
|
||||
"iowait_summary": None,
|
||||
"mem_summary": None,
|
||||
"net_rx_summary": None,
|
||||
"net_tx_summary": None,
|
||||
"disk_read_summary": None,
|
||||
"disk_write_summary": None,
|
||||
"disk": None,
|
||||
})
|
||||
poller = get_monitoring_poller().snapshot()
|
||||
enabled_count = sum(1 for machine in machines if machine.get("enabled"))
|
||||
logger.info("Dashboard monitoring machines=%s enabled=%s", len(machines), enabled_count)
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
TableHead,
|
||||
TableRow,
|
||||
TableSortLabel,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import type {
|
||||
@@ -102,6 +103,19 @@ function sortableText(value: string) {
|
||||
return value.toLowerCase();
|
||||
}
|
||||
|
||||
function getStatusChipProps(row: MonitoringMachineOverview) {
|
||||
if (row.status_error) {
|
||||
return { color: "error" as const, label: row.status_error };
|
||||
}
|
||||
if (row.status === "running") {
|
||||
return { color: "success" as const, label: "running" };
|
||||
}
|
||||
if (row.status === "not running") {
|
||||
return { color: "warning" as const, label: "not running" };
|
||||
}
|
||||
return { color: "default" as const, label: row.status || "-" };
|
||||
}
|
||||
|
||||
function metricSortValue(
|
||||
row: MonitoringMachineOverview,
|
||||
key: SortKey,
|
||||
@@ -136,6 +150,34 @@ function metricSortValue(
|
||||
}
|
||||
}
|
||||
|
||||
function NoDataCell() {
|
||||
return (
|
||||
<Stack
|
||||
sx={{
|
||||
width: "100%",
|
||||
minWidth: 0,
|
||||
height: "100%",
|
||||
minHeight: 118,
|
||||
textAlign: "center",
|
||||
justifyContent: "center",
|
||||
py: 0.5,
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="caption"
|
||||
color="text.secondary"
|
||||
sx={{
|
||||
fontSize: "0.7rem",
|
||||
fontStyle: "italic",
|
||||
lineHeight: 1.2,
|
||||
}}
|
||||
>
|
||||
No data
|
||||
</Typography>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
function MetricCell({
|
||||
value,
|
||||
min,
|
||||
@@ -441,7 +483,7 @@ export function MonitoringOverviewTable({
|
||||
) : (
|
||||
sortedRows.map((row) => {
|
||||
const machine = row.machine;
|
||||
const status = row.status || row.status_error || "-";
|
||||
const hasMetrics = row.sample_count > 0;
|
||||
const cpu = formatSummary(
|
||||
row.cpu_summary,
|
||||
(value) => `${value.toFixed(1)}%`,
|
||||
@@ -524,62 +566,106 @@ export function MonitoringOverviewTable({
|
||||
</Stack>
|
||||
</TableCell>
|
||||
<TableCell sx={{ width: 90 }}>{machine.mode}</TableCell>
|
||||
<TableCell sx={{ width: 120 }}>
|
||||
<TableCell sx={{ width: 120 }}>
|
||||
{(() => {
|
||||
const chip = getStatusChipProps(row);
|
||||
return (
|
||||
<Tooltip
|
||||
title={
|
||||
row.metrics_error
|
||||
? `Metrics: ${row.metrics_error}`
|
||||
: row.sample_count === 0
|
||||
? "No metrics collected yet. Start the collector to begin monitoring."
|
||||
: ""
|
||||
}
|
||||
arrow
|
||||
>
|
||||
<Chip
|
||||
size="small"
|
||||
variant="outlined"
|
||||
color={row.status_error ? "error" : "success"}
|
||||
label={status}
|
||||
color={chip.color}
|
||||
label={chip.label}
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
})()}
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
{hasMetrics ? (
|
||||
<MetricCell
|
||||
value={cpu.value}
|
||||
min={cpu.min}
|
||||
max={cpu.max}
|
||||
/>
|
||||
) : (
|
||||
<NoDataCell />
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
<MetricCell
|
||||
value={cpu.value}
|
||||
min={cpu.min}
|
||||
max={cpu.max}
|
||||
/>
|
||||
{hasMetrics ? (
|
||||
<MetricCell
|
||||
value={iowait.value}
|
||||
min={iowait.min}
|
||||
max={iowait.max}
|
||||
/>
|
||||
) : (
|
||||
<NoDataCell />
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
<MetricCell
|
||||
value={iowait.value}
|
||||
min={iowait.min}
|
||||
max={iowait.max}
|
||||
/>
|
||||
{hasMetrics ? (
|
||||
<MetricCell
|
||||
value={mem.value}
|
||||
min={mem.min}
|
||||
max={mem.max}
|
||||
/>
|
||||
) : (
|
||||
<NoDataCell />
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
<MetricCell
|
||||
value={mem.value}
|
||||
min={mem.min}
|
||||
max={mem.max}
|
||||
/>
|
||||
{hasMetrics ? (
|
||||
<MetricCell
|
||||
value={netDown.value}
|
||||
min={netDown.min}
|
||||
max={netDown.max}
|
||||
/>
|
||||
) : (
|
||||
<NoDataCell />
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
<MetricCell
|
||||
value={netDown.value}
|
||||
min={netDown.min}
|
||||
max={netDown.max}
|
||||
/>
|
||||
{hasMetrics ? (
|
||||
<MetricCell
|
||||
value={netUp.value}
|
||||
min={netUp.min}
|
||||
max={netUp.max}
|
||||
/>
|
||||
) : (
|
||||
<NoDataCell />
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
<MetricCell
|
||||
value={netUp.value}
|
||||
min={netUp.min}
|
||||
max={netUp.max}
|
||||
/>
|
||||
{hasMetrics ? (
|
||||
<MetricCell
|
||||
value={diskRead.value}
|
||||
min={diskRead.min}
|
||||
max={diskRead.max}
|
||||
/>
|
||||
) : (
|
||||
<NoDataCell />
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
<MetricCell
|
||||
value={diskRead.value}
|
||||
min={diskRead.min}
|
||||
max={diskRead.max}
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
<MetricCell
|
||||
value={diskWrite.value}
|
||||
min={diskWrite.min}
|
||||
max={diskWrite.max}
|
||||
/>
|
||||
{hasMetrics ? (
|
||||
<MetricCell
|
||||
value={diskWrite.value}
|
||||
min={diskWrite.min}
|
||||
max={diskWrite.max}
|
||||
/>
|
||||
) : (
|
||||
<NoDataCell />
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell align="center">
|
||||
{disk ? (
|
||||
@@ -588,22 +674,34 @@ export function MonitoringOverviewTable({
|
||||
min={disk.min}
|
||||
max={disk.max}
|
||||
/>
|
||||
) : (
|
||||
) : hasMetrics ? (
|
||||
"-"
|
||||
) : (
|
||||
<NoDataCell />
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell sx={{ width: 180 }}>
|
||||
<Stack spacing={0.1} sx={{ alignItems: "center" }}>
|
||||
{updated.map((line) => (
|
||||
{hasMetrics ? (
|
||||
updated.map((line) => (
|
||||
<Typography
|
||||
key={line}
|
||||
variant="caption"
|
||||
color="text.secondary"
|
||||
sx={{ lineHeight: 1.1 }}
|
||||
>
|
||||
{line}
|
||||
</Typography>
|
||||
))
|
||||
) : (
|
||||
<Typography
|
||||
key={line}
|
||||
variant="caption"
|
||||
color="text.secondary"
|
||||
sx={{ lineHeight: 1.1 }}
|
||||
sx={{ lineHeight: 1.1, fontStyle: "italic" }}
|
||||
>
|
||||
{line}
|
||||
No data yet
|
||||
</Typography>
|
||||
))}
|
||||
)}
|
||||
</Stack>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
|
||||
Reference in New Issue
Block a user