system health in settings
This commit is contained in:
@@ -2494,3 +2494,11 @@ export function recordAutoDeployRun(deployId: string, clientId: string) {
|
||||
Date.now(),
|
||||
);
|
||||
}
|
||||
|
||||
export function getDatabaseFileSizeBytes(): number {
|
||||
try {
|
||||
return Bun.file(dbPath).size;
|
||||
} catch {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ import { authenticateRequest } from "../../auth";
|
||||
import { AuditAction, getAuditLogs, logAudit } from "../../auditLog";
|
||||
import { logger } from "../../logger";
|
||||
import { getConfig, updateSecurityConfig, updateTlsConfig, updateAppearanceConfig, updateChatConfig, getExportableConfig, importFullConfig, updateRegistrationConfig, updateBuildRateLimitConfig, updateThumbnailsConfig } from "../../config";
|
||||
import { getClientMetricsSummary, getClientMetricsSummaryForUser } from "../../db";
|
||||
import { getClientMetricsSummary, getClientMetricsSummaryForUser, getDatabaseFileSizeBytes } from "../../db";
|
||||
import { getThumbnailStats } from "../../thumbnails";
|
||||
import { getClientCount, getOnlineClients } from "../../clientManager";
|
||||
import { metrics } from "../../metrics";
|
||||
import { requirePermission } from "../../rbac";
|
||||
import { getUserTelegramChatId, setUserTelegramChatId, getUserClientAccessScope, listUserClientRuleIdsByAccess, canUserAccessClient } from "../../users";
|
||||
@@ -750,5 +752,48 @@ export async function handleMiscRoutes(
|
||||
}
|
||||
}
|
||||
|
||||
// GET /api/settings/health
|
||||
if (req.method === "GET" && url.pathname === "/api/settings/health") {
|
||||
const user = await authenticateRequest(req);
|
||||
if (!user) return new Response("Unauthorized", { status: 401 });
|
||||
if (user.role !== "admin") return new Response("Forbidden", { status: 403 });
|
||||
|
||||
const mem = process.memoryUsage();
|
||||
return Response.json({
|
||||
memory: {
|
||||
rss: mem.rss,
|
||||
heapTotal: mem.heapTotal,
|
||||
heapUsed: mem.heapUsed,
|
||||
external: mem.external,
|
||||
arrayBuffers: (mem as any).arrayBuffers ?? 0,
|
||||
},
|
||||
uptime: Math.floor(process.uptime()),
|
||||
components: {
|
||||
thumbnails: getThumbnailStats(),
|
||||
clients: {
|
||||
inMemory: getClientCount(),
|
||||
online: getOnlineClients().length,
|
||||
},
|
||||
database: {
|
||||
fileSizeBytes: getDatabaseFileSizeBytes(),
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// POST /api/settings/gc
|
||||
if (req.method === "POST" && url.pathname === "/api/settings/gc") {
|
||||
const user = await authenticateRequest(req);
|
||||
if (!user) return new Response("Unauthorized", { status: 401 });
|
||||
if (user.role !== "admin") return new Response("Forbidden", { status: 403 });
|
||||
|
||||
const before = process.memoryUsage().heapUsed;
|
||||
if (typeof Bun !== "undefined" && typeof (Bun as any).gc === "function") {
|
||||
(Bun as any).gc(true);
|
||||
}
|
||||
const after = process.memoryUsage().heapUsed;
|
||||
return Response.json({ ok: true, freedBytes: Math.max(0, before - after) });
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -216,6 +216,28 @@ export function clearThumbnailRequest(id: string) {
|
||||
thumbnailRequests.delete(id);
|
||||
}
|
||||
|
||||
export function getThumbnailStats(): {
|
||||
cachedCount: number;
|
||||
cachedBytes: number;
|
||||
pendingFrames: number;
|
||||
genActive: number;
|
||||
genQueued: number;
|
||||
genStateTracked: number;
|
||||
cacheMax: number;
|
||||
} {
|
||||
let cachedBytes = 0;
|
||||
for (const rec of thumbnails.values()) cachedBytes += rec.bytes.byteLength;
|
||||
return {
|
||||
cachedCount: thumbnails.size,
|
||||
cachedBytes,
|
||||
pendingFrames: latestFrames.size,
|
||||
genActive: _activeThumbnailGen,
|
||||
genQueued: _thumbnailGenQueue.length,
|
||||
genStateTracked: thumbnailGenState.size,
|
||||
cacheMax: THUMBNAIL_CACHE_MAX,
|
||||
};
|
||||
}
|
||||
|
||||
export function consumeThumbnailRequest(id: string, windowMs = 5000): boolean {
|
||||
const ts = thumbnailRequests.get(id);
|
||||
if (!ts) return false;
|
||||
|
||||
Reference in New Issue
Block a user