From df1c802f8e4c1f91746ce7761590af6849d12d41 Mon Sep 17 00:00:00 2001 From: clover caruso Date: Sun, 4 Oct 2026 21:28:12 -0700 Subject: [PATCH] Preserve metrics and logs shortcuts for grouped Victoria Expose the grouped app routes from the canonical service definitions so its metrics shortcut still reaches VictoriaMetrics and deployment logs still reach VictoriaLogs. Assisted-by: gpt-6.1-sol --- dashboard/src/core.rs | 8 +++++--- dashboard/web/api.contract.ts | 2 +- dashboard/web/pages/Deploy.tsx | 2 +- dashboard/web/pages/Overview.tsx | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/dashboard/src/core.rs b/dashboard/src/core.rs index 993e5a5fb2849c6de0593867b3d99f002938dea1..fd6afcd1017c2f7d5576f117561e1549da6f999f 100644 --- a/dashboard/src/core.rs +++ b/dashboard/src/core.rs @@ -486,8 +486,10 @@ async fn launcher_module(repo: &Path) -> Result { module.push_str(&format!("local services = Map({})\n", services.join(", "))); module.push_str(r#"output { renderer = new JsonRenderer { omitNullProperties = false } value = services.filter((_, s) -> s.enabled && s.meta.launcher).mapValues((_, s) -> -let (route = (s.containers?.toMap()?.values ?? List()).add(s.container).filterNonNull().map((task) -> task.http).filterNonNull().findOrNull((http) -> http.hostname != null)) -new Dynamic { name = s.meta.name; tagline = s.meta.tagline; hostname = route?.hostname; access = s.meta.access ?? route?.authRole }) }"#); +let (tasks = s.containers?.toMap() ?? Map("app", s.container)) +let (routes = tasks.filter((_, task) -> task?.http?.hostname != null).mapValues((_, task) -> task.http)) +let (route = routes.values.firstOrNull) +new Dynamic { name = s.meta.name; tagline = s.meta.tagline; hostname = route?.hostname; access = s.meta.access ?? route?.authRole; urls = routes.mapValues((_, http) -> "https://\(http.hostname)") }) }"#); Ok(module) } @@ -502,7 +504,7 @@ async fn launcher(app: Arc) -> Result> { if let Some(host) = value["hostname"].as_str() { let path = std::path::Path::new(file); let id = if path.file_name().unwrap() == "service.pkl" { path.parent().unwrap().file_name().unwrap() } else { path.file_stem().unwrap() }.to_string_lossy(); - apps.push(json!({"id":id,"name":value["name"],"tagline":value["tagline"].as_str().filter(|s| !s.is_empty()),"url":format!("https://{host}"),"access":value["access"],"icon":icon_of(state.clone(),&id).await})); + apps.push(json!({"id":id,"name":value["name"],"tagline":value["tagline"].as_str().filter(|s| !s.is_empty()),"url":format!("https://{host}"),"urls":value["urls"],"access":value["access"],"icon":icon_of(state.clone(),&id).await})); } } Ok(json!(apps)) diff --git a/dashboard/web/api.contract.ts b/dashboard/web/api.contract.ts index b2448d7b7715d532d18e7d16bf8af85532246a09..8f0dd97eac896786849c5741237f933321d6ffaf 100644 --- a/dashboard/web/api.contract.ts +++ b/dashboard/web/api.contract.ts @@ -72,7 +72,7 @@ export type Api = Hono<{}, { $get: Endpoint; }; "/launcher": { - $get: Endpoint<{ id: string; name: string; tagline: string | null; url: string; icon: { light: string; dark: string; } | null; health: Health | null; }[]>; + $get: Endpoint<{ id: string; name: string; tagline: string | null; url: string; urls: Record; icon: { light: string; dark: string; } | null; health: Health | null; }[]>; }; "/status": { $get: Endpoint<{ load: number; issues: Issue[] | null }>; diff --git a/dashboard/web/pages/Deploy.tsx b/dashboard/web/pages/Deploy.tsx index eb34094486c9dc3ed2380dad80370f71a90ab464..4eb6d7e9d336b63f83b233ca73590bb297896a35 100644 --- a/dashboard/web/pages/Deploy.tsx +++ b/dashboard/web/pages/Deploy.tsx @@ -407,7 +407,7 @@ export function Deploy() { /** The job's lines in the logs app, bounded to the window once its jobs stopped. */ const logsUrl = (job: string, runtime: Runtime | undefined) => { - const url = service("victoria-logs")?.url; + const url = service("victoria")?.url; const iso = (t: number) => new Date(t * 1000).toISOString(); const window = runtime?.to ? ` _time:[${iso(runtime.from)}, ${iso(runtime.to)}]` : ""; return url && `${url}/select/vmui/#/?query=${encodeURIComponent(`{job="${job}"}${window}`)}`; diff --git a/dashboard/web/pages/Overview.tsx b/dashboard/web/pages/Overview.tsx index 072cfde7122fa8368f6d0979fabeaa8e6a5cf153..e4510bb5004256620ecbe545accda4925edc97dc 100644 --- a/dashboard/web/pages/Overview.tsx +++ b/dashboard/web/pages/Overview.tsx @@ -160,7 +160,7 @@ function Dashboard(props: { me: Me }) { const name = (id: string) => names()[id] ?? id; const health = (service: { id: string; health: Health | null }) => stream.latest()?.services[service.id]?.health ?? service.health; - const metrics = () => apps()?.find((app) => app.id === "victoria-metrics"); + const metrics = () => apps()?.find((app) => app.id === "victoria"); const [menuId, setMenuId] = createSignal(); const selectedStage = () => history()?.stages.find((stage) => stage.id === menuId()); @@ -340,7 +340,7 @@ function Dashboard(props: { me: Me }) {

machine

- {(app) => } + {(app) => }
-- 2.54.0