import type http from "node:http"; import { WebSocketServer } from "ws"; import { validateWebSocketRequest } from "../auth/auth"; import { getLastAdvancedStatsFile, recordAdvancedStats, } from "../monitoring/utilts"; import { docker } from "../constants"; export const setupDockerStatsMonitoringSocketServer = ( server: http.Server, ) => { const wssTerm = new WebSocketServer({ noServer: true, path: "/listen-docker-stats-monitoring", }); server.on("upgrade", (req, socket, head) => { const { pathname } = new URL(req.url || "", `http://${req.headers.host}`); if (pathname === "/_next/webpack-hmr") { return; } if (pathname === "/listen-docker-stats-monitoring") { wssTerm.handleUpgrade(req, socket, head, function done(ws) { wssTerm.emit("connection", ws, req); }); } }); wssTerm.on("connection", async (ws, req) => { const url = new URL(req.url || "", `http://${req.headers.host}`); const appName = url.searchParams.get("appName"); const appType = (url.searchParams.get("appType") || "application") as | "application" | "stack" | "docker-compose"; const { user, session } = await validateWebSocketRequest(req); if (!appName) { ws.close(4000, "appName no provided"); return; } if (!user || !session) { ws.close(); return; } const intervalId = setInterval(async () => { try { const filter = { status: ["running"], ...(appType === "application" && { label: [`com.docker.swarm.service.name=${appName}`], }), ...(appType === "stack" && { label: [`com.docker.swarm.task.name=${appName}`], }), ...(appType === "docker-compose" && { name: [appName], }), }; const containers = await docker.listContainers({ filters: JSON.stringify(filter), }); const container = containers[0]; if (!container || container?.State !== "running") { ws.close(4000, "Container not running"); return; } await recordAdvancedStats(appName, container?.Id); const data = await getLastAdvancedStatsFile(appName); ws.send( JSON.stringify({ data, }), ); } catch (error) { // @ts-ignore ws.close(4000, `Error: ${error.message}`); } }, 1300); ws.on("close", () => { clearInterval(intervalId); }); }); };