@futdevpro/nts-dynamo 1.15.437 → 1.15.438
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/_modules/machine-monitor/_models/machine-state-recorder-deps.interface.d.ts +18 -0
- package/build/_modules/machine-monitor/_models/machine-state-recorder-deps.interface.d.ts.map +1 -0
- package/build/_modules/machine-monitor/_models/machine-state-recorder-deps.interface.js +3 -0
- package/build/_modules/machine-monitor/_models/machine-state-recorder-deps.interface.js.map +1 -0
- package/build/_modules/machine-monitor/_models/machine-state-row.interface.d.ts +34 -0
- package/build/_modules/machine-monitor/_models/machine-state-row.interface.d.ts.map +1 -0
- package/build/_modules/machine-monitor/_models/machine-state-row.interface.js +3 -0
- package/build/_modules/machine-monitor/_models/machine-state-row.interface.js.map +1 -0
- package/build/_modules/machine-monitor/_models/machine-state-summary.interface.d.ts +14 -0
- package/build/_modules/machine-monitor/_models/machine-state-summary.interface.d.ts.map +1 -0
- package/build/_modules/machine-monitor/_models/machine-state-summary.interface.js +3 -0
- package/build/_modules/machine-monitor/_models/machine-state-summary.interface.js.map +1 -0
- package/build/_modules/machine-monitor/index.d.ts +8 -0
- package/build/_modules/machine-monitor/index.d.ts.map +1 -0
- package/build/_modules/machine-monitor/index.js +12 -0
- package/build/_modules/machine-monitor/index.js.map +1 -0
- package/build/_modules/machine-monitor/machine-state-window.util.d.ts +18 -0
- package/build/_modules/machine-monitor/machine-state-window.util.d.ts.map +1 -0
- package/build/_modules/machine-monitor/machine-state-window.util.js +68 -0
- package/build/_modules/machine-monitor/machine-state-window.util.js.map +1 -0
- package/build/_modules/machine-monitor/machine-state-windows-runners.util.d.ts +14 -0
- package/build/_modules/machine-monitor/machine-state-windows-runners.util.d.ts.map +1 -0
- package/build/_modules/machine-monitor/machine-state-windows-runners.util.js +26 -0
- package/build/_modules/machine-monitor/machine-state-windows-runners.util.js.map +1 -0
- package/build/_modules/machine-monitor/machine-state.recorder.d.ts +46 -0
- package/build/_modules/machine-monitor/machine-state.recorder.d.ts.map +1 -0
- package/build/_modules/machine-monitor/machine-state.recorder.js +123 -0
- package/build/_modules/machine-monitor/machine-state.recorder.js.map +1 -0
- package/build/_modules/machine-monitor/machine-state.util.d.ts +44 -0
- package/build/_modules/machine-monitor/machine-state.util.d.ts.map +1 -0
- package/build/_modules/machine-monitor/machine-state.util.js +121 -0
- package/build/_modules/machine-monitor/machine-state.util.js.map +1 -0
- package/package.json +11 -2
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** The dependencies of the machine-state recorder — the spec replaces them. */
|
|
2
|
+
export interface DyNTS_MachineStateRecorderDeps_Interface {
|
|
3
|
+
/** The folder of the daily JSONL files. */
|
|
4
|
+
dir: string;
|
|
5
|
+
runTypeperf: (counters: readonly string[]) => Promise<string>;
|
|
6
|
+
runTasklist: () => Promise<string>;
|
|
7
|
+
/** 🌡️ The `nvidia-smi` output (missing ⇒ no temperature measurement). */
|
|
8
|
+
runGpuTemps?: () => Promise<string>;
|
|
9
|
+
/** 🌡️ The alert above the threshold; missing ⇒ only the log. */
|
|
10
|
+
alert?: (text: string) => Promise<void>;
|
|
11
|
+
log: (code: string, detail: string, isError: boolean) => void;
|
|
12
|
+
/**
|
|
13
|
+
* The prefix of the logged codes (`<prefix>-MACHINE-STATE-FAILED`, …). Default: `DyNTS-MM`. An app that already
|
|
14
|
+
* counts its own codes keeps them (e.g. `MA` ⇒ `MA-MACHINE-STATE-FAILED`).
|
|
15
|
+
*/
|
|
16
|
+
codePrefix?: string;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=machine-state-recorder-deps.interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"machine-state-recorder-deps.interface.d.ts","sourceRoot":"","sources":["../../../../src/_modules/machine-monitor/_models/machine-state-recorder-deps.interface.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,WAAW,wCAAwC;IACvD,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9D,WAAW,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACnC,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACpC,iEAAiE;IACjE,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9D;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"machine-state-recorder-deps.interface.js","sourceRoot":"","sources":["../../../../src/_modules/machine-monitor/_models/machine-state-recorder-deps.interface.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** The momentary queue of one disk. */
|
|
2
|
+
export interface DyNTS_MachineDiskState_Interface {
|
|
3
|
+
/** The `typeperf` instance name (e.g. `4 C:`). */
|
|
4
|
+
disk: string;
|
|
5
|
+
queue: number | null;
|
|
6
|
+
/** Average service time, milliseconds. */
|
|
7
|
+
latencyMs: number | null;
|
|
8
|
+
}
|
|
9
|
+
/** The memory of one process. */
|
|
10
|
+
export interface DyNTS_MachineProcessMemory_Interface {
|
|
11
|
+
name: string;
|
|
12
|
+
pid: number;
|
|
13
|
+
memMb: number;
|
|
14
|
+
}
|
|
15
|
+
/** 🌡️ The temperature of one graphics card. */
|
|
16
|
+
export interface DyNTS_MachineGpuTemp_Interface {
|
|
17
|
+
name: string;
|
|
18
|
+
tempC: number | null;
|
|
19
|
+
}
|
|
20
|
+
/** One per-minute row of the machine-state log. */
|
|
21
|
+
export interface DyNTS_MachineStateRow_Interface {
|
|
22
|
+
ts: string;
|
|
23
|
+
availableMb: number | null;
|
|
24
|
+
commitGb: number | null;
|
|
25
|
+
commitLimitGb: number | null;
|
|
26
|
+
/** The commit as a percentage of the limit. */
|
|
27
|
+
commitPct: number | null;
|
|
28
|
+
pagefilePct: number | null;
|
|
29
|
+
disks: DyNTS_MachineDiskState_Interface[];
|
|
30
|
+
top: DyNTS_MachineProcessMemory_Interface[];
|
|
31
|
+
/** 🌡️ The temperature of the graphics cards (`nvidia-smi`; a read error ⇒ missing, the row still goes). */
|
|
32
|
+
gpus?: DyNTS_MachineGpuTemp_Interface[];
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=machine-state-row.interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"machine-state-row.interface.d.ts","sourceRoot":"","sources":["../../../../src/_modules/machine-monitor/_models/machine-state-row.interface.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,MAAM,WAAW,gCAAgC;IAC/C,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,0CAA0C;IAC1C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,iCAAiC;AACjC,MAAM,WAAW,oCAAoC;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,gDAAgD;AAChD,MAAM,WAAW,8BAA8B;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,mDAAmD;AACnD,MAAM,WAAW,+BAA+B;IAC9C,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,+CAA+C;IAC/C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,gCAAgC,EAAE,CAAC;IAC1C,GAAG,EAAE,oCAAoC,EAAE,CAAC;IAC5C,4GAA4G;IAC5G,IAAI,CAAC,EAAE,8BAA8B,EAAE,CAAC;CACzC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"machine-state-row.interface.js","sourceRoot":"","sources":["../../../../src/_modules/machine-monitor/_models/machine-state-row.interface.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { DyNTS_MachineDiskState_Interface, DyNTS_MachineProcessMemory_Interface } from './machine-state-row.interface';
|
|
2
|
+
/** The machine-state summary of a time window (e.g. around a CPU spike). */
|
|
3
|
+
export interface DyNTS_MachineStateSummary_Interface {
|
|
4
|
+
rows: number;
|
|
5
|
+
minAvailableMb: number | null;
|
|
6
|
+
maxCommitPct: number | null;
|
|
7
|
+
maxPagefilePct: number | null;
|
|
8
|
+
/** 🌡️ The highest graphics-card temperature in the window; no data ⇒ `null`. */
|
|
9
|
+
maxGpuTempC: number | null;
|
|
10
|
+
worstDisk: DyNTS_MachineDiskState_Interface | null;
|
|
11
|
+
/** The top processes of the row with the least free memory. */
|
|
12
|
+
topAtLow: DyNTS_MachineProcessMemory_Interface[];
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=machine-state-summary.interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"machine-state-summary.interface.d.ts","sourceRoot":"","sources":["../../../../src/_modules/machine-monitor/_models/machine-state-summary.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gCAAgC,EAAE,oCAAoC,EACvE,MAAM,+BAA+B,CAAC;AAEvC,4EAA4E;AAC5E,MAAM,WAAW,mCAAmC;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,iFAAiF;IACjF,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,gCAAgC,GAAG,IAAI,CAAC;IACnD,+DAA+D;IAC/D,QAAQ,EAAE,oCAAoC,EAAE,CAAC;CAClD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"machine-state-summary.interface.js","sourceRoot":"","sources":["../../../../src/_modules/machine-monitor/_models/machine-state-summary.interface.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { DyNTS_MachineDiskState_Interface, DyNTS_MachineGpuTemp_Interface, DyNTS_MachineProcessMemory_Interface, DyNTS_MachineStateRow_Interface, } from './_models/machine-state-row.interface';
|
|
2
|
+
export { DyNTS_MachineStateSummary_Interface } from './_models/machine-state-summary.interface';
|
|
3
|
+
export { DyNTS_MachineStateRecorderDeps_Interface } from './_models/machine-state-recorder-deps.interface';
|
|
4
|
+
export { DyNTS_MachineState_Util } from './machine-state.util';
|
|
5
|
+
export { DyNTS_MachineStateWindow_Util } from './machine-state-window.util';
|
|
6
|
+
export { DyNTS_MachineState_Recorder } from './machine-state.recorder';
|
|
7
|
+
export { DyNTS_MachineStateWindowsRunners_Util } from './machine-state-windows-runners.util';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/_modules/machine-monitor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gCAAgC,EAChC,8BAA8B,EAC9B,oCAAoC,EACpC,+BAA+B,GAChC,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,mCAAmC,EAAE,MAAM,2CAA2C,CAAC;AAChG,OAAO,EAAE,wCAAwC,EAAE,MAAM,iDAAiD,CAAC;AAC3G,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,qCAAqC,EAAE,MAAM,sCAAsC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DyNTS_MachineStateWindowsRunners_Util = exports.DyNTS_MachineState_Recorder = exports.DyNTS_MachineStateWindow_Util = exports.DyNTS_MachineState_Util = void 0;
|
|
4
|
+
var machine_state_util_1 = require("./machine-state.util");
|
|
5
|
+
Object.defineProperty(exports, "DyNTS_MachineState_Util", { enumerable: true, get: function () { return machine_state_util_1.DyNTS_MachineState_Util; } });
|
|
6
|
+
var machine_state_window_util_1 = require("./machine-state-window.util");
|
|
7
|
+
Object.defineProperty(exports, "DyNTS_MachineStateWindow_Util", { enumerable: true, get: function () { return machine_state_window_util_1.DyNTS_MachineStateWindow_Util; } });
|
|
8
|
+
var machine_state_recorder_1 = require("./machine-state.recorder");
|
|
9
|
+
Object.defineProperty(exports, "DyNTS_MachineState_Recorder", { enumerable: true, get: function () { return machine_state_recorder_1.DyNTS_MachineState_Recorder; } });
|
|
10
|
+
var machine_state_windows_runners_util_1 = require("./machine-state-windows-runners.util");
|
|
11
|
+
Object.defineProperty(exports, "DyNTS_MachineStateWindowsRunners_Util", { enumerable: true, get: function () { return machine_state_windows_runners_util_1.DyNTS_MachineStateWindowsRunners_Util; } });
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/_modules/machine-monitor/index.ts"],"names":[],"mappings":";;;AAQA,2DAA+D;AAAtD,6HAAA,uBAAuB,OAAA;AAChC,yEAA4E;AAAnE,0IAAA,6BAA6B,OAAA;AACtC,mEAAuE;AAA9D,qIAAA,2BAA2B,OAAA;AACpC,2FAA6F;AAApF,2JAAA,qCAAqC,OAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { DyNTS_MachineStateRow_Interface } from './_models/machine-state-row.interface';
|
|
2
|
+
import { DyNTS_MachineStateSummary_Interface } from './_models/machine-state-summary.interface';
|
|
3
|
+
/**
|
|
4
|
+
* BFR-FLEET-033 — the helpers of a time window of the machine-state log (e.g. ±2 minutes around a CPU spike).
|
|
5
|
+
*
|
|
6
|
+
* @description Transplanted from My Assistant (`MachineStateWindow_Util`), the logic unchanged.
|
|
7
|
+
*/
|
|
8
|
+
export declare class DyNTS_MachineStateWindow_Util {
|
|
9
|
+
/** The rows of a daily JSONL inside `[fromMs, toMs]` (a broken / NUL row is skipped). **Pure function.** */
|
|
10
|
+
static rowsBetween(jsonl: string, fromMs: number, toMs: number): DyNTS_MachineStateRow_Interface[];
|
|
11
|
+
/** The summary of the window; empty ⇒ `null`. **Pure function.** */
|
|
12
|
+
static summarize(rows: readonly DyNTS_MachineStateRow_Interface[]): DyNTS_MachineStateSummary_Interface | null;
|
|
13
|
+
/** The largest value; empty ⇒ `null`. **Pure function.** */
|
|
14
|
+
static max(values: readonly number[]): number | null;
|
|
15
|
+
/** One report line of the summary. **Pure function.** */
|
|
16
|
+
static line(summary: DyNTS_MachineStateSummary_Interface | null | undefined): string;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=machine-state-window.util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"machine-state-window.util.d.ts","sourceRoot":"","sources":["../../../src/_modules/machine-monitor/machine-state-window.util.ts"],"names":[],"mappings":"AAAA,OAAO,EACmE,+BAA+B,EACxG,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,mCAAmC,EAAE,MAAM,2CAA2C,CAAC;AAEhG;;;;GAIG;AACH,qBAAa,6BAA6B;IAExC,4GAA4G;IAC5G,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,+BAA+B,EAAE;IAmBlG,oEAAoE;IACpE,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,+BAA+B,EAAE,GAAG,mCAAmC,GAAG,IAAI;IAyB9G,4DAA4D;IAC5D,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI;IAIpD,yDAAyD;IACzD,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,mCAAmC,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM;CAYrF"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DyNTS_MachineStateWindow_Util = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* BFR-FLEET-033 — the helpers of a time window of the machine-state log (e.g. ±2 minutes around a CPU spike).
|
|
6
|
+
*
|
|
7
|
+
* @description Transplanted from My Assistant (`MachineStateWindow_Util`), the logic unchanged.
|
|
8
|
+
*/
|
|
9
|
+
class DyNTS_MachineStateWindow_Util {
|
|
10
|
+
/** The rows of a daily JSONL inside `[fromMs, toMs]` (a broken / NUL row is skipped). **Pure function.** */
|
|
11
|
+
static rowsBetween(jsonl, fromMs, toMs) {
|
|
12
|
+
const out = [];
|
|
13
|
+
for (const line of jsonl.split(/\r?\n/u)) {
|
|
14
|
+
if (!line.startsWith('{'))
|
|
15
|
+
continue;
|
|
16
|
+
try {
|
|
17
|
+
const row = JSON.parse(line);
|
|
18
|
+
const at = Date.parse(row.ts);
|
|
19
|
+
if (at >= fromMs && at <= toMs)
|
|
20
|
+
out.push(row);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return out;
|
|
27
|
+
}
|
|
28
|
+
/** The summary of the window; empty ⇒ `null`. **Pure function.** */
|
|
29
|
+
static summarize(rows) {
|
|
30
|
+
if (!rows.length)
|
|
31
|
+
return null;
|
|
32
|
+
const nums = (pick) => rows.map(pick).filter((value) => value !== null);
|
|
33
|
+
const available = nums((row) => row.availableMb);
|
|
34
|
+
const low = [...rows].sort((a, b) => (a.availableMb ?? Infinity) - (b.availableMb ?? Infinity))[0];
|
|
35
|
+
const disks = rows.flatMap((row) => row.disks);
|
|
36
|
+
const worstDisk = [...disks]
|
|
37
|
+
.sort((a, b) => (b.queue ?? 0) - (a.queue ?? 0) || (b.latencyMs ?? 0) - (a.latencyMs ?? 0))[0] ?? null;
|
|
38
|
+
return {
|
|
39
|
+
rows: rows.length,
|
|
40
|
+
minAvailableMb: available.length ? Math.min(...available) : null,
|
|
41
|
+
maxCommitPct: DyNTS_MachineStateWindow_Util.max(nums((row) => row.commitPct)),
|
|
42
|
+
maxPagefilePct: DyNTS_MachineStateWindow_Util.max(nums((row) => row.pagefilePct)),
|
|
43
|
+
maxGpuTempC: DyNTS_MachineStateWindow_Util.max(rows
|
|
44
|
+
.flatMap((row) => (row.gpus ?? []).map((gpu) => gpu.tempC))
|
|
45
|
+
.filter((value) => value !== null)),
|
|
46
|
+
worstDisk: worstDisk,
|
|
47
|
+
topAtLow: low?.top ?? [],
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** The largest value; empty ⇒ `null`. **Pure function.** */
|
|
51
|
+
static max(values) {
|
|
52
|
+
return values.length ? Math.max(...values) : null;
|
|
53
|
+
}
|
|
54
|
+
/** One report line of the summary. **Pure function.** */
|
|
55
|
+
static line(summary) {
|
|
56
|
+
if (!summary)
|
|
57
|
+
return '- Machine state (±2 min): no data (the per-minute log wrote no row for this window)';
|
|
58
|
+
const disk = summary.worstDisk;
|
|
59
|
+
return `- Machine state (±2 min, ${summary.rows} samples): least free memory ${summary.minAvailableMb ?? '?'} MB, `
|
|
60
|
+
+ `commit max ${summary.maxCommitPct ?? '?'}%, page file max ${summary.maxPagefilePct ?? '?'}%, `
|
|
61
|
+
+ `graphics card max ${summary.maxGpuTempC ?? '?'} °C, `
|
|
62
|
+
+ `largest disk queue ${disk ? `${disk.disk}: queue ${disk.queue ?? '?'}, ${disk.latencyMs ?? '?'} ms` : '?'}; `
|
|
63
|
+
+ `top memory: ${summary.topAtLow
|
|
64
|
+
.map((p) => `${p.name} ${p.memMb} MB`).join(', ') || '?'}`;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
exports.DyNTS_MachineStateWindow_Util = DyNTS_MachineStateWindow_Util;
|
|
68
|
+
//# sourceMappingURL=machine-state-window.util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"machine-state-window.util.js","sourceRoot":"","sources":["../../../src/_modules/machine-monitor/machine-state-window.util.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { DyNTS_MachineStateRecorderDeps_Interface } from './_models/machine-state-recorder-deps.interface';
|
|
2
|
+
/**
|
|
3
|
+
* BFR-FLEET-033 — the default Windows readers of the machine-state recorder: `typeperf`, `tasklist` and `nvidia-smi`,
|
|
4
|
+
* as asynchronous child processes (the event loop never stands), hidden windows, with a timeout each.
|
|
5
|
+
*
|
|
6
|
+
* @description Transplanted from My Assistant's wiring (the same commands and timeouts). ⛔ Windows only; a Linux host
|
|
7
|
+
* needs its own readers (a later step). Without an NVIDIA card `nvidia-smi` fails — the recorder then logs the read
|
|
8
|
+
* error once and keeps writing rows.
|
|
9
|
+
*/
|
|
10
|
+
export declare class DyNTS_MachineStateWindowsRunners_Util {
|
|
11
|
+
/** The three readers, to spread into the recorder's dependencies. */
|
|
12
|
+
static runners(): Pick<DyNTS_MachineStateRecorderDeps_Interface, 'runTypeperf' | 'runTasklist' | 'runGpuTemps'>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=machine-state-windows-runners.util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"machine-state-windows-runners.util.d.ts","sourceRoot":"","sources":["../../../src/_modules/machine-monitor/machine-state-windows-runners.util.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,wCAAwC,EAAE,MAAM,iDAAiD,CAAC;AAI3G;;;;;;;GAOG;AACH,qBAAa,qCAAqC;IAEhD,qEAAqE;IACrE,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC,wCAAwC,EAAE,aAAa,GAAG,aAAa,GAAG,aAAa,CAAC;CAahH"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DyNTS_MachineStateWindowsRunners_Util = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const util_1 = require("util");
|
|
6
|
+
const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
7
|
+
/**
|
|
8
|
+
* BFR-FLEET-033 — the default Windows readers of the machine-state recorder: `typeperf`, `tasklist` and `nvidia-smi`,
|
|
9
|
+
* as asynchronous child processes (the event loop never stands), hidden windows, with a timeout each.
|
|
10
|
+
*
|
|
11
|
+
* @description Transplanted from My Assistant's wiring (the same commands and timeouts). ⛔ Windows only; a Linux host
|
|
12
|
+
* needs its own readers (a later step). Without an NVIDIA card `nvidia-smi` fails — the recorder then logs the read
|
|
13
|
+
* error once and keeps writing rows.
|
|
14
|
+
*/
|
|
15
|
+
class DyNTS_MachineStateWindowsRunners_Util {
|
|
16
|
+
/** The three readers, to spread into the recorder's dependencies. */
|
|
17
|
+
static runners() {
|
|
18
|
+
return {
|
|
19
|
+
runTypeperf: async (counters) => (await execFileAsync('typeperf', [...counters, '-sc', '1'], { windowsHide: true, timeout: 30_000 })).stdout,
|
|
20
|
+
runTasklist: async () => (await execFileAsync('tasklist', ['/fo', 'csv', '/nh'], { windowsHide: true, timeout: 30_000 })).stdout,
|
|
21
|
+
runGpuTemps: async () => (await execFileAsync('nvidia-smi', ['--query-gpu=name,temperature.gpu', '--format=csv,noheader,nounits'], { windowsHide: true, timeout: 10_000 })).stdout,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.DyNTS_MachineStateWindowsRunners_Util = DyNTS_MachineStateWindowsRunners_Util;
|
|
26
|
+
//# sourceMappingURL=machine-state-windows-runners.util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"machine-state-windows-runners.util.js","sourceRoot":"","sources":["../../../src/_modules/machine-monitor/machine-state-windows-runners.util.ts"],"names":[],"mappings":";;;AAAA,iDAAyC;AACzC,+BAAiC;AAIjC,MAAM,aAAa,GAAG,IAAA,gBAAS,EAAC,wBAAQ,CAAC,CAAC;AAE1C;;;;;;;GAOG;AACH,MAAa,qCAAqC;IAEhD,qEAAqE;IACrE,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,WAAW,EAAE,KAAK,EAAE,QAA2B,EAAmB,EAAE,CAClE,CAAC,MAAM,aAAa,CAAC,UAAU,EAAE,CAAE,GAAG,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAE,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM;YAC/G,WAAW,EAAE,KAAK,IAAqB,EAAE,CACvC,CAAC,MAAM,aAAa,CAAC,UAAU,EAAE,CAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAE,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM;YAC3G,WAAW,EAAE,KAAK,IAAqB,EAAE,CAAC,CAAC,MAAM,aAAa,CAC5D,YAAY,EACZ,CAAE,kCAAkC,EAAE,+BAA+B,CAAE,EACvE,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CACvC,CAAC,CAAC,MAAM;SACV,CAAC;IACJ,CAAC;CACF;AAhBD,sFAgBC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { DyNTS_MachineStateRow_Interface } from './_models/machine-state-row.interface';
|
|
2
|
+
import { DyNTS_MachineStateRecorderDeps_Interface } from './_models/machine-state-recorder-deps.interface';
|
|
3
|
+
/**
|
|
4
|
+
* BFR-FLEET-033 — the per-minute machine-state recorder: one JSONL row per minute into the daily file, with a 7-day
|
|
5
|
+
* retention. ⛔ It never throws.
|
|
6
|
+
*
|
|
7
|
+
* @description Transplanted from My Assistant (`MachineStateRecorder`), the logic unchanged. Run it on the app's own
|
|
8
|
+
* tick (e.g. a watcher loop): `tick()` returns early inside the minute, and the child processes are asynchronous, so
|
|
9
|
+
* the event loop never stands. The error is coded (`<prefix>-MACHINE-STATE-FAILED`), never silent — but the same
|
|
10
|
+
* error is logged only once, not every minute.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const recorder = new DyNTS_MachineState_Recorder({
|
|
15
|
+
* dir: DyNTS_MachineState_Util.resolveDir('my-app'),
|
|
16
|
+
* ...DyNTS_MachineStateWindowsRunners_Util.runners(),
|
|
17
|
+
* log: (code, detail) => DyFM_Log.warn(code, detail),
|
|
18
|
+
* });
|
|
19
|
+
* setInterval(() => void recorder.tick(), 15_000);
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare class DyNTS_MachineState_Recorder {
|
|
23
|
+
static readonly EVERY_MS: number;
|
|
24
|
+
/** 🌡️ At least this much time between two heat alerts. */
|
|
25
|
+
static readonly HEAT_ALERT_EVERY_MS: number;
|
|
26
|
+
private lastRunAt;
|
|
27
|
+
private lastPrunedDay;
|
|
28
|
+
private lastError;
|
|
29
|
+
private isRunning;
|
|
30
|
+
/** 🌡️ The time of the last heat alert (at most one per 30 minutes). */
|
|
31
|
+
private lastHeatAlertAt;
|
|
32
|
+
private lastGpuError;
|
|
33
|
+
private readonly deps;
|
|
34
|
+
constructor(deps: DyNTS_MachineStateRecorderDeps_Interface);
|
|
35
|
+
/** The code with the configured prefix. */
|
|
36
|
+
private code;
|
|
37
|
+
/** One measurement, if a minute passed since the last; the written row, or `null`. */
|
|
38
|
+
tick(now?: Date): Promise<DyNTS_MachineStateRow_Interface | null>;
|
|
39
|
+
/** 🌡️ The graphics-card temperature; error ⇒ `null` (the row goes on; the same error is logged once). */
|
|
40
|
+
private readGpus;
|
|
41
|
+
/** 🌡️ Above the threshold: an alert + an error log, at most once per 30 minutes. */
|
|
42
|
+
private alertIfHot;
|
|
43
|
+
/** The files past the retention are removed, once a day. */
|
|
44
|
+
private pruneOncePerDay;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=machine-state.recorder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"machine-state.recorder.d.ts","sourceRoot":"","sources":["../../../src/_modules/machine-monitor/machine-state.recorder.ts"],"names":[],"mappings":"AAGA,OAAO,EAC2B,+BAA+B,EAChE,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,wCAAwC,EAAE,MAAM,iDAAiD,CAAC;AAG3G;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,2BAA2B;IAEtC,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAU;IAE1C,2DAA2D;IAC3D,MAAM,CAAC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAe;IAE1D,OAAO,CAAC,SAAS,CAAoC;IACrD,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,SAAS,CAAkB;IACnC,wEAAwE;IACxE,OAAO,CAAC,eAAe,CAAoC;IAC3D,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA2C;gBAEpD,IAAI,EAAE,wCAAwC;IAI1D,2CAA2C;IAC3C,OAAO,CAAC,IAAI;IAIZ,sFAAsF;IAChF,IAAI,CAAC,GAAG,GAAE,IAAiB,GAAG,OAAO,CAAC,+BAA+B,GAAG,IAAI,CAAC;IAyCnF,0GAA0G;YAC5F,QAAQ;IAoBtB,qFAAqF;YACvE,UAAU;IAexB,4DAA4D;YAC9C,eAAe;CAU9B"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DyNTS_MachineState_Recorder = void 0;
|
|
4
|
+
const promises_1 = require("fs/promises");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const machine_state_util_1 = require("./machine-state.util");
|
|
7
|
+
/**
|
|
8
|
+
* BFR-FLEET-033 — the per-minute machine-state recorder: one JSONL row per minute into the daily file, with a 7-day
|
|
9
|
+
* retention. ⛔ It never throws.
|
|
10
|
+
*
|
|
11
|
+
* @description Transplanted from My Assistant (`MachineStateRecorder`), the logic unchanged. Run it on the app's own
|
|
12
|
+
* tick (e.g. a watcher loop): `tick()` returns early inside the minute, and the child processes are asynchronous, so
|
|
13
|
+
* the event loop never stands. The error is coded (`<prefix>-MACHINE-STATE-FAILED`), never silent — but the same
|
|
14
|
+
* error is logged only once, not every minute.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const recorder = new DyNTS_MachineState_Recorder({
|
|
19
|
+
* dir: DyNTS_MachineState_Util.resolveDir('my-app'),
|
|
20
|
+
* ...DyNTS_MachineStateWindowsRunners_Util.runners(),
|
|
21
|
+
* log: (code, detail) => DyFM_Log.warn(code, detail),
|
|
22
|
+
* });
|
|
23
|
+
* setInterval(() => void recorder.tick(), 15_000);
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
class DyNTS_MachineState_Recorder {
|
|
27
|
+
static EVERY_MS = 60_000;
|
|
28
|
+
/** 🌡️ At least this much time between two heat alerts. */
|
|
29
|
+
static HEAT_ALERT_EVERY_MS = 30 * 60_000;
|
|
30
|
+
lastRunAt = Number.NEGATIVE_INFINITY;
|
|
31
|
+
lastPrunedDay = null;
|
|
32
|
+
lastError = null;
|
|
33
|
+
isRunning = false;
|
|
34
|
+
/** 🌡️ The time of the last heat alert (at most one per 30 minutes). */
|
|
35
|
+
lastHeatAlertAt = Number.NEGATIVE_INFINITY;
|
|
36
|
+
lastGpuError = null;
|
|
37
|
+
deps;
|
|
38
|
+
constructor(deps) {
|
|
39
|
+
this.deps = deps;
|
|
40
|
+
}
|
|
41
|
+
/** The code with the configured prefix. */
|
|
42
|
+
code(suffix) {
|
|
43
|
+
return `${this.deps.codePrefix ?? 'DyNTS-MM'}-${suffix}`;
|
|
44
|
+
}
|
|
45
|
+
/** One measurement, if a minute passed since the last; the written row, or `null`. */
|
|
46
|
+
async tick(now = new Date()) {
|
|
47
|
+
if (this.isRunning || now.getTime() - this.lastRunAt < DyNTS_MachineState_Recorder.EVERY_MS - 1_000)
|
|
48
|
+
return null;
|
|
49
|
+
this.isRunning = true;
|
|
50
|
+
this.lastRunAt = now.getTime();
|
|
51
|
+
try {
|
|
52
|
+
const [perf, tasks, gpus] = await Promise.all([
|
|
53
|
+
this.deps.runTypeperf(machine_state_util_1.DyNTS_MachineState_Util.COUNTERS), this.deps.runTasklist(), this.readGpus(),
|
|
54
|
+
]);
|
|
55
|
+
const row = {
|
|
56
|
+
ts: now.toISOString(),
|
|
57
|
+
...machine_state_util_1.DyNTS_MachineState_Util.parseTypeperf(perf),
|
|
58
|
+
top: machine_state_util_1.DyNTS_MachineState_Util.topByMemory(tasks),
|
|
59
|
+
...(gpus ? { gpus: gpus } : {}),
|
|
60
|
+
};
|
|
61
|
+
if (row.availableMb === null && !row.disks.length) {
|
|
62
|
+
throw new Error('the typeperf output is not readable (neither memory nor disk)');
|
|
63
|
+
}
|
|
64
|
+
await (0, promises_1.mkdir)(this.deps.dir, { recursive: true });
|
|
65
|
+
await (0, promises_1.appendFile)((0, path_1.join)(this.deps.dir, `${machine_state_util_1.DyNTS_MachineState_Util.dayOf(now)}.jsonl`), `${JSON.stringify(row)}\n`, 'utf-8');
|
|
66
|
+
await this.pruneOncePerDay(now);
|
|
67
|
+
await this.alertIfHot(row, now);
|
|
68
|
+
this.lastError = null;
|
|
69
|
+
return row;
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
73
|
+
if (detail !== this.lastError)
|
|
74
|
+
this.deps.log(this.code('MACHINE-STATE-FAILED'), detail, true);
|
|
75
|
+
this.lastError = detail;
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
this.isRunning = false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/** 🌡️ The graphics-card temperature; error ⇒ `null` (the row goes on; the same error is logged once). */
|
|
83
|
+
async readGpus() {
|
|
84
|
+
if (!this.deps.runGpuTemps)
|
|
85
|
+
return null;
|
|
86
|
+
try {
|
|
87
|
+
const gpus = machine_state_util_1.DyNTS_MachineState_Util.parseGpuTemps(await this.deps.runGpuTemps());
|
|
88
|
+
this.lastGpuError = null;
|
|
89
|
+
return gpus;
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
93
|
+
if (detail !== this.lastGpuError)
|
|
94
|
+
this.deps.log(this.code('MACHINE-TEMP-READ-FAILED'), detail, true);
|
|
95
|
+
this.lastGpuError = detail;
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/** 🌡️ Above the threshold: an alert + an error log, at most once per 30 minutes. */
|
|
100
|
+
async alertIfHot(row, now) {
|
|
101
|
+
const hot = (row.gpus ?? [])
|
|
102
|
+
.filter((gpu) => gpu.tempC !== null && gpu.tempC >= machine_state_util_1.DyNTS_MachineState_Util.GPU_TEMP_HIGH_C);
|
|
103
|
+
if (!hot.length || now.getTime() - this.lastHeatAlertAt < DyNTS_MachineState_Recorder.HEAT_ALERT_EVERY_MS)
|
|
104
|
+
return;
|
|
105
|
+
this.lastHeatAlertAt = now.getTime();
|
|
106
|
+
const text = `🌡️ MACHINE TEMPERATURE: ${hot.map((gpu) => `${gpu.name} ${gpu.tempC} °C`).join(', ')} `
|
|
107
|
+
+ `(threshold ${machine_state_util_1.DyNTS_MachineState_Util.GPU_TEMP_HIGH_C} °C)`;
|
|
108
|
+
this.deps.log(this.code('MACHINE-TEMP-HIGH'), text, true);
|
|
109
|
+
await this.deps.alert?.(text).catch((err) => this.deps.log(this.code('MACHINE-TEMP-ALERT-FAILED'), err instanceof Error ? err.message : String(err), true));
|
|
110
|
+
}
|
|
111
|
+
/** The files past the retention are removed, once a day. */
|
|
112
|
+
async pruneOncePerDay(now) {
|
|
113
|
+
const day = machine_state_util_1.DyNTS_MachineState_Util.dayOf(now);
|
|
114
|
+
if (this.lastPrunedDay === day)
|
|
115
|
+
return;
|
|
116
|
+
this.lastPrunedDay = day;
|
|
117
|
+
for (const name of machine_state_util_1.DyNTS_MachineState_Util.expired(await (0, promises_1.readdir)(this.deps.dir), now)) {
|
|
118
|
+
await (0, promises_1.rm)((0, path_1.join)(this.deps.dir, name), { force: true });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
exports.DyNTS_MachineState_Recorder = DyNTS_MachineState_Recorder;
|
|
123
|
+
//# sourceMappingURL=machine-state.recorder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"machine-state.recorder.js","sourceRoot":"","sources":["../../../src/_modules/machine-monitor/machine-state.recorder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { DyNTS_MachineGpuTemp_Interface, DyNTS_MachineProcessMemory_Interface, DyNTS_MachineStateRow_Interface } from './_models/machine-state-row.interface';
|
|
2
|
+
/**
|
|
3
|
+
* BFR-FLEET-033 — the pure helpers of the per-minute machine-state log (Windows): memory, commit, page file, per-disk
|
|
4
|
+
* queue, the top processes by memory and the graphics-card temperature.
|
|
5
|
+
*
|
|
6
|
+
* @description Transplanted from My Assistant (`cli/src/diagnostics/machine-state.ts`), the logic unchanged. Measured
|
|
7
|
+
* there: `typeperf -sc 1` with the English counter names takes ~1.5 s wall time at negligible CPU, `tasklist /fo csv
|
|
8
|
+
* /nh` ~0.8 s (⛔ WMI — it is avoided under load).
|
|
9
|
+
*/
|
|
10
|
+
export declare class DyNTS_MachineState_Util {
|
|
11
|
+
/** The `typeperf` counters (English names). */
|
|
12
|
+
static readonly COUNTERS: readonly string[];
|
|
13
|
+
/** The retention (days). */
|
|
14
|
+
static readonly KEEP_DAYS: number;
|
|
15
|
+
/** The time zone of the daily file names. */
|
|
16
|
+
static readonly TIME_ZONE: string;
|
|
17
|
+
/**
|
|
18
|
+
* 🌡️ An alert above this temperature (°C).
|
|
19
|
+
*
|
|
20
|
+
* @description ⚠️ Without elevated rights the CPU and disk temperatures are NOT readable (ACPI: not supported,
|
|
21
|
+
* performance counter: error, disk: access denied) ⇒ those need an administrator sensor — a separate step.
|
|
22
|
+
*/
|
|
23
|
+
static readonly GPU_TEMP_HIGH_C: number;
|
|
24
|
+
/** The output of `nvidia-smi --query-gpu=name,temperature.gpu --format=csv,noheader,nounits`. **Pure function.** */
|
|
25
|
+
static parseGpuTemps(output: string): DyNTS_MachineGpuTemp_Interface[];
|
|
26
|
+
/**
|
|
27
|
+
* The folder of the daily files under the user's config folder.
|
|
28
|
+
*
|
|
29
|
+
* @param appFolder the app's own folder under `~/.config` (e.g. `my-app`)
|
|
30
|
+
* @param userHome the home folder (default: the current user's)
|
|
31
|
+
*/
|
|
32
|
+
static resolveDir(appFolder: string, userHome?: string): string;
|
|
33
|
+
/** The fields of one CSV line (the quoted form of `typeperf` / `tasklist`). **Pure function.** */
|
|
34
|
+
static csvFields(line: string): string[];
|
|
35
|
+
/** The output of `typeperf -sc 1` ⇒ the memory and disk part of the row. **Pure function.** */
|
|
36
|
+
static parseTypeperf(output: string): Omit<DyNTS_MachineStateRow_Interface, 'ts' | 'top'>;
|
|
37
|
+
/** The output of `tasklist /fo csv /nh` ⇒ the `count` processes using the most memory. **Pure function.** */
|
|
38
|
+
static topByMemory(output: string, count?: number): DyNTS_MachineProcessMemory_Interface[];
|
|
39
|
+
/** The name of the daily file (the day in `TIME_ZONE`). **Pure function.** */
|
|
40
|
+
static dayOf(now: Date): string;
|
|
41
|
+
/** The daily files past the retention. **Pure function.** */
|
|
42
|
+
static expired(names: readonly string[], now: Date, keepDays?: number): string[];
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=machine-state.util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"machine-state.util.d.ts","sourceRoot":"","sources":["../../../src/_modules/machine-monitor/machine-state.util.ts"],"names":[],"mappings":"AAGA,OAAO,EAC6B,8BAA8B,EAAE,oCAAoC,EACtG,+BAA+B,EAChC,MAAM,uCAAuC,CAAC;AAE/C;;;;;;;GAOG;AACH,qBAAa,uBAAuB;IAElC,+CAA+C;IAC/C,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAOzC;IAEF,4BAA4B;IAC5B,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAK;IAEtC,6CAA6C;IAC7C,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAqB;IAEtD;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAM;IAE7C,oHAAoH;IACpH,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,8BAA8B,EAAE;IAatE;;;;;OAKG;IACH,MAAM,CAAC,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAkB,GAAG,MAAM;IAI1E,kGAAkG;IAClG,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE;IAKxC,+FAA+F;IAC/F,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,+BAA+B,EAAE,IAAI,GAAG,KAAK,CAAC;IA0CzF,6GAA6G;IAC7G,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,oCAAoC,EAAE;IAiB7F,8EAA8E;IAC9E,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,GAAG,MAAM;IAI/B,6DAA6D;IAC7D,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,GAAE,MAA0C,GAAG,MAAM,EAAE;CAMpH"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DyNTS_MachineState_Util = void 0;
|
|
4
|
+
const os_1 = require("os");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
/**
|
|
7
|
+
* BFR-FLEET-033 — the pure helpers of the per-minute machine-state log (Windows): memory, commit, page file, per-disk
|
|
8
|
+
* queue, the top processes by memory and the graphics-card temperature.
|
|
9
|
+
*
|
|
10
|
+
* @description Transplanted from My Assistant (`cli/src/diagnostics/machine-state.ts`), the logic unchanged. Measured
|
|
11
|
+
* there: `typeperf -sc 1` with the English counter names takes ~1.5 s wall time at negligible CPU, `tasklist /fo csv
|
|
12
|
+
* /nh` ~0.8 s (⛔ WMI — it is avoided under load).
|
|
13
|
+
*/
|
|
14
|
+
class DyNTS_MachineState_Util {
|
|
15
|
+
/** The `typeperf` counters (English names). */
|
|
16
|
+
static COUNTERS = [
|
|
17
|
+
'\\Memory\\Available MBytes',
|
|
18
|
+
'\\Memory\\Committed Bytes',
|
|
19
|
+
'\\Memory\\Commit Limit',
|
|
20
|
+
'\\Paging File(_Total)\\% Usage',
|
|
21
|
+
'\\PhysicalDisk(*)\\Avg. Disk Queue Length',
|
|
22
|
+
'\\PhysicalDisk(*)\\Avg. Disk sec/Transfer',
|
|
23
|
+
];
|
|
24
|
+
/** The retention (days). */
|
|
25
|
+
static KEEP_DAYS = 7;
|
|
26
|
+
/** The time zone of the daily file names. */
|
|
27
|
+
static TIME_ZONE = 'Europe/Budapest';
|
|
28
|
+
/**
|
|
29
|
+
* 🌡️ An alert above this temperature (°C).
|
|
30
|
+
*
|
|
31
|
+
* @description ⚠️ Without elevated rights the CPU and disk temperatures are NOT readable (ACPI: not supported,
|
|
32
|
+
* performance counter: error, disk: access denied) ⇒ those need an administrator sensor — a separate step.
|
|
33
|
+
*/
|
|
34
|
+
static GPU_TEMP_HIGH_C = 85;
|
|
35
|
+
/** The output of `nvidia-smi --query-gpu=name,temperature.gpu --format=csv,noheader,nounits`. **Pure function.** */
|
|
36
|
+
static parseGpuTemps(output) {
|
|
37
|
+
return output.split(/\r?\n/u).flatMap((line) => {
|
|
38
|
+
const at = line.lastIndexOf(',');
|
|
39
|
+
if (at < 0)
|
|
40
|
+
return [];
|
|
41
|
+
const name = line.slice(0, at).trim();
|
|
42
|
+
const value = Number(line.slice(at + 1).trim());
|
|
43
|
+
return name ? [{ name: name, tempC: Number.isFinite(value) ? value : null }] : [];
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The folder of the daily files under the user's config folder.
|
|
48
|
+
*
|
|
49
|
+
* @param appFolder the app's own folder under `~/.config` (e.g. `my-app`)
|
|
50
|
+
* @param userHome the home folder (default: the current user's)
|
|
51
|
+
*/
|
|
52
|
+
static resolveDir(appFolder, userHome = (0, os_1.homedir)()) {
|
|
53
|
+
return (0, path_1.join)(userHome, '.config', appFolder, 'machine-state');
|
|
54
|
+
}
|
|
55
|
+
/** The fields of one CSV line (the quoted form of `typeperf` / `tasklist`). **Pure function.** */
|
|
56
|
+
static csvFields(line) {
|
|
57
|
+
return [...line.matchAll(/"((?:[^"]|"")*)"/gu)]
|
|
58
|
+
.map((match) => (match[1] ?? '').replace(/""/gu, '"'));
|
|
59
|
+
}
|
|
60
|
+
/** The output of `typeperf -sc 1` ⇒ the memory and disk part of the row. **Pure function.** */
|
|
61
|
+
static parseTypeperf(output) {
|
|
62
|
+
const lines = output.split(/\r?\n/u).filter((line) => line.startsWith('"'));
|
|
63
|
+
const header = DyNTS_MachineState_Util.csvFields(lines[0] ?? '');
|
|
64
|
+
const values = DyNTS_MachineState_Util.csvFields(lines[1] ?? '');
|
|
65
|
+
const num = (index) => {
|
|
66
|
+
const value = Number.parseFloat(values[index] ?? '');
|
|
67
|
+
return Number.isFinite(value) ? value : null;
|
|
68
|
+
};
|
|
69
|
+
const find = (suffix) => header.findIndex((name) => name.endsWith(suffix));
|
|
70
|
+
const commit = num(find('\\Memory\\Committed Bytes'));
|
|
71
|
+
const limit = num(find('\\Memory\\Commit Limit'));
|
|
72
|
+
const disks = new Map();
|
|
73
|
+
header.forEach((name, index) => {
|
|
74
|
+
const match = /\\PhysicalDisk\(([^)]+)\)\\(Avg\. Disk Queue Length|Avg\. Disk sec\/Transfer)$/u.exec(name);
|
|
75
|
+
if (!match || match[1] === '_Total')
|
|
76
|
+
return;
|
|
77
|
+
const disk = disks.get(match[1] ?? '') ?? { disk: match[1] ?? '', queue: null, latencyMs: null };
|
|
78
|
+
const value = num(index);
|
|
79
|
+
if (match[2] === 'Avg. Disk Queue Length')
|
|
80
|
+
disk.queue = value === null ? null : Math.round(value * 1000) / 1000;
|
|
81
|
+
else
|
|
82
|
+
disk.latencyMs = value === null ? null : Math.round(value * 1000 * 10) / 10;
|
|
83
|
+
disks.set(disk.disk, disk);
|
|
84
|
+
});
|
|
85
|
+
const gb = (bytes) => bytes === null ? null : Math.round(bytes / 1024 ** 3 * 10) / 10;
|
|
86
|
+
const pagefile = num(find('\\Paging File(_Total)\\% Usage'));
|
|
87
|
+
return {
|
|
88
|
+
availableMb: num(find('\\Memory\\Available MBytes')),
|
|
89
|
+
commitGb: gb(commit),
|
|
90
|
+
commitLimitGb: gb(limit),
|
|
91
|
+
commitPct: commit !== null && limit ? Math.round(commit / limit * 1000) / 10 : null,
|
|
92
|
+
pagefilePct: pagefile === null ? null : Math.round(pagefile * 10) / 10,
|
|
93
|
+
disks: [...disks.values()],
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/** The output of `tasklist /fo csv /nh` ⇒ the `count` processes using the most memory. **Pure function.** */
|
|
97
|
+
static topByMemory(output, count = 5) {
|
|
98
|
+
const out = [];
|
|
99
|
+
for (const line of output.split(/\r?\n/u)) {
|
|
100
|
+
const [name, pid, , , mem] = DyNTS_MachineState_Util.csvFields(line);
|
|
101
|
+
const kb = Number.parseInt((mem ?? '').replace(/[^\d]/gu, ''), 10);
|
|
102
|
+
if (!name || !Number.isFinite(kb))
|
|
103
|
+
continue;
|
|
104
|
+
out.push({ name: name, pid: Number.parseInt(pid ?? '', 10) || 0, memMb: Math.round(kb / 1024) });
|
|
105
|
+
}
|
|
106
|
+
return out
|
|
107
|
+
.sort((a, b) => b.memMb - a.memMb)
|
|
108
|
+
.slice(0, count);
|
|
109
|
+
}
|
|
110
|
+
/** The name of the daily file (the day in `TIME_ZONE`). **Pure function.** */
|
|
111
|
+
static dayOf(now) {
|
|
112
|
+
return new Intl.DateTimeFormat('sv-SE', { timeZone: DyNTS_MachineState_Util.TIME_ZONE }).format(now);
|
|
113
|
+
}
|
|
114
|
+
/** The daily files past the retention. **Pure function.** */
|
|
115
|
+
static expired(names, now, keepDays = DyNTS_MachineState_Util.KEEP_DAYS) {
|
|
116
|
+
const cutoff = DyNTS_MachineState_Util.dayOf(new Date(now.getTime() - keepDays * 86_400_000));
|
|
117
|
+
return names.filter((name) => /^\d{4}-\d{2}-\d{2}\.jsonl$/u.test(name) && name.slice(0, 10) < cutoff);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
exports.DyNTS_MachineState_Util = DyNTS_MachineState_Util;
|
|
121
|
+
//# sourceMappingURL=machine-state.util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"machine-state.util.js","sourceRoot":"","sources":["../../../src/_modules/machine-monitor/machine-state.util.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@futdevpro/nts-dynamo",
|
|
3
|
-
"version": "01.15.
|
|
3
|
+
"version": "01.15.438",
|
|
4
4
|
"description": "Dynamic NodeTS (NodeJS-Typescript), MongoDB Backend System Framework by Future Development Program Ltd.",
|
|
5
5
|
"DyBu_settings": {
|
|
6
6
|
"packageType": "server-package",
|
|
@@ -297,6 +297,12 @@
|
|
|
297
297
|
"types": "./build/_modules/logs/index.d.ts",
|
|
298
298
|
"typings": "./build/_modules/logs/index.d.ts"
|
|
299
299
|
},
|
|
300
|
+
"./machine-monitor": {
|
|
301
|
+
"default": "./build/_modules/machine-monitor/index.js",
|
|
302
|
+
"module": "./build/_modules/machine-monitor/index.js",
|
|
303
|
+
"types": "./build/_modules/machine-monitor/index.d.ts",
|
|
304
|
+
"typings": "./build/_modules/machine-monitor/index.d.ts"
|
|
305
|
+
},
|
|
300
306
|
"./usage": {
|
|
301
307
|
"default": "./build/_modules/usage/index.js",
|
|
302
308
|
"module": "./build/_modules/usage/index.js",
|
|
@@ -450,6 +456,9 @@
|
|
|
450
456
|
"logs": [
|
|
451
457
|
"build/_modules/logs/index.d.ts"
|
|
452
458
|
],
|
|
459
|
+
"machine-monitor": [
|
|
460
|
+
"build/_modules/machine-monitor/index.d.ts"
|
|
461
|
+
],
|
|
453
462
|
"usage": [
|
|
454
463
|
"build/_modules/usage/index.d.ts"
|
|
455
464
|
],
|
|
@@ -544,7 +553,7 @@
|
|
|
544
553
|
}
|
|
545
554
|
},
|
|
546
555
|
"devDependencies": {
|
|
547
|
-
"@futdevpro/fsm-dynamo": "1.20.
|
|
556
|
+
"@futdevpro/fsm-dynamo": "1.20.136",
|
|
548
557
|
"@futdevpro/dynamo-eslint": "1.20.74",
|
|
549
558
|
"@discordjs/opus": "^0.10.0",
|
|
550
559
|
"@discordjs/voice": "^0.18.0",
|