From 62d5c1c43c0e180f000b133707232f760250bde7 Mon Sep 17 00:00:00 2001 From: "stefan.meyer" Date: Thu, 28 Nov 2024 14:35:33 +0000 Subject: [PATCH] Work at monitoring of app --- .../project/app/[appId]/overview/actions.ts | 7 +-- .../app/[appId]/overview/monitoring-app.tsx | 47 ++++++++++++---- src/server/services/monitor-app.service.ts | 53 ++++++++++++++----- src/shared/model/pods-resource-info.model.ts | 14 +++++ 4 files changed, 95 insertions(+), 26 deletions(-) create mode 100644 src/shared/model/pods-resource-info.model.ts diff --git a/src/app/project/app/[appId]/overview/actions.ts b/src/app/project/app/[appId]/overview/actions.ts index 994d533..3a2efed 100644 --- a/src/app/project/app/[appId]/overview/actions.ts +++ b/src/app/project/app/[appId]/overview/actions.ts @@ -10,6 +10,7 @@ import deploymentService from "@/server/services/deployment.service"; import monitorAppService from "@/server/services/monitor-app.service"; import podService from "@/server/services/pod.service"; import { getAuthUserSession, simpleAction } from "@/server/utils/action-wrapper.utils"; +import { PodsResourceInfoModel } from "@/shared/model/pods-resource-info.model"; export const getDeploymentsAndBuildsForApp = async (appId: string) => @@ -33,8 +34,8 @@ export const getPodsForApp = async (appId: string) => return await podService.getPodsForApp(app.projectId, appId); }) as Promise>; -export const getRessourceDataApp = async (namespace: string, deploymentName: string) => +export const getRessourceDataApp = async (projectId: string, appId: string) => simpleAction(async () => { await getAuthUserSession(); - return await monitorAppService.getPodsFromDeployment(namespace, deploymentName); - }) as Promise>; \ No newline at end of file + return await monitorAppService.getPodsForApp(projectId, appId); + }) as Promise>; \ No newline at end of file diff --git a/src/app/project/app/[appId]/overview/monitoring-app.tsx b/src/app/project/app/[appId]/overview/monitoring-app.tsx index b97fba4..e4c6489 100644 --- a/src/app/project/app/[appId]/overview/monitoring-app.tsx +++ b/src/app/project/app/[appId]/overview/monitoring-app.tsx @@ -12,6 +12,8 @@ import { DeploymentInfoModel } from "@/shared/model/deployment-info.model"; import DeploymentStatusBadge from "./deployment-status-badge"; import { BuildLogsDialog } from "./build-logs-overlay"; import ShortCommitHash from "@/components/custom/short-commit-hash"; +import { PodsResourceInfoModel } from "@/shared/model/pods-resource-info.model"; +import { Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; export default function MonitoringTab({ app @@ -19,24 +21,27 @@ export default function MonitoringTab({ app: AppExtendedModel; }) { + const [selectedPod, setSelectedPod] = useState(undefined); + const [error, setError] = useState(undefined); + const updateValues = async () => { + setError(undefined); try { - const response = await getRessourceDataApp(app.projectId, app.id.split('-').slice(0, 3).join('-')); + const response = await getRessourceDataApp(app.projectId, app.id); if (response.status === 'success' && response.data) { - console.log(response.data); + setSelectedPod(response.data); + } else { console.error(response); - console.log(response.message ?? 'An unknown error occurred.'); + setError(response.message ?? 'An unknown error occurred.'); } } catch (ex) { console.error(ex); + setError('An unknown error occurred.'); } } useEffect(() => { - if (app.sourceType === 'container') { - return; - } updateValues(); const intervalId = setInterval(updateValues, 10000); return () => clearInterval(intervalId); @@ -51,8 +56,32 @@ export default function MonitoringTab({ App Monitoring - This is an overview about the resources the app is consuming. + This is an overview about the resources the app is consuming. + - + + + + + CPU absolut + CPU percent + memory absent + memory percent + volume percent + + + + + {selectedPod?.cpuAbsolut} + {selectedPod?.cpuPercent} + {selectedPod?.memoryAbsolut} + {selectedPod?.memoryPercent} + {selectedPod?.volumePercent} + + +
+
+ + ; -} +} \ No newline at end of file diff --git a/src/server/services/monitor-app.service.ts b/src/server/services/monitor-app.service.ts index 505b924..3b87c89 100644 --- a/src/server/services/monitor-app.service.ts +++ b/src/server/services/monitor-app.service.ts @@ -1,12 +1,13 @@ import { AppExtendedModel } from "@/shared/model/app-extended.model"; import k3s from "../adapter/kubernetes-api.adapter"; +import * as k8s from '@kubernetes/client-node'; import { V1Deployment, V1LabelSelector, V1ReplicaSet } from "@kubernetes/client-node"; import buildService from "./build.service"; import { ListUtils } from "../../shared/utils/list.utils"; import { DeploymentInfoModel, DeplyomentStatus } from "@/shared/model/deployment-info.model"; import { BuildJobStatus } from "@/shared/model/build-job"; import { ServiceException } from "@/shared/model/service.exception.model"; -import { PodsInfoModel } from "@/shared/model/pods-info.model"; +import { PodsInfoModel, podsInfoZodModel } from "@/shared/model/pods-info.model"; import { KubeObjectNameUtils } from "../utils/kube-object-name.utils"; import pvcService from "./pvc.service"; import ingressService from "./ingress.service"; @@ -14,23 +15,47 @@ import namespaceService from "./namespace.service"; import { Constants } from "../../shared/utils/constants"; import svcService from "./svc.service"; import { Label } from "@radix-ui/react-dropdown-menu"; +import setupPodService from "./setup-services/setup-pod.service"; +import clusterService from "./node.service"; +import { PodsResourceInfoModel } from "@/shared/model/pods-resource-info.model"; class MonitorAppService { - async getRessourceData() { - //console.log("gugus"); - return "miau"; + async getPodsForApp(projectId: string, appId: string): Promise { + const metricsClient = new k8s.Metrics(k3s.getKubeConfig()); + const podsFromApp = await setupPodService.getPodsForApp(projectId, appId); + const topPodsRes1 = await k8s.topPods(k3s.core, metricsClient, projectId); + + const filteredTopPods = topPodsRes1.filter((topPod) => + podsFromApp.some((pod) => pod.podName === topPod.Pod.metadata?.name) + ); + + const nodeInfo = await clusterService.getNodeInfo(); + + const nodesColumns = nodeInfo.map((node) => { + return { + 'POD': node.name, + 'CPU(cores)': node.cpuCapacity, + 'MEMORY(bytes)': node.ramCapacity, + }; + }); + + const podsColumns = filteredTopPods.map((pod) => { + return { + 'POD': pod.Pod.metadata?.name, + 'CPU(cores)': pod.CPU.CurrentUsage, + 'MEMORY(bytes)': pod.Memory.CurrentUsage, + }; + }); + + return { + cpuAbsolut: '5', + cpuPercent: '6', + memoryAbsolut: '7', + memoryPercent: '8', + volumePercent: '9', + } } - async getPodsFromDeployment(namespace: string, deploymentName: string): Promise { - const pods = await k3s.core.listNamespacedPod(namespace, undefined, undefined, undefined, undefined, `app=${deploymentName}`); - // console.log(namespace); - // console.log(deploymentName); - //console.log(pods.body.items); - for (const pod of pods.body.items) { - //console.log(pod.metadata?.name); - } - -} } const monitorAppService = new MonitorAppService(); diff --git a/src/shared/model/pods-resource-info.model.ts b/src/shared/model/pods-resource-info.model.ts new file mode 100644 index 0000000..d55ffd2 --- /dev/null +++ b/src/shared/model/pods-resource-info.model.ts @@ -0,0 +1,14 @@ +import { memo } from "react"; +import { z } from "zod"; + +export const podsResourceInfoZodModel = z.object({ + cpuAbsolut: z.string(), + cpuPercent: z.string(), + memoryAbsolut: z.string(), + memoryPercent: z.string(), + volumePercent: z.string(), +}); + +export type PodsResourceInfoModel = z.infer; + +