From fbefc08b85811d8d681b2bccd343aaa00d2f61c9 Mon Sep 17 00:00:00 2001 From: chyoo Date: Thu, 9 Jul 2026 13:09:41 +0900 Subject: [PATCH] add app monitoring charts and runtime metrics --- src/runtime/runtime.service.ts | 59 ++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/src/runtime/runtime.service.ts b/src/runtime/runtime.service.ts index 8f9fc6d..46c2e07 100644 --- a/src/runtime/runtime.service.ts +++ b/src/runtime/runtime.service.ts @@ -62,14 +62,59 @@ export class RuntimeService { } async listPodMetrics(namespace?: string) { - const output = await this.kubectl([ - 'top', - 'pods', - ...(namespace ? ['-n', namespace] : ['--all-namespaces']), - '--no-headers', - ]); + try { + const output = await this.kubectl([ + 'top', + 'pods', + ...(namespace ? ['-n', namespace] : ['--all-namespaces']), + '--no-headers', + ]); - return parsePodMetrics(output, Boolean(namespace), namespace); + return parsePodMetrics(output, Boolean(namespace), namespace); + } catch { + return this.listRunningPodMetrics(namespace); + } + } + + private async listRunningPodMetrics(namespace?: string) { + const pods = await this.kubectlJson([ + 'get', + 'pods', + '-o', + 'json', + ...(namespace ? ['-n', namespace] : ['--all-namespaces']), + ]); + const runningPods = (pods.items ?? []) + .filter((pod: KubectlJson) => pod.status?.phase === 'Running') + .map((pod: KubectlJson) => ({ + namespace: pod.metadata?.namespace, + name: pod.metadata?.name, + })) + .filter((pod: { namespace?: string; name?: string }) => pod.namespace && pod.name); + + if (!runningPods.length) { + return []; + } + + const byNamespace = new Map(); + runningPods.forEach((pod: { namespace: string; name: string }) => { + byNamespace.set(pod.namespace, [...(byNamespace.get(pod.namespace) ?? []), pod.name]); + }); + + const outputs = await Promise.all([...byNamespace.entries()].map(([podNamespace, podNames]) => ( + this.kubectl([ + 'top', + 'pods', + ...podNames, + '-n', + podNamespace, + '--no-headers', + ]) + .then((output) => parsePodMetrics(output, true, podNamespace)) + .catch(() => []) + ))); + + return outputs.flat(); } async getClusterMetrics() {