Files
Termix/plugins/host-metrics/backend/widgets/uptime-collector.ts
T

106 lines
2.8 KiB
TypeScript

import type { Client } from "ssh2";
import {
execCommand,
execPowerShell,
type HostPlatform,
} from "../../../../src/backend/hosts/metrics-shared/common-utils.js";
function formatUptime(uptimeSeconds: number): string {
const days = Math.floor(uptimeSeconds / 86400);
const hours = Math.floor((uptimeSeconds % 86400) / 3600);
const minutes = Math.floor((uptimeSeconds % 3600) / 60);
return `${days}d ${hours}h ${minutes}m`;
}
async function collectDarwinUptimeMetrics(client: Client): Promise<{
seconds: number | null;
formatted: string | null;
}> {
let uptimeSeconds: number | null = null;
let uptimeFormatted: string | null = null;
try {
const bootTimeOut = await execCommand(client, "sysctl -n kern.boottime");
// "{ sec = 1700000000, usec = 123456 } Thu Nov 16 ..."
const match = bootTimeOut.stdout.match(/sec\s*=\s*(\d+)/);
if (match) {
const bootSeconds = Number(match[1]);
if (Number.isFinite(bootSeconds)) {
uptimeSeconds = Math.max(0, Date.now() / 1000 - bootSeconds);
uptimeFormatted = formatUptime(uptimeSeconds);
}
}
} catch {
// expected
}
return {
seconds: uptimeSeconds,
formatted: uptimeFormatted,
};
}
async function collectWindowsUptimeMetrics(client: Client): Promise<{
seconds: number | null;
formatted: string | null;
}> {
let uptimeSeconds: number | null = null;
let uptimeFormatted: string | null = null;
try {
const { stdout } = await execPowerShell(
client,
"$os=Get-CimInstance Win32_OperatingSystem; [PSCustomObject]@{seconds=((Get-Date) - $os.LastBootUpTime).TotalSeconds} | ConvertTo-Json -Compress",
);
const parsed = JSON.parse(stdout.trim());
const seconds = Number(parsed?.seconds);
if (Number.isFinite(seconds)) {
uptimeSeconds = Math.max(0, seconds);
uptimeFormatted = formatUptime(uptimeSeconds);
}
} catch {
// expected
}
return {
seconds: uptimeSeconds,
formatted: uptimeFormatted,
};
}
export async function collectUptimeMetrics(
client: Client,
platform?: HostPlatform,
): Promise<{
seconds: number | null;
formatted: string | null;
}> {
if (platform === "darwin") {
return collectDarwinUptimeMetrics(client);
}
if (platform === "windows") {
return collectWindowsUptimeMetrics(client);
}
let uptimeSeconds: number | null = null;
let uptimeFormatted: string | null = null;
try {
const uptimeOut = await execCommand(client, "cat /proc/uptime");
const uptimeParts = uptimeOut.stdout.trim().split(/\s+/);
if (uptimeParts.length >= 1) {
uptimeSeconds = Number(uptimeParts[0]);
if (Number.isFinite(uptimeSeconds)) {
uptimeFormatted = formatUptime(uptimeSeconds);
}
}
} catch {
// expected
}
return {
seconds: uptimeSeconds,
formatted: uptimeFormatted,
};
}