diff --git a/apps/web/src/pages/telemetry-page.tsx b/apps/web/src/pages/telemetry-page.tsx index 46b30d8..df6bf3b 100644 --- a/apps/web/src/pages/telemetry-page.tsx +++ b/apps/web/src/pages/telemetry-page.tsx @@ -236,6 +236,7 @@ export function TelemetryPage() { const [stats, setStats] = useState(null); const [metrics, setMetrics] = useState([]); const [chartMap, setChartMap] = useState>(new Map()); + const [memChartData, setMemChartData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [refreshing, setRefreshing] = useState(false); @@ -255,22 +256,51 @@ export function TelemetryPage() { setStats(statsData); setMetrics(discoverData); - // Fetch charts for top metrics + // Fetch charts for top metrics (excluding prometheus noise) const topMetrics = discoverData .filter((m) => !m.metric_name.startsWith("prometheus_") && m.service !== "prometheus") - .slice(0, 6); + .slice(0, 4); const chartPanels = topMetrics.map((m) => ({ key: m.metric_name, metric: m.metric_name, })); - // Add CPU and disk + // Built-in computations + app metrics chartPanels.unshift({ key: "_cpu_usage_pct", metric: "_cpu_usage_pct" }); chartPanels.unshift({ key: "_disk_usage_pct", metric: "_disk_usage_pct" }); + // Memory charts (raw values, % computed client-side) + chartPanels.push({ key: "node_memory_MemTotal_bytes", metric: "node_memory_MemTotal_bytes" }); + chartPanels.push({ key: "node_memory_MemAvailable_bytes", metric: "node_memory_MemAvailable_bytes" }); + + // App-specific metrics + for (const appMetric of ["zeavis_api_http_requests_total", "zeavis_api_http_requests_active"]) { + if (discoverData.find((m) => m.metric_name === appMetric)) { + chartPanels.push({ key: appMetric, metric: appMetric }); + } + } + const charts = await api.charts(chartPanels); setChartMap(charts); + + // Compute memory usage % = (total - available) / total + const memTotalData = charts.get("node_memory_MemTotal_bytes"); + const memAvailData = charts.get("node_memory_MemAvailable_bytes"); + if (memTotalData && memAvailData && memTotalData.length > 0 && memAvailData.length > 0) { + const merged: ChartPoint[] = []; + for (let i = 0; i < Math.min(memTotalData.length, memAvailData.length); i++) { + const total = memTotalData[i].value; + const avail = memAvailData[i].value; + if (total > 0) { + merged.push({ time: memTotalData[i].time, value: 1 - avail / total }); + } + } + setMemChartData(merged); + } else { + setMemChartData([]); + } + setChartMap(charts); } catch (e) { setError(e instanceof Error ? e.message : "Unknown error"); } finally { @@ -402,14 +432,20 @@ export function TelemetryPage() { )} - {/* CPU & Disk charts */} -
+ {/* CPU, Memory, Disk charts */} +
+
+ {/* Application Metrics */} + {(chartMap.has("zeavis_api_http_requests_total") || chartMap.has("zeavis_api_http_requests_active")) && ( +
+

Application Metrics

+
+ {chartMap.has("zeavis_api_http_requests_total") && ( + + )} + {chartMap.has("zeavis_api_http_requests_active") && ( + + )} +
+
+ )} + {/* Top Metrics */}