diff options
| author | Dan Engelbrecht <[email protected]> | 2026-03-27 16:23:59 +0100 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2026-03-27 16:23:59 +0100 |
| commit | aff16da9a634ff6869b0394bf936bbb45096ad54 (patch) | |
| tree | 3d88cc842e6a87c3e4d07cc838a31b8dbabfce9a /src/zenserver/frontend/html/pages/start.js | |
| parent | remove CPR HTTP client backend (#894) (diff) | |
| download | zen-aff16da9a634ff6869b0394bf936bbb45096ad54.tar.xz zen-aff16da9a634ff6869b0394bf936bbb45096ad54.zip | |
dashboard improvements (#896)
- Feature: Added Workspaces dashboard page with HTTP request stats and per-workspace metrics
- Feature: Added Build Storage dashboard page with service-specific HTTP request stats
- Improvement: Front page now shows Hub and Object Store activity tiles; HTTP panel is fixed above the tiles grid
- Improvement: HTTP stats tiles now include 5m/15m rates and p999/max latency across all service pages
Diffstat (limited to 'src/zenserver/frontend/html/pages/start.js')
| -rw-r--r-- | src/zenserver/frontend/html/pages/start.js | 115 |
1 files changed, 76 insertions, 39 deletions
diff --git a/src/zenserver/frontend/html/pages/start.js b/src/zenserver/frontend/html/pages/start.js index df70ea2f4..e5b4d14f1 100644 --- a/src/zenserver/frontend/html/pages/start.js +++ b/src/zenserver/frontend/html/pages/start.js @@ -36,6 +36,15 @@ export class Page extends ZenPage all_stats[provider] = await new Fetcher().resource("stats", provider).json(); })); + this._http_panel = section.tag().classify("card").classify("stats-tile").classify("stats-http-panel"); + this._http_panel.inner().addEventListener("click", () => { window.location = "?page=metrics"; }); + this._http_panel.tag().classify("http-title").text("HTTP"); + const req_section = this._http_panel.tag().classify("http-section"); + req_section.tag().classify("http-section-label").text("Requests"); + this._http_req_metrics = req_section.tag().classify("tile-metrics"); + const ws_section = this._http_panel.tag().classify("http-section"); + ws_section.tag().classify("http-section-label").text("Websockets"); + this._http_ws_metrics = ws_section.tag().classify("tile-metrics"); this._stats_grid = section.tag().classify("grid").classify("stats-tiles"); this._safe_lookup = safe_lookup; this._render_stats(all_stats); @@ -113,7 +122,6 @@ export class Page extends ZenPage ); var cell = row.get_cell(0); cell.tag().text(namespace).on_click(() => this.view_zcache(namespace)); - row.get_cell(1).tag().text(namespace); cell = row.get_cell(-1); const action_tb = new Toolbar(cell, true); @@ -143,44 +151,43 @@ export class Page extends ZenPage const grid = this._stats_grid; const safe_lookup = this._safe_lookup; - // Clear existing tiles + // Clear and repopulate service tiles grid grid.inner().innerHTML = ""; - // HTTP tile — aggregate request stats across all providers - { - const tile = grid.tag().classify("card").classify("stats-tile"); - tile.tag().classify("card-title").text("HTTP"); - const columns = tile.tag().classify("tile-columns"); - - // Left column: request stats - const left = columns.tag().classify("tile-metrics"); - - let total_requests = 0; - let total_rate = 0; - for (const p in all_stats) - { - total_requests += (safe_lookup(all_stats[p], "requests.count") || 0); - total_rate += (safe_lookup(all_stats[p], "requests.rate_1") || 0); - } + // HTTP panel — update metrics containers built once in main() + const left = this._http_req_metrics; + left.inner().innerHTML = ""; - this._add_tile_metric(left, Friendly.sep(total_requests), "total requests", true); - if (total_rate > 0) - this._add_tile_metric(left, Friendly.sep(total_rate, 1) + "/s", "req/sec (1m)"); + let total_requests = 0; + let total_rate = 0; + for (const p in all_stats) + { + total_requests += (safe_lookup(all_stats[p], "requests.count") || 0); + total_rate += (safe_lookup(all_stats[p], "requests.rate_1") || 0); + } - // Right column: websocket stats - const ws = all_stats["http"] ? (all_stats["http"]["websockets"] || {}) : {}; - const right = columns.tag().classify("tile-metrics"); + this._add_tile_metric(left, Friendly.sep(total_requests), "total requests", true); + if (total_rate > 0) + { + this._add_tile_metric(left, Friendly.sep(total_rate, 1) + "/s", "req/sec (1m)"); + } - this._add_tile_metric(right, Friendly.sep(ws.active_connections || 0), "ws connections", true); - const ws_frames = (ws.frames_received || 0) + (ws.frames_sent || 0); - if (ws_frames > 0) - this._add_tile_metric(right, Friendly.sep(ws_frames), "ws frames"); - const ws_bytes = (ws.bytes_received || 0) + (ws.bytes_sent || 0); - if (ws_bytes > 0) - this._add_tile_metric(right, Friendly.bytes(ws_bytes), "ws traffic"); + const right = this._http_ws_metrics; + right.inner().innerHTML = ""; - tile.on_click(() => { window.location = "?page=metrics"; }); + const ws = all_stats["http"] ? (all_stats["http"]["websockets"] || {}) : {}; + this._add_tile_metric(right, Friendly.sep(ws.active_connections || 0), "ws connections", true); + const ws_frames = (ws.frames_received || 0) + (ws.frames_sent || 0); + if (ws_frames > 0) + { + this._add_tile_metric(right, Friendly.sep(ws_frames), "ws frames"); } + const ws_bytes = (ws.bytes_received || 0) + (ws.bytes_sent || 0); + if (ws_bytes > 0) + { + this._add_tile_metric(right, Friendly.bytes(ws_bytes), "ws traffic"); + } + // Cache tile (z$) if (all_stats["z$"]) @@ -198,7 +205,7 @@ export class Page extends ZenPage this._add_tile_metric(body, safe_lookup(s, "cache.size.disk", Friendly.bytes) || "-", "disk"); this._add_tile_metric(body, safe_lookup(s, "cache.size.memory", Friendly.bytes) || "-", "memory"); - tile.on_click(() => { window.location = "?page=stat&provider=z$"; }); + tile.inner().addEventListener("click", () => { window.location = "?page=stat&provider=z$"; }); } // Project Store tile (prj) @@ -210,9 +217,9 @@ export class Page extends ZenPage const body = tile.tag().classify("tile-metrics"); this._add_tile_metric(body, safe_lookup(s, "requests.count", Friendly.sep) || "-", "requests", true); - this._add_tile_metric(body, safe_lookup(s, "store.size.disk", Friendly.bytes) || "-", "disk"); + this._add_tile_metric(body, safe_lookup(s, "project_count", Friendly.sep) || "-", "projects"); - tile.on_click(() => { window.location = "?page=stat&provider=prj"; }); + tile.inner().addEventListener("click", () => { window.location = "?page=stat&provider=prj"; }); } // Build Store tile (builds) @@ -226,7 +233,7 @@ export class Page extends ZenPage this._add_tile_metric(body, safe_lookup(s, "requests.count", Friendly.sep) || "-", "requests", true); this._add_tile_metric(body, safe_lookup(s, "store.size.disk", Friendly.bytes) || "-", "disk"); - tile.on_click(() => { window.location = "?page=stat&provider=builds"; }); + tile.inner().addEventListener("click", () => { window.location = "?page=builds"; }); } // Proxy tile @@ -250,7 +257,37 @@ export class Page extends ZenPage this._add_tile_metric(body, Friendly.sep(mappings.length), "mappings"); this._add_tile_metric(body, Friendly.bytes(totalBytes), "traffic"); - tile.on_click(() => { window.location = "?page=proxy"; }); + tile.inner().addEventListener("click", () => { window.location = "?page=proxy"; }); + } + + // Hub tile + if (all_stats["hub"]) + { + const s = all_stats["hub"]; + const tile = grid.tag().classify("card").classify("stats-tile"); + tile.tag().classify("card-title").text("Hub"); + const body = tile.tag().classify("tile-metrics"); + + const current = safe_lookup(s, "currentInstanceCount") || 0; + const limit = safe_lookup(s, "instanceLimit") || safe_lookup(s, "maxInstanceCount") || 0; + this._add_tile_metric(body, `${current} / ${limit}`, "instances", true); + this._add_tile_metric(body, safe_lookup(s, "requests.count", Friendly.sep) || "-", "requests"); + + tile.inner().addEventListener("click", () => { window.location = "?page=stat&provider=hub"; }); + } + + // Object Store tile (obj) + if (all_stats["obj"]) + { + const s = all_stats["obj"]; + const tile = grid.tag().classify("card").classify("stats-tile"); + tile.tag().classify("card-title").text("Object Store"); + const body = tile.tag().classify("tile-metrics"); + + this._add_tile_metric(body, safe_lookup(s, "requests.count", Friendly.sep) || "-", "requests", true); + this._add_tile_metric(body, safe_lookup(s, "total_bytes_served", Friendly.bytes) || "-", "bytes served"); + + tile.inner().addEventListener("click", () => { window.location = "?page=stat&provider=obj"; }); } // Workspace tile (ws) @@ -262,9 +299,9 @@ export class Page extends ZenPage const body = tile.tag().classify("tile-metrics"); this._add_tile_metric(body, safe_lookup(s, "requests.count", Friendly.sep) || "-", "requests", true); - this._add_tile_metric(body, safe_lookup(s, "workspaces.filescount", Friendly.sep) || "-", "files"); + this._add_tile_metric(body, safe_lookup(s, "workspaces", Friendly.sep) || "-", "workspaces"); - tile.on_click(() => { window.location = "?page=stat&provider=ws"; }); + tile.inner().addEventListener("click", () => { window.location = "?page=stat&provider=ws"; }); } } |