node-os-utils
Version:
Advanced cross-platform operating system monitoring utilities with TypeScript support
592 lines • 21.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SystemMonitor = void 0;
const base_monitor_1 = require("../core/base-monitor");
/**
* 系统监控器
*
* 提供系统级别的监控功能,包括系统信息、运行时间、负载等
*/
class SystemMonitor extends base_monitor_1.BaseMonitor {
constructor(adapter, config = {}, cache) {
super(adapter, config, cache);
this.systemConfig = { ...this.getDefaultConfig(), ...config };
}
/**
* 获取系统基本信息
*/
async info() {
const cacheKey = 'system-info';
return this.executeWithCache(cacheKey, async () => {
this.validatePlatformSupport('system.info');
const rawData = await this.adapter.getSystemInfo();
return this.transformSystemInfo(rawData);
}, this.systemConfig.cacheTTL || 60000 // 系统基本信息缓存 1 分钟
);
}
/**
* 获取系统运行时间
*/
async uptime() {
if (!this.systemConfig.includeUptime) {
return this.createErrorResult(this.createUnsupportedError('system.uptime (disabled in config)'));
}
const cacheKey = 'system-uptime';
return this.executeWithCache(cacheKey, async () => {
this.validatePlatformSupport('system.uptime');
const rawData = await this.adapter.getSystemUptime();
const uptime = this.safeParseNumber(rawData.uptime) * 1000; // 转换为毫秒
const bootTime = Date.now() - uptime;
return {
uptime,
uptimeFormatted: this.formatUptime(uptime),
bootTime
};
}, this.systemConfig.cacheTTL || 30000);
}
/**
* 获取系统负载
*/
async load() {
if (!this.systemConfig.includeLoad) {
return this.createErrorResult(this.createUnsupportedError('system.load (disabled in config)'));
}
const cacheKey = 'system-load';
return this.executeWithCache(cacheKey, async () => {
this.validatePlatformSupport('system.load');
const rawData = await this.adapter.getSystemLoad();
const loadAvg = this.transformLoadAverage(rawData);
// 获取 CPU 核心数用于标准化负载
const cpuInfo = await this.adapter.getCPUInfo();
const cpuCores = cpuInfo.cores || cpuInfo.count || 1;
const normalized = {
load1: loadAvg.load1 / cpuCores,
load5: loadAvg.load5 / cpuCores,
load15: loadAvg.load15 / cpuCores
};
const status = this.evaluateLoadStatus(normalized.load1);
return {
...loadAvg,
normalized,
status
};
}, this.systemConfig.cacheTTL || 5000);
}
/**
* 获取当前登录用户
*/
async users() {
if (!this.systemConfig.includeUsers) {
return this.createErrorResult(this.createUnsupportedError('system.users (disabled in config)'));
}
const cacheKey = 'system-users';
return this.executeWithCache(cacheKey, async () => {
this.validatePlatformSupport('system.users');
const rawData = await this.adapter.getSystemUsers();
return this.transformUsersList(rawData);
}, this.systemConfig.cacheTTL || 30000);
}
/**
* 获取系统服务状态
*/
async services() {
if (!this.systemConfig.includeServices) {
return this.createErrorResult(this.createUnsupportedError('system.services (disabled in config)'));
}
const cacheKey = 'system-services';
return this.executeWithCache(cacheKey, async () => {
this.validatePlatformSupport('system.services');
const rawData = await this.adapter.getSystemServices();
return this.transformServicesList(rawData);
}, this.systemConfig.cacheTTL || 60000);
}
/**
* 获取系统资源总览
*/
async overview() {
const cacheKey = 'system-overview';
return this.executeWithCache(cacheKey, async () => {
// 并行获取各种信息
const [systemInfo, uptimeInfo, loadInfo, usersInfo] = await Promise.allSettled([
this.info(),
this.uptime().catch(() => ({ success: false, data: null })),
this.load().catch(() => ({ success: false, data: null })),
this.users().catch(() => ({ success: false, data: [] }))
]);
const system = {
hostname: systemInfo.status === 'fulfilled' && systemInfo.value.success ?
systemInfo.value.data.hostname : 'unknown',
platform: systemInfo.status === 'fulfilled' && systemInfo.value.success ?
systemInfo.value.data.platform : 'unknown',
uptime: uptimeInfo.status === 'fulfilled' && uptimeInfo.value.success ?
uptimeInfo.value.data.uptimeFormatted : 'unknown',
loadStatus: loadInfo.status === 'fulfilled' && loadInfo.value.success ?
loadInfo.value.data.status : 'unknown'
};
// 获取资源使用情况(这里可能需要调用其他监控器)
const resources = {
cpuUsage: 0, // 需要从 CPU 监控器获取
memoryUsage: 0, // 需要从内存监控器获取
diskUsage: 0, // 需要从磁盘监控器获取
networkActivity: false // 需要从网络监控器获取
};
const counts = {
processes: systemInfo.status === 'fulfilled' && systemInfo.value.success ?
systemInfo.value.data.processCount || 0 : 0,
users: usersInfo.status === 'fulfilled' && usersInfo.value.success ?
usersInfo.value.data.length : 0
};
// 评估健康状态
const health = this.evaluateSystemHealth(loadInfo, counts);
return {
system,
resources,
counts,
health
};
}, this.systemConfig.cacheTTL || 30000);
}
/**
* 获取系统时间信息
*/
async time() {
const cacheKey = 'system-time';
return this.executeWithCache(cacheKey, async () => {
const current = Date.now();
const date = new Date(current);
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';
const utcOffset = date.getTimezoneOffset() * -1; // 转换为正确的偏移量
let bootTime;
try {
const uptimeResult = await this.uptime();
if (uptimeResult.success && uptimeResult.data) {
bootTime = uptimeResult.data.bootTime;
}
}
catch {
// 忽略错误
}
return {
current,
timezone,
utcOffset,
formatted: date.toISOString(),
bootTime
};
}, this.systemConfig.cacheTTL || 60000);
}
/**
* 系统健康检查
*/
async healthCheck() {
const cacheKey = 'system-health';
return this.executeWithCache(cacheKey, async () => {
const issues = [];
const checks = {
load: true,
uptime: true,
services: true,
resources: true
};
let totalScore = 100;
// 检查系统负载
try {
const loadResult = await this.load();
if (loadResult.success && loadResult.data) {
if (loadResult.data.status === 'critical') {
issues.push(`Critical system load: ${loadResult.data.load1.toFixed(2)}`);
checks.load = false;
totalScore -= 30;
}
else if (loadResult.data.status === 'high') {
issues.push(`High system load: ${loadResult.data.load1.toFixed(2)}`);
totalScore -= 15;
}
}
}
catch (error) {
issues.push('Failed to check system load');
checks.load = false;
totalScore -= 20;
}
// 检查系统运行时间
try {
const uptimeResult = await this.uptime();
if (uptimeResult.success && uptimeResult.data) {
const uptimeHours = uptimeResult.data.uptime / (1000 * 60 * 60);
if (uptimeHours < 1) {
issues.push('System recently restarted');
totalScore -= 10;
}
}
}
catch (error) {
issues.push('Failed to check system uptime');
checks.uptime = false;
totalScore -= 10;
}
// 检查关键服务(如果启用)
if (this.systemConfig.includeServices) {
try {
const servicesResult = await this.services();
if (servicesResult.success && servicesResult.data) {
const failedServices = servicesResult.data.filter(service => service.status === 'failed' && service.enabled);
if (failedServices.length > 0) {
issues.push(`Failed services: ${failedServices.map(s => s.name).join(', ')}`);
checks.services = false;
totalScore -= failedServices.length * 10;
}
}
}
catch (error) {
issues.push('Failed to check system services');
checks.services = false;
totalScore -= 15;
}
}
// 确定整体健康状态
let status;
if (totalScore >= 90) {
status = 'healthy';
}
else if (totalScore >= 70) {
status = 'warning';
}
else {
status = 'critical';
}
return {
status,
checks,
issues,
score: Math.max(0, totalScore)
};
}, this.systemConfig.cacheTTL || 60000);
}
/**
* 配置是否包含系统负载
*/
withLoad(include) {
this.systemConfig.includeLoad = include;
return this;
}
/**
* 配置是否包含运行时间
*/
withUptime(include) {
this.systemConfig.includeUptime = include;
return this;
}
/**
* 配置是否包含系统信息
*/
withSystemInfo(include) {
this.systemConfig.includeSystemInfo = include;
return this;
}
/**
* 配置是否包含用户信息
*/
withUsers(include) {
this.systemConfig.includeUsers = include;
return this;
}
/**
* 配置是否包含服务状态
*/
withServices(include) {
this.systemConfig.includeServices = include;
return this;
}
/**
* 获取默认配置
*/
getDefaultConfig() {
return {
interval: 30000,
timeout: 15000,
cacheEnabled: true,
cacheTTL: 30000,
samples: 1,
includeDetails: true,
includeLoad: true,
includeUptime: true,
includeSystemInfo: true,
includeUsers: false, // 用户信息可能涉及隐私,默认不包含
includeServices: false // 服务检查可能需要特殊权限,默认不包含
};
}
// 私有转换方法
/**
* 转换系统信息
*/
transformSystemInfo(rawData) {
return {
hostname: rawData.hostname || rawData.name || 'unknown',
platform: rawData.platform || rawData.type || 'unknown',
distro: rawData.distro || rawData.distribution || rawData.platform || 'unknown',
release: rawData.release || rawData.version || 'unknown',
kernel: rawData.kernel || rawData.kernelVersion || 'unknown',
arch: rawData.arch || rawData.architecture || 'unknown',
uptime: this.normalizeUptime(rawData),
uptimeSeconds: this.extractUptimeSeconds(rawData),
bootTime: this.normalizeBootTime(rawData),
loadAverage: this.transformLoadAverage(rawData.loadAverage || rawData.load || {}),
userCount: rawData.userCount || rawData.users,
processCount: rawData.processCount || rawData.processes,
time: Date.now(),
timezone: rawData.timezone || Intl.DateTimeFormat().resolvedOptions().timeZone
};
}
normalizeUptime(rawData) {
const now = Date.now();
if (typeof rawData?.uptimeMs === 'number') {
return Math.max(0, rawData.uptimeMs);
}
if (typeof rawData?.uptimeMilliseconds === 'number') {
return Math.max(0, rawData.uptimeMilliseconds);
}
if (typeof rawData?.uptimeSeconds === 'number') {
return Math.max(0, rawData.uptimeSeconds * 1000);
}
if (typeof rawData?.uptime === 'number') {
if (typeof rawData?.bootTime === 'number') {
return Math.max(0, now - rawData.bootTime);
}
return Math.max(0, rawData.uptime);
}
if (typeof rawData?.bootTime === 'number') {
return Math.max(0, now - rawData.bootTime);
}
if (typeof rawData?.uptime === 'string') {
const parsed = parseFloat(rawData.uptime);
if (!Number.isNaN(parsed)) {
return Math.max(0, parsed * 1000);
}
}
return 0;
}
extractUptimeSeconds(rawData) {
// 优先读取统一的秒级字段,避免重复转换
if (typeof rawData?.uptimeSeconds === 'number') {
return Math.max(0, rawData.uptimeSeconds);
}
if (typeof rawData?.uptime === 'number' && rawData.uptime < 1e6) {
return Math.max(0, rawData.uptime);
}
if (typeof rawData?.uptime === 'number' && typeof rawData?.bootTime === 'number') {
return Math.max(0, (Date.now() - rawData.bootTime) / 1000);
}
if (typeof rawData?.bootTime === 'number') {
return Math.max(0, (Date.now() - rawData.bootTime) / 1000);
}
return undefined;
}
normalizeBootTime(rawData) {
// 保持 bootTime 的可追溯性,缺失时退化为当前时间推算
if (typeof rawData?.bootTime === 'number') {
return rawData.bootTime;
}
if (typeof rawData?.uptimeSeconds === 'number') {
return Date.now() - rawData.uptimeSeconds * 1000;
}
if (typeof rawData?.uptime === 'number') {
const uptime = rawData.uptime < 1e6 ? rawData.uptime * 1000 : rawData.uptime;
return Date.now() - uptime;
}
return undefined;
}
/**
* 转换负载平均值
*/
transformLoadAverage(rawLoad) {
return {
load1: this.safeParseNumber(rawLoad.load1 || rawLoad[0]),
load5: this.safeParseNumber(rawLoad.load5 || rawLoad[1]),
load15: this.safeParseNumber(rawLoad.load15 || rawLoad[2])
};
}
/**
* 转换用户列表
*/
transformUsersList(rawData) {
if (!Array.isArray(rawData)) {
return [];
}
return rawData.map(user => ({
username: user.username || user.user || user.name || 'unknown',
terminal: user.terminal || user.tty || user.line || 'unknown',
host: user.host || user.hostname || user.from || 'localhost',
loginTime: this.parseLoginTime(user.loginTime || user.login_time || user.time)
}));
}
/**
* 转换服务列表
*/
transformServicesList(rawData) {
if (!Array.isArray(rawData)) {
return [];
}
return rawData.map(service => ({
name: service.name
|| service.service
|| service.unit
|| service.label
|| 'unknown',
status: this.normalizeServiceStatus(service.status ?? service.state ?? service.active ?? service.sub, service),
enabled: this.isServiceEnabled(service),
description: service.description || service.desc || service.DisplayName
}));
}
isServiceEnabled(service) {
if (service?.enabled !== undefined) {
return Boolean(service.enabled);
}
const loadState = typeof service?.load === 'string' ? service.load.toLowerCase() : '';
if (loadState.includes('masked') || loadState.includes('disabled') || loadState.includes('not-found')) {
return false;
}
if (service?.StartType) {
return String(service.StartType).toLowerCase() !== 'disabled';
}
return true;
}
/**
* 格式化运行时间
*/
formatUptime(uptimeMs) {
const seconds = Math.floor(uptimeMs / 1000);
const days = Math.floor(seconds / (24 * 3600));
const hours = Math.floor((seconds % (24 * 3600)) / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const parts = [];
if (days > 0) {
parts.push(`${days} day${days > 1 ? 's' : ''}`);
}
if (hours > 0) {
parts.push(`${hours} hour${hours > 1 ? 's' : ''}`);
}
if (minutes > 0) {
parts.push(`${minutes} minute${minutes > 1 ? 's' : ''}`);
}
return parts.length > 0 ? parts.join(', ') : 'less than a minute';
}
/**
* 评估负载状态
*/
evaluateLoadStatus(normalizedLoad) {
if (normalizedLoad >= 2.0) {
return 'critical';
}
else if (normalizedLoad >= 1.0) {
return 'high';
}
else if (normalizedLoad >= 0.7) {
return 'normal';
}
else {
return 'low';
}
}
/**
* 评估系统健康状态
*/
evaluateSystemHealth(loadInfo, counts) {
const issues = [];
// 检查负载状态
if (loadInfo.status === 'fulfilled' && loadInfo.value.success) {
const loadStatus = loadInfo.value.data.status;
if (loadStatus === 'critical') {
issues.push('Critical system load detected');
}
else if (loadStatus === 'high') {
issues.push('High system load detected');
}
}
// 检查进程数(简单的启发式检查)
if (counts.processes > 1000) {
issues.push('High number of processes detected');
}
// 确定整体状态
let status = 'healthy';
if (issues.some(issue => issue.includes('Critical'))) {
status = 'critical';
}
else if (issues.length > 0) {
status = 'warning';
}
return { status, issues };
}
/**
* 规范化服务状态
*/
normalizeServiceStatus(status, service) {
if (typeof status === 'number') {
if (status === 0)
return 'running';
if (status > 0)
return 'failed';
}
if (typeof status === 'string') {
const normalizedStatus = status.toLowerCase().trim();
if (normalizedStatus === '-' && typeof service?.pid === 'number') {
return service.pid > 0 ? 'running' : 'stopped';
}
if (!Number.isNaN(Number(normalizedStatus))) {
return this.normalizeServiceStatus(Number(normalizedStatus), service);
}
if (/(running|active|online|up)/.test(normalizedStatus)) {
return 'running';
}
if (/(stopped|inactive|down|stop|exit|exited|not running)/.test(normalizedStatus)) {
return 'stopped';
}
if (/(failed|error|dead|crashed)/.test(normalizedStatus)) {
return 'failed';
}
}
if (typeof service?.pid === 'number' && service.pid > 0) {
return 'running';
}
return 'unknown';
}
/**
* 解析登录时间
*/
parseLoginTime(loginTime) {
if (typeof loginTime === 'number') {
// 如果是时间戳
if (loginTime > 1000000000000) {
// 毫秒时间戳
return loginTime;
}
else {
// 秒时间戳
return loginTime * 1000;
}
}
if (typeof loginTime === 'string') {
const parsed = Date.parse(loginTime);
if (!isNaN(parsed)) {
return parsed;
}
}
// 默认返回当前时间
return Date.now();
}
/**
* 安全解析数字
*/
safeParseNumber(value) {
if (typeof value === 'number') {
return isNaN(value) ? 0 : value;
}
if (typeof value === 'string') {
const parsed = parseFloat(value);
return isNaN(parsed) ? 0 : parsed;
}
return 0;
}
}
exports.SystemMonitor = SystemMonitor;
//# sourceMappingURL=system-monitor.js.map