mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-11 23:04:52 +09:00
Rename SystemMetrics to SystemInfo
There are more pieces of information about a system than just its CPU, Memory and disk metrics. To avoid having to build a separate collection and subscription for metrics and system info, rename the existing system metrics to system info in anticipation of providing additonal static system information such as CPU model in it.
This commit is contained in:
1 parent
5f25aad273
commit
4e36fa1b4e
14 files changed
+128
-128
No files matched your search
@@ -53,8 +53,8 @@ export default class Controller {
|
||||
config: lib.ControllerConfig;
|
||||
app: Application;
|
||||
|
||||
/** True if (@link Controller.systemMetrics} has changed since last time it was saved */
|
||||
systemMetricsDirty = false;
|
||||
/** True if (@link Controller.systems} has changed since last time it was saved */
|
||||
systemsDirty = false;
|
||||
/** True if {@link Controller.hosts} has changed since last time it was saved */
|
||||
hostsDirty = false;
|
||||
/** True if {@link Controller.instances} has changed since last time it was saved */
|
||||
@@ -102,7 +102,7 @@ export default class Controller {
|
||||
let databaseDirectory = config.get("controller.database_directory");
|
||||
await fs.ensureDir(databaseDirectory);
|
||||
|
||||
const systemMetrics = await Controller.loadSystemMetrics(path.join(databaseDirectory, "metrics.json"));
|
||||
const systems = await Controller.loadSystems(path.join(databaseDirectory, "systems.json"));
|
||||
const hosts = await Controller.loadHosts(path.join(databaseDirectory, "hosts.json"));
|
||||
const instances = await Controller.loadInstances(path.join(databaseDirectory, "instances.json"));
|
||||
const saves = await Controller.loadSaves(path.join(databaseDirectory, "saves.json"));
|
||||
@@ -115,7 +115,7 @@ export default class Controller {
|
||||
const modStore = await lib.ModStore.fromDirectory(modsDirectory);
|
||||
|
||||
return [
|
||||
systemMetrics,
|
||||
systems,
|
||||
hosts,
|
||||
instances,
|
||||
saves,
|
||||
@@ -131,7 +131,7 @@ export default class Controller {
|
||||
configPath: string,
|
||||
config: lib.ControllerConfig,
|
||||
|
||||
public systemMetrics = new Map<lib.SystemMetrics["id"], lib.SystemMetrics>(),
|
||||
public systems = new Map<lib.SystemInfo["id"], lib.SystemInfo>(),
|
||||
/** Mapping of host id to host info */
|
||||
public hosts = new Map<number, HostInfo>(),
|
||||
/** Mapping of instance id to instance info */
|
||||
@@ -162,7 +162,7 @@ export default class Controller {
|
||||
});
|
||||
|
||||
// Handle subscriptions for all internal properties
|
||||
this.subscriptions.handle(lib.SystemMetricsUpdateEvent, this.handleSystemMetricsSubscription.bind(this));
|
||||
this.subscriptions.handle(lib.SystemInfoUpdateEvent, this.handleSystemInfoSubscription.bind(this));
|
||||
this.subscriptions.handle(lib.HostUpdatesEvent, this.handleHostSubscription.bind(this));
|
||||
this.subscriptions.handle(lib.InstanceDetailsUpdatesEvent, this.handleInstanceDetailsSubscription.bind(this));
|
||||
this.subscriptions.handle(
|
||||
@@ -444,30 +444,30 @@ export default class Controller {
|
||||
const systemMetricsIntervalSeconds = this.config.get("controller.system_metrics_interval");
|
||||
if (systemMetricsIntervalSeconds > 0) {
|
||||
this.systemMetricsInterval = setInterval(
|
||||
this.updateSystemMetrics.bind(this),
|
||||
this.updateSystems.bind(this),
|
||||
systemMetricsIntervalSeconds * 1000
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async updateSystemMetrics() {
|
||||
async updateSystems() {
|
||||
try {
|
||||
const requests: Promise<lib.SystemMetrics>[] = [];
|
||||
const requests: Promise<lib.SystemInfo>[] = [];
|
||||
for (let hostConnection of this.wsServer.hostConnections.values()) {
|
||||
if (!hostConnection.connected) {
|
||||
continue;
|
||||
}
|
||||
requests.push(hostConnection.send(new lib.SystemMetricsRequest()));
|
||||
requests.push(hostConnection.send(new lib.SystemInfoRequest()));
|
||||
}
|
||||
requests.push(lib.gatherSystemMetrics("controller"));
|
||||
requests.push(lib.gatherSystemInfo("controller"));
|
||||
const newMetrics = await Promise.all(requests);
|
||||
for (const metric of newMetrics) {
|
||||
this.systemMetrics.set(metric.id, metric);
|
||||
this.systems.set(metric.id, metric);
|
||||
}
|
||||
this.systemMetricsDirty = true;
|
||||
this.subscriptions.broadcast(new lib.SystemMetricsUpdateEvent(newMetrics));
|
||||
this.systemsDirty = true;
|
||||
this.subscriptions.broadcast(new lib.SystemInfoUpdateEvent(newMetrics));
|
||||
} catch (err: any) {
|
||||
logger.error(`Unexpected error updating system metrics:\n${err.stack ?? err.message}`);
|
||||
logger.error(`Unexpected error updating system infos:\n${err.stack ?? err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,9 +507,9 @@ export default class Controller {
|
||||
}
|
||||
|
||||
let databaseDirectory = this.config.get("controller.database_directory");
|
||||
if (this.systemMetricsDirty) {
|
||||
this.systemMetricsDirty = false;
|
||||
await Controller.saveSystemMetrics(path.join(databaseDirectory, "metrics.json"), this.systemMetrics);
|
||||
if (this.systemsDirty) {
|
||||
this.systemsDirty = false;
|
||||
await Controller.saveSystems(path.join(databaseDirectory, "systems.json"), this.systems);
|
||||
}
|
||||
|
||||
if (this.hostsDirty) {
|
||||
@@ -539,8 +539,8 @@ export default class Controller {
|
||||
await lib.invokeHook(this.plugins, "onSaveData");
|
||||
}
|
||||
|
||||
static async loadSystemMetrics(filePath: string): Promise<Map<lib.SystemMetrics["id"], lib.SystemMetrics>> {
|
||||
let json: Static<typeof lib.SystemMetrics.jsonSchema>[];
|
||||
static async loadSystems(filePath: string): Promise<Map<lib.SystemInfo["id"], lib.SystemInfo>> {
|
||||
let json: Static<typeof lib.SystemInfo.jsonSchema>[];
|
||||
try {
|
||||
json = JSON.parse(await fs.readFile(filePath, { encoding: "utf8" }));
|
||||
|
||||
@@ -551,11 +551,11 @@ export default class Controller {
|
||||
return new Map();
|
||||
}
|
||||
|
||||
return new Map(json.map(m => lib.SystemMetrics.fromJSON(m)).map(m => [m.id, m]));
|
||||
return new Map(json.map(m => lib.SystemInfo.fromJSON(m)).map(m => [m.id, m]));
|
||||
}
|
||||
|
||||
static async saveSystemMetrics(filePath: string, systemMetrics: Map<lib.SystemMetrics["id"], lib.SystemMetrics>) {
|
||||
await lib.safeOutputFile(filePath, JSON.stringify([...systemMetrics.values()], null, "\t"));
|
||||
static async saveSystems(filePath: string, systems: Map<lib.SystemInfo["id"], lib.SystemInfo>) {
|
||||
await lib.safeOutputFile(filePath, JSON.stringify([...systems.values()], null, "\t"));
|
||||
}
|
||||
|
||||
static async loadHosts(filePath: string): Promise<Map<number, HostInfo>> {
|
||||
@@ -741,11 +741,11 @@ export default class Controller {
|
||||
}
|
||||
}
|
||||
|
||||
async handleSystemMetricsSubscription(request: lib.SubscriptionRequest) {
|
||||
const systemMetrics = [...this.systemMetrics.values()].filter(
|
||||
async handleSystemInfoSubscription(request: lib.SubscriptionRequest) {
|
||||
const systems = [...this.systems.values()].filter(
|
||||
metric => metric.updatedAt > request.lastRequestTime,
|
||||
);
|
||||
return systemMetrics.length ? new lib.SystemMetricsUpdateEvent(systemMetrics) : null;
|
||||
return systems.length ? new lib.SystemInfoUpdateEvent(systems) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -354,7 +354,7 @@ export default class Host extends lib.Link {
|
||||
this.snoopEvent(lib.InstanceWhitelistUpdateEvent, this.handleWhitelistUpdateEvent.bind(this));
|
||||
this.handle(lib.InstanceAssignInternalRequest, this.handleInstanceAssignInternalRequest.bind(this));
|
||||
this.handle(lib.InstanceUnassignInternalRequest, this.handleInstanceUnassignInternalRequest.bind(this));
|
||||
this.handle(lib.SystemMetricsRequest, this.handleSystemMetricsRequest.bind(this));
|
||||
this.handle(lib.SystemInfoRequest, this.handleSystemInfoRequest.bind(this));
|
||||
this.handle(lib.HostMetricsRequest, this.handleHostMetricsRequest.bind(this));
|
||||
this.fallbackRequest(
|
||||
lib.InstanceSaveDetailsListRequest, this.fallbackInstanceSaveDetailsListRequest.bind(this),
|
||||
@@ -750,8 +750,8 @@ export default class Host extends lib.Link {
|
||||
return instanceConnection;
|
||||
}
|
||||
|
||||
async handleSystemMetricsRequest() {
|
||||
return lib.gatherSystemMetrics(this.config.get("host.id"));
|
||||
async handleSystemInfoRequest() {
|
||||
return lib.gatherSystemInfo(this.config.get("host.id"));
|
||||
}
|
||||
|
||||
async handleHostMetricsRequest() {
|
||||
|
||||
@@ -204,7 +204,7 @@ export class LogMessageEvent {
|
||||
}
|
||||
}
|
||||
|
||||
export class SystemMetrics {
|
||||
export class SystemInfo {
|
||||
constructor(
|
||||
/**
|
||||
* Id of the host these metrics originate from, or the string
|
||||
@@ -278,31 +278,31 @@ export class SystemMetrics {
|
||||
}
|
||||
}
|
||||
|
||||
export class SystemMetricsRequest {
|
||||
declare ["constructor"]: typeof SystemMetricsRequest;
|
||||
export class SystemInfoRequest {
|
||||
declare ["constructor"]: typeof SystemInfoRequest;
|
||||
static type = "request" as const;
|
||||
static src = "controller" as const;
|
||||
static dst = "host" as const;
|
||||
static Response = SystemMetrics;
|
||||
static Response = SystemInfo;
|
||||
}
|
||||
|
||||
export class SystemMetricsUpdateEvent {
|
||||
declare ["constructor"]: typeof SystemMetricsUpdateEvent;
|
||||
export class SystemInfoUpdateEvent {
|
||||
declare ["constructor"]: typeof SystemInfoUpdateEvent;
|
||||
static type = "event" as const;
|
||||
static src = "controller" as const;
|
||||
static dst = "control" as const;
|
||||
static permission = "core.system_metrics.subscribe" as const;
|
||||
static permission = "core.system.subscribe" as const;
|
||||
|
||||
constructor(
|
||||
public updates: SystemMetrics[],
|
||||
public updates: SystemInfo[],
|
||||
) { }
|
||||
|
||||
static jsonSchema = Type.Object({
|
||||
"updates": Type.Array(SystemMetrics.jsonSchema),
|
||||
"updates": Type.Array(SystemInfo.jsonSchema),
|
||||
});
|
||||
|
||||
static fromJSON(json: Static<typeof this.jsonSchema>) {
|
||||
return new this(json.updates.map(update => SystemMetrics.fromJSON(update)));
|
||||
return new this(json.updates.map(update => SystemInfo.fromJSON(update)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@ export const dataClasses: (RequestClass<unknown, unknown> | EventClass<unknown>)
|
||||
controller.LogSetSubscriptionsRequest,
|
||||
controller.LogQueryRequest,
|
||||
controller.LogMessageEvent,
|
||||
controller.SystemMetricsRequest,
|
||||
controller.SystemMetricsUpdateEvent,
|
||||
controller.SystemInfoRequest,
|
||||
controller.SystemInfoUpdateEvent,
|
||||
controller.DebugDumpWsRequest,
|
||||
controller.DebugWsMessageEvent,
|
||||
|
||||
|
||||
@@ -130,11 +130,11 @@ definePermission({
|
||||
description: "Modify the controller config or entries of the controller config.",
|
||||
});
|
||||
definePermission({
|
||||
name: "core.system_metrics.subscribe",
|
||||
title: "Subscribe to system metrics updates",
|
||||
name: "core.system.subscribe",
|
||||
title: "Subscribe to system updates",
|
||||
description:
|
||||
"Subscribe to be notified when the system metrics detailing cpu, memory and disk usage for the " +
|
||||
"controller and hosts are updated.",
|
||||
"Subscribe to be notified when the system info detailing system specific information along with metrics " +
|
||||
"such as cpu, memory and disk usage for the controller and hosts are updated.",
|
||||
});
|
||||
definePermission({
|
||||
name: "core.host.get_config",
|
||||
|
||||
@@ -2,7 +2,7 @@ import fs from "fs-extra";
|
||||
import os from "os";
|
||||
import util from "util";
|
||||
import { Gauge } from "./prometheus";
|
||||
import { SystemMetrics } from "./data";
|
||||
import { SystemInfo } from "./data";
|
||||
|
||||
function cpuModel() {
|
||||
const model = os.cpus()[0].model;
|
||||
@@ -133,7 +133,7 @@ function minZip<T>(a: T[], b: T[]): [T, T][] {
|
||||
|
||||
let previousTotalCpuMs: number[] = [];
|
||||
let previousIdleCpuMs: number[] = [];
|
||||
export async function gatherSystemMetrics(id: SystemMetrics["id"]) {
|
||||
export async function gatherSystemInfo(id: SystemInfo["id"]) {
|
||||
const cpus = os.cpus();
|
||||
const currentTotalCpuMs = cpus.map(({ times }) => times.user + times.idle + times.irq + times.nice + times.sys);
|
||||
const currentIdleCpuMs = cpus.map(({ times }) => times.idle);
|
||||
@@ -151,7 +151,7 @@ export async function gatherSystemMetrics(id: SystemMetrics["id"]) {
|
||||
diskAvailable = stats.bavail * stats.bsize;
|
||||
}
|
||||
|
||||
return new SystemMetrics(
|
||||
return new SystemInfo(
|
||||
id,
|
||||
cpuUsage,
|
||||
os.totalmem(),
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
MetricDiskUsed, MetricDiskRatio,
|
||||
} from "./system_metrics";
|
||||
import { useAccount } from "../model/account";
|
||||
import { useSystemMetrics } from "../model/system_metrics";
|
||||
import { useSystems } from "../model/system";
|
||||
import ControllerConfigTree from "./ControllerConfigTree";
|
||||
import PageLayout from "./PageLayout";
|
||||
|
||||
@@ -17,18 +17,18 @@ const { Title } = Typography;
|
||||
|
||||
export default function ControllerPage() {
|
||||
let account = useAccount();
|
||||
const [systemMetrics] = useSystemMetrics();
|
||||
const metrics = systemMetrics.get("controller");
|
||||
const [systems] = useSystems();
|
||||
const system = systems.get("controller");
|
||||
|
||||
return <PageLayout nav={[{ name: "Controller" }]}>
|
||||
<h2>Controller</h2>
|
||||
<Descriptions bordered size="small" column={{ xs: 1, md: 2, lg: 2, xl: 2, xxl: 2 }}>
|
||||
<Descriptions.Item label="CPU Usage"><MetricCpuRatio metrics={metrics} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Cores"><MetricCpuUsed metrics={metrics} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Memory Usage"><MetricMemoryRatio metrics={metrics} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Memory"><MetricMemoryUsed metrics={metrics} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Disk Usage"><MetricDiskRatio metrics={metrics} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Disk"><MetricDiskUsed metrics={metrics} /></Descriptions.Item>
|
||||
<Descriptions.Item label="CPU Usage"><MetricCpuRatio system={system} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Cores"><MetricCpuUsed system={system} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Memory Usage"><MetricMemoryRatio system={system} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Memory"><MetricMemoryUsed system={system} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Disk Usage"><MetricDiskRatio system={system} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Disk"><MetricDiskUsed system={system} /></Descriptions.Item>
|
||||
</Descriptions>
|
||||
{account.hasPermission("core.log.follow") && <>
|
||||
<Title level={5} style={{ marginTop: 16 }}>Console</Title>
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
MetricDiskUsed, MetricDiskRatio,
|
||||
} from "./system_metrics";
|
||||
import { formatTimestamp } from "../util/time_format";
|
||||
import { useSystemMetrics } from "../model/system_metrics";
|
||||
import { useSystems } from "../model/system";
|
||||
|
||||
const { Title } = Typography;
|
||||
|
||||
@@ -29,8 +29,8 @@ export default function HostViewPage() {
|
||||
let control = useContext(ControlContext);
|
||||
let account = useAccount();
|
||||
let [instances] = useInstances();
|
||||
const [systemMetrics] = useSystemMetrics();
|
||||
const metrics = systemMetrics.get(hostId);
|
||||
const [systems] = useSystems();
|
||||
const system = systems.get(hostId);
|
||||
const [host, synced] = useHost(hostId);
|
||||
const hostInstances = new Map([...instances].filter(([_id, instance]) => instance.assignedHost === hostId));
|
||||
|
||||
@@ -78,13 +78,13 @@ export default function HostViewPage() {
|
||||
{host["connected"] ? "Connected" : "Disconnected"}
|
||||
</Tag>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="CPU Usage"><MetricCpuRatio metrics={metrics} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Cores"><MetricCpuUsed metrics={metrics} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Memory Usage"><MetricMemoryRatio metrics={metrics} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Memory"><MetricMemoryUsed metrics={metrics} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Disk Usage"><MetricDiskRatio metrics={metrics} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Disk"><MetricDiskUsed metrics={metrics} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Version">{host["version"]}</Descriptions.Item>
|
||||
<Descriptions.Item label="CPU Usage"><MetricCpuRatio system={system} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Cores"><MetricCpuUsed system={system} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Memory Usage"><MetricMemoryRatio system={system} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Memory"><MetricMemoryUsed system={system} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Disk Usage"><MetricDiskRatio system={system} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Disk"><MetricDiskUsed system={system} /></Descriptions.Item>
|
||||
<Descriptions.Item label="Public Address">{host.publicAddress}</Descriptions.Item>
|
||||
{
|
||||
host.tokenValidAfter
|
||||
? <Descriptions.Item label="Tokens valid after:">
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
MetricDiskUsed, MetricDiskRatio,
|
||||
} from "./system_metrics";
|
||||
import { useHosts } from "../model/host";
|
||||
import { useSystemMetrics } from "../model/system_metrics";
|
||||
import { useSystems } from "../model/system";
|
||||
import notify, { notifyErrorHandler } from "../util/notify";
|
||||
|
||||
const strcmp = new Intl.Collator(undefined, { numeric: true, sensitivity: "base" }).compare;
|
||||
@@ -189,7 +189,7 @@ export default function HostsPage() {
|
||||
let account = useAccount();
|
||||
let navigate = useNavigate();
|
||||
let [hosts] = useHosts();
|
||||
const [metrics] = useSystemMetrics();
|
||||
const [systems] = useSystems();
|
||||
const [showRatios, setShowRatios] = useState(true);
|
||||
const [showNumbers, setShowNumbers] = useState(false);
|
||||
|
||||
@@ -209,46 +209,46 @@ export default function HostsPage() {
|
||||
},
|
||||
{
|
||||
title: "CPU%",
|
||||
sorter: (a, b) => (metrics.get(a.id)?.cpuRatio ?? 0) - (metrics.get(b.id)?.cpuRatio ?? 0),
|
||||
render: (_, host) => <MetricCpuRatio metrics={metrics.get(host.id)} />,
|
||||
sorter: (a, b) => (systems.get(a.id)?.cpuRatio ?? 0) - (systems.get(b.id)?.cpuRatio ?? 0),
|
||||
render: (_, host) => <MetricCpuRatio system={systems.get(host.id)} />,
|
||||
hidden: !showRatios,
|
||||
},
|
||||
{
|
||||
title: "Cores",
|
||||
sorter: (a, b) => (
|
||||
(metrics.get(a.id)?.cpuUsed ?? 0) - (metrics.get(b.id)?.cpuUsed ?? 0)
|
||||
(systems.get(a.id)?.cpuUsed ?? 0) - (systems.get(b.id)?.cpuUsed ?? 0)
|
||||
),
|
||||
render: (_, host) => <MetricCpuUsed metrics={metrics.get(host.id)} />,
|
||||
render: (_, host) => <MetricCpuUsed system={systems.get(host.id)} />,
|
||||
hidden: !showNumbers,
|
||||
},
|
||||
{
|
||||
title: "Mem%",
|
||||
sorter: (a, b) => (
|
||||
(metrics.get(a.id)?.memoryRatio ?? 0) - (metrics.get(b.id)?.memoryRatio ?? 0)
|
||||
(systems.get(a.id)?.memoryRatio ?? 0) - (systems.get(b.id)?.memoryRatio ?? 0)
|
||||
),
|
||||
render: (_, host) => <MetricMemoryRatio metrics={metrics.get(host.id)} />,
|
||||
render: (_, host) => <MetricMemoryRatio system={systems.get(host.id)} />,
|
||||
hidden: !showRatios,
|
||||
},
|
||||
{
|
||||
title: "Memory",
|
||||
sorter: (a, b) => (
|
||||
(metrics.get(a.id)?.memoryUsed ?? 0) - (metrics.get(b.id)?.memoryUsed ?? 0)
|
||||
(systems.get(a.id)?.memoryUsed ?? 0) - (systems.get(b.id)?.memoryUsed ?? 0)
|
||||
),
|
||||
render: (_, host) => <MetricMemoryUsed metrics={metrics.get(host.id)} />,
|
||||
render: (_, host) => <MetricMemoryUsed system={systems.get(host.id)} />,
|
||||
hidden: !showNumbers,
|
||||
},
|
||||
{
|
||||
title: "Disk%",
|
||||
sorter: (a, b) => (metrics.get(a.id)?.diskAvailable ?? 0) - (metrics.get(b.id)?.diskAvailable ?? 0),
|
||||
render: (_, host) => <MetricDiskRatio metrics={metrics.get(host.id)} />,
|
||||
sorter: (a, b) => (systems.get(a.id)?.diskAvailable ?? 0) - (systems.get(b.id)?.diskAvailable ?? 0),
|
||||
render: (_, host) => <MetricDiskRatio system={systems.get(host.id)} />,
|
||||
hidden: !showRatios,
|
||||
},
|
||||
{
|
||||
title: "Disk",
|
||||
sorter: (a, b) => (
|
||||
(metrics.get(a.id)?.diskUsed ?? 0) - (metrics.get(b.id)?.diskUsed ?? 0)
|
||||
(systems.get(a.id)?.diskUsed ?? 0) - (systems.get(b.id)?.diskUsed ?? 0)
|
||||
),
|
||||
render: (_, host) => <MetricDiskUsed metrics={metrics.get(host.id)} />,
|
||||
render: (_, host) => <MetricDiskUsed system={systems.get(host.id)} />,
|
||||
hidden: !showNumbers,
|
||||
},
|
||||
{
|
||||
|
||||
@@ -3,53 +3,53 @@ import React from "react";
|
||||
import * as lib from "@clusterio/lib";
|
||||
import { Progress } from "antd";
|
||||
|
||||
export function MetricCpuRatio(props: { metrics?: lib.SystemMetrics }) {
|
||||
if (!props.metrics) {
|
||||
export function MetricCpuRatio(props: { system?: lib.SystemInfo }) {
|
||||
if (!props.system) {
|
||||
return "N/A";
|
||||
}
|
||||
const ratio = props.metrics.cpuRatio;
|
||||
const ratio = props.system.cpuRatio;
|
||||
return <Progress status="normal" percent={Math.ceil(ratio * 100)}/>;
|
||||
}
|
||||
|
||||
export function MetricCpuUsed(props: { metrics?: lib.SystemMetrics }) {
|
||||
if (!props.metrics) {
|
||||
export function MetricCpuUsed(props: { system?: lib.SystemInfo }) {
|
||||
if (!props.system) {
|
||||
return "N/A";
|
||||
}
|
||||
const used = props.metrics.cpuUsed.toLocaleString(undefined, { maximumFractionDigits: 1 });
|
||||
const capacity = props.metrics.cpuCapacity;
|
||||
const used = props.system.cpuUsed.toLocaleString(undefined, { maximumFractionDigits: 1 });
|
||||
const capacity = props.system.cpuCapacity;
|
||||
return `${used} / ${capacity}`;
|
||||
}
|
||||
|
||||
export function MetricMemoryRatio(props: { metrics?: lib.SystemMetrics }) {
|
||||
if (!props.metrics) {
|
||||
export function MetricMemoryRatio(props: { system?: lib.SystemInfo }) {
|
||||
if (!props.system) {
|
||||
return "N/A";
|
||||
}
|
||||
const ratio = props.metrics.memoryRatio;
|
||||
const ratio = props.system.memoryRatio;
|
||||
return <Progress status="normal" percent={Math.ceil(ratio * 100)}/>;
|
||||
}
|
||||
|
||||
export function MetricMemoryUsed(props: { metrics?: lib.SystemMetrics }) {
|
||||
if (!props.metrics) {
|
||||
export function MetricMemoryUsed(props: { system?: lib.SystemInfo }) {
|
||||
if (!props.system) {
|
||||
return "N/A";
|
||||
}
|
||||
const used = lib.formatBytes(props.metrics.memoryUsed, "binary");
|
||||
const capacity = lib.formatBytes(props.metrics.memoryCapacity, "binary");
|
||||
const used = lib.formatBytes(props.system.memoryUsed, "binary");
|
||||
const capacity = lib.formatBytes(props.system.memoryCapacity, "binary");
|
||||
return `${used} / ${capacity}`;
|
||||
}
|
||||
|
||||
export function MetricDiskRatio(props: { metrics?: lib.SystemMetrics }) {
|
||||
if (!props.metrics) {
|
||||
export function MetricDiskRatio(props: { system?: lib.SystemInfo }) {
|
||||
if (!props.system) {
|
||||
return "N/A";
|
||||
}
|
||||
const ratio = props.metrics.diskRatio;
|
||||
const ratio = props.system.diskRatio;
|
||||
return <Progress status="normal" percent={Math.ceil(ratio * 100)}/>;
|
||||
}
|
||||
|
||||
export function MetricDiskUsed(props: { metrics?: lib.SystemMetrics }) {
|
||||
if (!props.metrics) {
|
||||
export function MetricDiskUsed(props: { system?: lib.SystemInfo }) {
|
||||
if (!props.system) {
|
||||
return "N/A";
|
||||
}
|
||||
const used = lib.formatBytes(props.metrics.diskUsed);
|
||||
const capacity = lib.formatBytes(props.metrics.diskCapacity);
|
||||
const used = lib.formatBytes(props.system.diskUsed);
|
||||
const capacity = lib.formatBytes(props.system.diskCapacity);
|
||||
return `${used} / ${capacity}`;
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useCallback, useContext, useSyncExternalStore } from "react";
|
||||
import ControlContext from "../components/ControlContext";
|
||||
|
||||
export function useSystemMetrics() {
|
||||
export function useSystems() {
|
||||
const control = useContext(ControlContext);
|
||||
const subscribe = useCallback((callback: () => void) => control.systemMetrics.subscribe(callback), [control]);
|
||||
return useSyncExternalStore(subscribe, () => control.systemMetrics.getSnapshot());
|
||||
const subscribe = useCallback((callback: () => void) => control.systems.subscribe(callback), [control]);
|
||||
return useSyncExternalStore(subscribe, () => control.systems.getSnapshot());
|
||||
}
|
||||
@@ -59,7 +59,7 @@ export class Control extends lib.Link {
|
||||
logHandlers: Map<lib.LogFilter, logHandler[]> = new Map();
|
||||
|
||||
/** Updates handled by the subscription service */
|
||||
systemMetrics = new lib.EventSubscriber(lib.SystemMetricsUpdateEvent, this);
|
||||
systems = new lib.EventSubscriber(lib.SystemInfoUpdateEvent, this);
|
||||
hosts = new lib.EventSubscriber(lib.HostUpdatesEvent, this);
|
||||
instances = new lib.EventSubscriber(lib.InstanceDetailsUpdatesEvent, this);
|
||||
saves = new lib.EventSubscriber(lib.InstanceSaveDetailsUpdatesEvent, this);
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
const assert = require("assert").strict;
|
||||
|
||||
const lib = require("@clusterio/lib");
|
||||
const { SystemInfo } = lib;
|
||||
|
||||
|
||||
describe("lib/data/ModPack", function() {
|
||||
describe("class SystemInfo", function() {
|
||||
it("correctly calculates derived metrics", function() {
|
||||
const system = new SystemInfo("controller", [0.5, 0.25, 0, 1], 1024, 768, 2048, 512, 0, false);
|
||||
assert.equal(system.cpuCapacity, 4);
|
||||
assert.equal(system.cpuUsed, 1.75);
|
||||
assert.equal(system.cpuAvailable, 2.25);
|
||||
assert.equal(system.cpuRatio, 0.4375);
|
||||
assert.equal(system.memoryUsed, 256);
|
||||
assert.equal(system.memoryRatio, 0.25);
|
||||
assert.equal(system.diskUsed, 1536);
|
||||
assert.equal(system.diskRatio, 0.75);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,22 +0,0 @@
|
||||
"use strict";
|
||||
const assert = require("assert").strict;
|
||||
|
||||
const lib = require("@clusterio/lib");
|
||||
const { SystemMetrics } = lib;
|
||||
|
||||
|
||||
describe("lib/data/ModPack", function() {
|
||||
describe("class SystemMetrics", function() {
|
||||
it("correctly calculates derived metrics", function() {
|
||||
const metrics = new SystemMetrics("controller", [0.5, 0.25, 0, 1], 1024, 768, 2048, 512, 0, false);
|
||||
assert.equal(metrics.cpuCapacity, 4);
|
||||
assert.equal(metrics.cpuUsed, 1.75);
|
||||
assert.equal(metrics.cpuAvailable, 2.25);
|
||||
assert.equal(metrics.cpuRatio, 0.4375);
|
||||
assert.equal(metrics.memoryUsed, 256);
|
||||
assert.equal(metrics.memoryRatio, 0.25);
|
||||
assert.equal(metrics.diskUsed, 1536);
|
||||
assert.equal(metrics.diskRatio, 0.75);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user