diff --git a/client/src/hooks/forms/UseInitPageSpeedForm.tsx b/client/src/hooks/forms/UseInitPageSpeedForm.tsx index a26cc67d0..ced0f7654 100644 --- a/client/src/hooks/forms/UseInitPageSpeedForm.tsx +++ b/client/src/hooks/forms/UseInitPageSpeedForm.tsx @@ -11,7 +11,6 @@ export const useInitForm = ({ }) => { return useMemo(() => { const apiToForm = (apiData: IMonitor): FormValues => { - console.log(JSON.stringify(apiData)); return { type: apiData.type, url: apiData.url, diff --git a/client/src/pages/docker/DockerDetails.tsx b/client/src/pages/docker/DockerDetails.tsx index 6e22eda1b..c3f3bce27 100644 --- a/client/src/pages/docker/DockerDetails.tsx +++ b/client/src/pages/docker/DockerDetails.tsx @@ -38,9 +38,7 @@ const DockerDetailsPage = () => { const monitor = response?.data?.monitor; const stats = response?.data?.stats; const checks = (response?.data?.checks || []) as any; - const latestCheck = checks[0]; - const snapshot = latestCheck?.runningContainersSnapshot || []; - console.log(checks); + const snapshot = monitor?.latestChecks?.[0].containerSnapshot || []; const palette = getStatusPalette(monitor?.status || "initializing"); const streakDuration = stats?.currentStreakStartedAt diff --git a/client/src/pages/docker/DockerMonitorsTable.tsx b/client/src/pages/docker/DockerMonitorsTable.tsx index 82ad4f5a1..3489cfb2f 100644 --- a/client/src/pages/docker/DockerMonitorsTable.tsx +++ b/client/src/pages/docker/DockerMonitorsTable.tsx @@ -31,7 +31,6 @@ export const DockerMonitorsTable = ({ const navigate = useNavigate(); const theme = useTheme(); const { patch } = usePatch(); - console.log(monitors); const handlePageChange = ( _e: React.MouseEvent | null, newPage: number @@ -124,7 +123,11 @@ export const DockerMonitorsTable = ({ }, { id: "actions", - content: {t("common.table.headers.actions")}, + content: ( + + {t("common.table.headers.actions")} + + ), render: (row) => , }, ]; diff --git a/client/src/types/check.ts b/client/src/types/check.ts index b6d1e4b4f..c61d8d72c 100644 --- a/client/src/types/check.ts +++ b/client/src/types/check.ts @@ -123,7 +123,7 @@ export interface ICheck { lighthouse?: ICheckLighthouseFields; system?: ISystemInfo; // Present for docker monitor checks - dockerContainers?: IDockerContainerSummary[]; + containerSnapshot?: IDockerContainerSummary[]; } export interface CheckWithMonitor { _id: string; diff --git a/server/src/db/models/monitors/Monitor.ts b/server/src/db/models/monitors/Monitor.ts index 9e8a3b6b1..670401917 100644 --- a/server/src/db/models/monitors/Monitor.ts +++ b/server/src/db/models/monitors/Monitor.ts @@ -1,4 +1,5 @@ import mongoose, { Schema, Document, Types } from "mongoose"; +import type { IDockerContainerSummary } from "@/db/models/checks/Check.js"; import { Check, Incident, @@ -33,6 +34,13 @@ export interface IMonitorThresholds { temperature?: number; } +export interface LatestCheck { + status: MonitorStatus; + responseTime: number; + checkedAt: Date; + // Snapshot of containers from the latest docker check (array from payload.data) + containerSnapshot?: IDockerContainerSummary[]; +} export interface IMonitor extends Document { _id: Types.ObjectId; orgId: Types.ObjectId; @@ -48,11 +56,7 @@ export interface IMonitor extends Document { n: number; // Number of consecutive successes required to change status thresholds?: IMonitorThresholds; lastCheckedAt?: Date; - latestChecks: { - status: MonitorStatus; - responseTime: number; - checkedAt: Date; - }[]; + latestChecks: LatestCheck[]; notificationChannels?: Types.ObjectId[]; createdBy: Types.ObjectId; updatedBy: Types.ObjectId; @@ -104,6 +108,32 @@ const MonitorSchema = new Schema( }, responseTime: { type: Number, required: true }, checkedAt: { type: Date, required: true }, + containerSnapshot: { + type: [ + { + container_id: { type: String }, + container_name: { type: String }, + status: { type: String }, + health: { + healthy: { type: Boolean }, + source: { type: String }, + message: { type: String }, + }, + running: { type: Boolean }, + base_image: { type: String }, + exposed_ports: [ + { + port: { type: String }, + protocol: { type: String }, + }, + ], + started_at: { type: Number }, + finished_at: { type: Number }, + }, + ], + required: false, + default: undefined, + }, }, ], default: [], diff --git a/server/src/services/business/MonitorService.ts b/server/src/services/business/MonitorService.ts index f67efdf1b..d52cce1d1 100644 --- a/server/src/services/business/MonitorService.ts +++ b/server/src/services/business/MonitorService.ts @@ -362,28 +362,6 @@ class MonitorService implements IMonitorService { }, }, }, - runningContainersSnapshot: { - $last: { - $map: { - input: { - $filter: { - input: { $ifNull: ["$dockerContainers", []] }, - as: "c", - cond: { $eq: ["$$c.running", true] }, - }, - }, - as: "c", - in: { - container_id: "$$c.container_id", - container_name: "$$c.container_name", - base_image: "$$c.base_image", - exposed_ports: "$$c.exposed_ports", - status: "$$c.status", - health: "$$c.health", - }, - }, - }, - }, }; }; diff --git a/server/src/services/infrastructure/StatusService.ts b/server/src/services/infrastructure/StatusService.ts index 1bbb3a4ff..3ba851480 100644 --- a/server/src/services/infrastructure/StatusService.ts +++ b/server/src/services/infrastructure/StatusService.ts @@ -5,6 +5,7 @@ import { ICheck, } from "@/db/models/index.js"; import { StatusResponse } from "./NetworkService.js"; +import { LatestCheck } from "@/db/models/monitors/Monitor.js"; const emptyMetrics = (): ThresholdEvaluationResult["metrics"] => ({ cpu: { breached: false }, @@ -74,11 +75,21 @@ class StatusService implements IStatusService { // Store latest checks for display monitor.latestChecks = monitor.latestChecks || []; - monitor.latestChecks.push({ + const nextCheck: LatestCheck = { status: newStatus, responseTime: statusResponse.responseTime, checkedAt: monitor.lastCheckedAt, - }); + }; + // If this is a docker type, add the snapshot + if (monitor.type === "docker") { + const payload: any = statusResponse.payload; + nextCheck.containerSnapshot = payload.data; + } + monitor.latestChecks.push(nextCheck); + + if (monitor.type === "docker") { + } + while (monitor.latestChecks.length > MAX_LATEST_CHECKS) { monitor.latestChecks.shift(); } @@ -102,6 +113,7 @@ class StatusService implements IStatusService { if (allDifferent && monitor.status !== newStatus) { monitor.status = newStatus; } + return [await monitor.save(), allDifferent]; } };