Files
metona-ai-desktop/electron/utils/slo.ts
T
thzxx f4532a2bb2 refactor: 移除多余依赖,统一 MUI 为唯一 UI 库
- 移除 radix-ui、clsx、tailwind-merge、class-variance-authority、react-router-dom

- 前后端全面适配 MUI 组件,清理残留 Tailwind 工具类引用

- 优化 Agent Loop 引擎、IPC 处理器、Provider Adapter 等后端模块

- 新增 Agent 网络工具通用设计文档 v2
2026-07-05 19:15:48 +08:00

110 lines
3.3 KiB
TypeScript

/**
* Health Checker — 健康检查器
*
* 对数据库连通性、磁盘空间、内存使用执行真实检查。
*
* @see docs/生产级通用 AI Agent 智能体桌面应用:完整设计与构建指南.html — 第十一章
*/
import { existsSync } from 'fs';
import { app } from 'electron';
import type Database from 'better-sqlite3';
export interface HealthReport {
healthy: boolean;
checks: HealthCheck[];
timestamp: Date;
}
export interface HealthCheck {
name: string;
healthy: boolean;
latencyMs?: number;
error?: string;
}
export class HealthChecker {
/**
* @param getDB 数据库获取器(用于真实验证数据库连通性)
* @param dbPath 数据库文件路径(后备:文件存在性检查)
*/
constructor(
private getDB?: () => Database.Database,
private dbPath?: string,
) {}
async check(): Promise<HealthReport> {
const checks: HealthCheck[] = [];
checks.push(await this.checkDatabase());
checks.push(await this.checkFreeMemory());
checks.push(await this.checkMemoryUsage());
const allHealthy = checks.every((c) => c.healthy);
return { healthy: allHealthy, checks, timestamp: new Date() };
}
private async checkDatabase(): Promise<HealthCheck> {
const start = Date.now();
try {
// 优先使用注入的 DB 实例执行真实 ping
if (this.getDB) {
const db = this.getDB();
// 执行真实查询验证数据库连通性
db.prepare('SELECT 1').get();
return { name: 'database', healthy: true, latencyMs: Date.now() - start };
}
// 后备:检查数据库文件是否存在
if (this.dbPath && existsSync(this.dbPath)) {
return { name: 'database', healthy: true, latencyMs: Date.now() - start };
}
return { name: 'database', healthy: false, error: 'Database not available' };
} catch (error) {
return {
name: 'database',
healthy: false,
error: error instanceof Error ? error.message : String(error),
};
}
}
private async checkFreeMemory(): Promise<HealthCheck> {
try {
const userDataPath = app.getPath('userData');
if (!existsSync(userDataPath)) {
return { name: 'free_memory', healthy: false, error: 'User data path not accessible' };
}
// 检查实际可用内存(Windows/Linux 返回字节数)
const { freemem } = await import('os');
const freeBytes = freemem();
const freeMB = freeBytes / (1024 * 1024);
// 少于 200MB 视为不健康
if (freeMB < 200) {
return {
name: 'free_memory',
healthy: false,
error: `Free memory critically low: ${freeMB.toFixed(0)}MB available`,
};
}
return { name: 'free_memory', healthy: true };
} catch (error) {
return {
name: 'free_memory',
healthy: false,
error: error instanceof Error ? error.message : String(error),
};
}
}
private async checkMemoryUsage(): Promise<HealthCheck> {
const used = process.memoryUsage();
const heapUsedMB = used.heapUsed / 1024 / 1024;
const thresholdMB = 512;
return {
name: 'memory_usage',
healthy: heapUsedMB < thresholdMB,
...(heapUsedMB >= thresholdMB
? { error: `Heap usage ${heapUsedMB.toFixed(0)}MB exceeds threshold ${thresholdMB}MB` }
: {}),
};
}
}