@glassmkr/crucible 0.1.0
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/LICENSE +21 -0
- package/README.md +92 -0
- package/config/collector.example.yaml +43 -0
- package/dist/alerts/evaluator.d.ts +3 -0
- package/dist/alerts/evaluator.js +14 -0
- package/dist/alerts/evaluator.js.map +1 -0
- package/dist/alerts/rules.d.ts +7 -0
- package/dist/alerts/rules.js +203 -0
- package/dist/alerts/rules.js.map +1 -0
- package/dist/alerts/state.d.ts +6 -0
- package/dist/alerts/state.js +77 -0
- package/dist/alerts/state.js.map +1 -0
- package/dist/collect/cpu.d.ts +2 -0
- package/dist/collect/cpu.js +35 -0
- package/dist/collect/cpu.js.map +1 -0
- package/dist/collect/disks.d.ts +2 -0
- package/dist/collect/disks.js +33 -0
- package/dist/collect/disks.js.map +1 -0
- package/dist/collect/ipmi.d.ts +2 -0
- package/dist/collect/ipmi.js +55 -0
- package/dist/collect/ipmi.js.map +1 -0
- package/dist/collect/memory.d.ts +2 -0
- package/dist/collect/memory.js +27 -0
- package/dist/collect/memory.js.map +1 -0
- package/dist/collect/network.d.ts +2 -0
- package/dist/collect/network.js +54 -0
- package/dist/collect/network.js.map +1 -0
- package/dist/collect/os-alerts.d.ts +2 -0
- package/dist/collect/os-alerts.js +41 -0
- package/dist/collect/os-alerts.js.map +1 -0
- package/dist/collect/raid.d.ts +2 -0
- package/dist/collect/raid.js +34 -0
- package/dist/collect/raid.js.map +1 -0
- package/dist/collect/smart.d.ts +2 -0
- package/dist/collect/smart.js +56 -0
- package/dist/collect/smart.js.map +1 -0
- package/dist/collect/system.d.ts +2 -0
- package/dist/collect/system.js +19 -0
- package/dist/collect/system.js.map +1 -0
- package/dist/config.d.ts +208 -0
- package/dist/config.js +58 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +96 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/exec.d.ts +1 -0
- package/dist/lib/exec.js +19 -0
- package/dist/lib/exec.js.map +1 -0
- package/dist/lib/parse.d.ts +4 -0
- package/dist/lib/parse.js +29 -0
- package/dist/lib/parse.js.map +1 -0
- package/dist/lib/types.d.ts +103 -0
- package/dist/lib/types.js +2 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/notify/email.d.ts +4 -0
- package/dist/notify/email.js +55 -0
- package/dist/notify/email.js.map +1 -0
- package/dist/notify/slack.d.ts +2 -0
- package/dist/notify/slack.js +38 -0
- package/dist/notify/slack.js.map +1 -0
- package/dist/notify/telegram.d.ts +2 -0
- package/dist/notify/telegram.js +38 -0
- package/dist/notify/telegram.js.map +1 -0
- package/dist/push/forge.d.ts +2 -0
- package/dist/push/forge.js +26 -0
- package/dist/push/forge.js.map +1 -0
- package/package.json +29 -0
- package/src/alerts/evaluator.ts +15 -0
- package/src/alerts/rules.ts +184 -0
- package/src/alerts/state.ts +92 -0
- package/src/collect/cpu.ts +44 -0
- package/src/collect/disks.ts +36 -0
- package/src/collect/ipmi.ts +60 -0
- package/src/collect/memory.ts +30 -0
- package/src/collect/network.ts +61 -0
- package/src/collect/os-alerts.ts +43 -0
- package/src/collect/raid.ts +40 -0
- package/src/collect/smart.ts +60 -0
- package/src/collect/system.ts +21 -0
- package/src/config.ts +60 -0
- package/src/index.ts +112 -0
- package/src/lib/exec.ts +16 -0
- package/src/lib/parse.ts +29 -0
- package/src/lib/types.ts +110 -0
- package/src/notify/email.ts +68 -0
- package/src/notify/slack.ts +46 -0
- package/src/notify/telegram.ts +45 -0
- package/src/push/forge.ts +25 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { run } from "../lib/exec.js";
|
|
2
|
+
export async function collectIpmi() {
|
|
3
|
+
const sensorRaw = await run("ipmitool", ["sensor"]);
|
|
4
|
+
if (!sensorRaw) {
|
|
5
|
+
return { available: false, sensors: [], ecc_errors: { correctable: 0, uncorrectable: 0 }, sel_entries_count: 0 };
|
|
6
|
+
}
|
|
7
|
+
// Parse sensor readings
|
|
8
|
+
const sensors = [];
|
|
9
|
+
for (const line of sensorRaw.split("\n")) {
|
|
10
|
+
const parts = line.split("|").map((s) => s.trim());
|
|
11
|
+
if (parts.length < 4)
|
|
12
|
+
continue;
|
|
13
|
+
const name = parts[0];
|
|
14
|
+
const rawValue = parts[1];
|
|
15
|
+
const unit = parts[2];
|
|
16
|
+
const status = parts[3];
|
|
17
|
+
const numValue = parseFloat(rawValue);
|
|
18
|
+
const value = isNaN(numValue) ? rawValue : numValue;
|
|
19
|
+
// Parse upper critical threshold
|
|
20
|
+
let upperCritical;
|
|
21
|
+
if (parts[8]) {
|
|
22
|
+
const uc = parseFloat(parts[8]);
|
|
23
|
+
if (!isNaN(uc))
|
|
24
|
+
upperCritical = uc;
|
|
25
|
+
}
|
|
26
|
+
sensors.push({ name, value, unit, status, upper_critical: upperCritical });
|
|
27
|
+
}
|
|
28
|
+
// ECC errors from memory-type sensors
|
|
29
|
+
let correctable = 0;
|
|
30
|
+
let uncorrectable = 0;
|
|
31
|
+
for (const sensor of sensors) {
|
|
32
|
+
const name = sensor.name.toLowerCase();
|
|
33
|
+
if (name.includes("correctable") && typeof sensor.value === "number") {
|
|
34
|
+
correctable += sensor.value;
|
|
35
|
+
}
|
|
36
|
+
if (name.includes("uncorrectable") && typeof sensor.value === "number") {
|
|
37
|
+
uncorrectable += sensor.value;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// SEL entry count
|
|
41
|
+
let selCount = 0;
|
|
42
|
+
const selInfo = await run("ipmitool", ["sel", "info"]);
|
|
43
|
+
if (selInfo) {
|
|
44
|
+
const match = selInfo.match(/Entries\s*:\s*(\d+)/i);
|
|
45
|
+
if (match)
|
|
46
|
+
selCount = parseInt(match[1], 10);
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
available: true,
|
|
50
|
+
sensors,
|
|
51
|
+
ecc_errors: { correctable, uncorrectable },
|
|
52
|
+
sel_entries_count: selCount,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=ipmi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ipmi.js","sourceRoot":"","sources":["../../src/collect/ipmi.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { readProcFile, parseKb } from "../lib/parse.js";
|
|
2
|
+
export async function collectMemory() {
|
|
3
|
+
const raw = readProcFile("/proc/meminfo") || "";
|
|
4
|
+
const kv = {};
|
|
5
|
+
for (const line of raw.split("\n")) {
|
|
6
|
+
const match = line.match(/^(\w+):\s+(.+)/);
|
|
7
|
+
if (match)
|
|
8
|
+
kv[match[1]] = match[2];
|
|
9
|
+
}
|
|
10
|
+
const totalKb = parseKb(kv["MemTotal"]);
|
|
11
|
+
const availableKb = parseKb(kv["MemAvailable"]);
|
|
12
|
+
const swapTotalKb = parseKb(kv["SwapTotal"]);
|
|
13
|
+
const swapFreeKb = parseKb(kv["SwapFree"]);
|
|
14
|
+
const totalMb = Math.round(totalKb / 1024);
|
|
15
|
+
const availableMb = Math.round(availableKb / 1024);
|
|
16
|
+
const usedMb = totalMb - availableMb;
|
|
17
|
+
const swapTotalMb = Math.round(swapTotalKb / 1024);
|
|
18
|
+
const swapUsedMb = Math.round((swapTotalKb - swapFreeKb) / 1024);
|
|
19
|
+
return {
|
|
20
|
+
total_mb: totalMb,
|
|
21
|
+
used_mb: usedMb,
|
|
22
|
+
available_mb: availableMb,
|
|
23
|
+
swap_total_mb: swapTotalMb,
|
|
24
|
+
swap_used_mb: swapUsedMb,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/collect/memory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAGxD,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,GAAG,GAAG,YAAY,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;IAChD,MAAM,EAAE,GAA2B,EAAE,CAAC;IACtC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAC3C,IAAI,KAAK;YAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IACxC,MAAM,WAAW,GAAG,OAAO,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC;IAChD,MAAM,WAAW,GAAG,OAAO,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAC7C,MAAM,UAAU,GAAG,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAE3C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAC3C,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,OAAO,GAAG,WAAW,CAAC;IACrC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACnD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,GAAG,UAAU,CAAC,GAAG,IAAI,CAAC,CAAC;IAEjE,OAAO;QACL,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,MAAM;QACf,YAAY,EAAE,WAAW;QACzB,aAAa,EAAE,WAAW;QAC1B,YAAY,EAAE,UAAU;KACzB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { readProcFile, sleep } from "../lib/parse.js";
|
|
2
|
+
import { readFileSync } from "fs";
|
|
3
|
+
function parseNetDev() {
|
|
4
|
+
const raw = readProcFile("/proc/net/dev") || "";
|
|
5
|
+
const result = {};
|
|
6
|
+
for (const line of raw.split("\n").slice(2)) {
|
|
7
|
+
const match = line.match(/^\s*(\S+):\s+(.*)/);
|
|
8
|
+
if (!match)
|
|
9
|
+
continue;
|
|
10
|
+
const name = match[1];
|
|
11
|
+
// Skip virtual interfaces
|
|
12
|
+
if (name === "lo" || name.startsWith("veth") || name.startsWith("docker") || name.startsWith("br-") || name.startsWith("virbr"))
|
|
13
|
+
continue;
|
|
14
|
+
const parts = match[2].trim().split(/\s+/).map(Number);
|
|
15
|
+
result[name] = {
|
|
16
|
+
rx_bytes: parts[0] || 0, rx_packets: parts[1] || 0, rx_errors: parts[2] || 0, rx_drops: parts[3] || 0,
|
|
17
|
+
tx_bytes: parts[8] || 0, tx_packets: parts[9] || 0, tx_errors: parts[10] || 0, tx_drops: parts[11] || 0,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
function getSpeed(iface) {
|
|
23
|
+
try {
|
|
24
|
+
const speed = readFileSync(`/sys/class/net/${iface}/speed`, "utf-8").trim();
|
|
25
|
+
const val = parseInt(speed, 10);
|
|
26
|
+
return isNaN(val) || val <= 0 ? 0 : val;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return 0;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export async function collectNetwork() {
|
|
33
|
+
const stats1 = parseNetDev();
|
|
34
|
+
await sleep(1000);
|
|
35
|
+
const stats2 = parseNetDev();
|
|
36
|
+
const results = [];
|
|
37
|
+
for (const [name, s2] of Object.entries(stats2)) {
|
|
38
|
+
const s1 = stats1[name];
|
|
39
|
+
if (!s1)
|
|
40
|
+
continue;
|
|
41
|
+
results.push({
|
|
42
|
+
interface: name,
|
|
43
|
+
speed_mbps: getSpeed(name),
|
|
44
|
+
rx_bytes_sec: s2.rx_bytes - s1.rx_bytes,
|
|
45
|
+
tx_bytes_sec: s2.tx_bytes - s1.tx_bytes,
|
|
46
|
+
rx_errors: s2.rx_errors,
|
|
47
|
+
tx_errors: s2.tx_errors,
|
|
48
|
+
rx_drops: s2.rx_drops,
|
|
49
|
+
tx_drops: s2.tx_drops,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return results;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=network.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.js","sourceRoot":"","sources":["../../src/collect/network.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { run } from "../lib/exec.js";
|
|
2
|
+
import { readdirSync, readFileSync } from "fs";
|
|
3
|
+
export async function collectOsAlerts() {
|
|
4
|
+
// OOM kills
|
|
5
|
+
let oomKills = 0;
|
|
6
|
+
const dmesg = await run("dmesg", ["--level=err,crit", "--since", "5 min ago"]);
|
|
7
|
+
if (dmesg) {
|
|
8
|
+
oomKills = (dmesg.match(/Out of memory/gi) || []).length;
|
|
9
|
+
}
|
|
10
|
+
// Zombie processes
|
|
11
|
+
let zombies = 0;
|
|
12
|
+
try {
|
|
13
|
+
const pids = readdirSync("/proc").filter((f) => /^\d+$/.test(f));
|
|
14
|
+
for (const pid of pids) {
|
|
15
|
+
try {
|
|
16
|
+
const stat = readFileSync(`/proc/${pid}/stat`, "utf-8");
|
|
17
|
+
// Field 3 is the state character
|
|
18
|
+
const state = stat.split(" ")[2];
|
|
19
|
+
if (state === "Z")
|
|
20
|
+
zombies++;
|
|
21
|
+
}
|
|
22
|
+
catch { /* process disappeared */ }
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch { /* /proc not readable */ }
|
|
26
|
+
// Time drift (simple: check if chrony/ntp reports drift)
|
|
27
|
+
let timeDriftMs = 0;
|
|
28
|
+
const chrony = await run("chronyc", ["tracking"]);
|
|
29
|
+
if (chrony) {
|
|
30
|
+
const match = chrony.match(/System time\s*:\s*([\d.]+)\s*seconds\s*(slow|fast)/);
|
|
31
|
+
if (match) {
|
|
32
|
+
timeDriftMs = parseFloat(match[1]) * 1000;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
oom_kills_recent: oomKills,
|
|
37
|
+
zombie_processes: zombies,
|
|
38
|
+
time_drift_ms: Math.round(timeDriftMs * 100) / 100,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=os-alerts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"os-alerts.js","sourceRoot":"","sources":["../../src/collect/os-alerts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAG/C,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,YAAY;IACZ,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC,kBAAkB,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;IAC/E,IAAI,KAAK,EAAE,CAAC;QACV,QAAQ,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;IAC3D,CAAC;IAED,mBAAmB;IACnB,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACjE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,YAAY,CAAC,SAAS,GAAG,OAAO,EAAE,OAAO,CAAC,CAAC;gBACxD,iCAAiC;gBACjC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBACjC,IAAI,KAAK,KAAK,GAAG;oBAAE,OAAO,EAAE,CAAC;YAC/B,CAAC;YAAC,MAAM,CAAC,CAAC,yBAAyB,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,wBAAwB,CAAC,CAAC;IAEpC,yDAAyD;IACzD,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAClD,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACjF,IAAI,KAAK,EAAE,CAAC;YACV,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,OAAO;QACL,gBAAgB,EAAE,QAAQ;QAC1B,gBAAgB,EAAE,OAAO;QACzB,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC,GAAG,GAAG;KACnD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { readProcFile } from "../lib/parse.js";
|
|
2
|
+
export async function collectRaid() {
|
|
3
|
+
const raw = readProcFile("/proc/mdstat");
|
|
4
|
+
if (!raw)
|
|
5
|
+
return [];
|
|
6
|
+
const results = [];
|
|
7
|
+
const lines = raw.split("\n");
|
|
8
|
+
for (let i = 0; i < lines.length; i++) {
|
|
9
|
+
const match = lines[i].match(/^(md\d+)\s*:\s*(\w+)\s+(\w+)\s+(.*)/);
|
|
10
|
+
if (!match)
|
|
11
|
+
continue;
|
|
12
|
+
const device = match[1];
|
|
13
|
+
const status = match[2]; // "active" or "inactive"
|
|
14
|
+
const level = match[3]; // "raid1", "raid5", etc.
|
|
15
|
+
const disksPart = match[4];
|
|
16
|
+
// Parse component disks (e.g., "sda1[0] sdb1[1]")
|
|
17
|
+
const disks = (disksPart.match(/\w+\[\d+\]/g) || []).map((d) => d.replace(/\[\d+\]/, ""));
|
|
18
|
+
// Check next line for degraded status (e.g., "[UU_]" means one drive missing)
|
|
19
|
+
const statusLine = lines[i + 1] || "";
|
|
20
|
+
const bracketMatch = statusLine.match(/\[([U_]+)\]/);
|
|
21
|
+
const degraded = bracketMatch ? bracketMatch[1].includes("_") : false;
|
|
22
|
+
const failedDisks = [];
|
|
23
|
+
if (degraded && bracketMatch) {
|
|
24
|
+
const pattern = bracketMatch[1];
|
|
25
|
+
pattern.split("").forEach((c, idx) => {
|
|
26
|
+
if (c === "_" && disks[idx])
|
|
27
|
+
failedDisks.push(disks[idx]);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
results.push({ device, level, status, degraded, disks, failed_disks: failedDisks });
|
|
31
|
+
}
|
|
32
|
+
return results;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=raid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raid.js","sourceRoot":"","sources":["../../src/collect/raid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG/C,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,GAAG,GAAG,YAAY,CAAC,cAAc,CAAC,CAAC;IACzC,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IAEpB,MAAM,OAAO,GAAe,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACpE,IAAI,CAAC,KAAK;YAAE,SAAS;QAErB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACxB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,yBAAyB;QAClD,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,yBAAyB;QACjD,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAE3B,kDAAkD;QAClD,MAAM,KAAK,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC;QAE1F,8EAA8E;QAC9E,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QACtC,MAAM,YAAY,GAAG,UAAU,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QACrD,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAEtE,MAAM,WAAW,GAAa,EAAE,CAAC;QACjC,IAAI,QAAQ,IAAI,YAAY,EAAE,CAAC;YAC7B,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YAChC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE;gBACnC,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC;oBAAE,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5D,CAAC,CAAC,CAAC;QACL,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC,CAAC;IACtF,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { run } from "../lib/exec.js";
|
|
2
|
+
import { readdirSync } from "fs";
|
|
3
|
+
export async function collectSmart() {
|
|
4
|
+
// Find block devices
|
|
5
|
+
const devices = [];
|
|
6
|
+
try {
|
|
7
|
+
const entries = readdirSync("/sys/block");
|
|
8
|
+
for (const entry of entries) {
|
|
9
|
+
if (entry.startsWith("sd") || entry.startsWith("nvme") || entry.startsWith("hd")) {
|
|
10
|
+
devices.push(`/dev/${entry}`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
const results = [];
|
|
18
|
+
for (const device of devices) {
|
|
19
|
+
const output = await run("smartctl", ["--json", "--all", device]);
|
|
20
|
+
if (!output)
|
|
21
|
+
continue;
|
|
22
|
+
try {
|
|
23
|
+
const data = JSON.parse(output);
|
|
24
|
+
const info = {
|
|
25
|
+
device,
|
|
26
|
+
model: data.model_name || data.model_family || "unknown",
|
|
27
|
+
health: data.smart_status?.passed ? "PASSED" : "FAILED",
|
|
28
|
+
temperature_c: data.temperature?.current,
|
|
29
|
+
power_on_hours: data.power_on_time?.hours,
|
|
30
|
+
};
|
|
31
|
+
// NVMe specific
|
|
32
|
+
if (data.nvme_smart_health_information_log) {
|
|
33
|
+
const nvme = data.nvme_smart_health_information_log;
|
|
34
|
+
info.percentage_used = nvme.percentage_used;
|
|
35
|
+
info.temperature_c = nvme.temperature;
|
|
36
|
+
}
|
|
37
|
+
// SATA specific
|
|
38
|
+
if (data.ata_smart_attributes?.table) {
|
|
39
|
+
for (const attr of data.ata_smart_attributes.table) {
|
|
40
|
+
if (attr.id === 5 || attr.name === "Reallocated_Sector_Ct") {
|
|
41
|
+
info.reallocated_sectors = attr.raw?.value || 0;
|
|
42
|
+
}
|
|
43
|
+
if (attr.id === 197 || attr.name === "Current_Pending_Sector") {
|
|
44
|
+
info.pending_sectors = attr.raw?.value || 0;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
results.push(info);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// Failed to parse, skip this device
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return results;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=smart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smart.js","sourceRoot":"","sources":["../../src/collect/smart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AAGjC,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,qBAAqB;IACrB,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,WAAW,CAAC,YAAY,CAAC,CAAC;QAC1C,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjF,OAAO,CAAC,IAAI,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,OAAO,GAAgB,EAAE,CAAC;IAChC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QAClE,IAAI,CAAC,MAAM;YAAE,SAAS;QAEtB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAChC,MAAM,IAAI,GAAc;gBACtB,MAAM;gBACN,KAAK,EAAE,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,YAAY,IAAI,SAAS;gBACxD,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ;gBACvD,aAAa,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO;gBACxC,cAAc,EAAE,IAAI,CAAC,aAAa,EAAE,KAAK;aAC1C,CAAC;YAEF,gBAAgB;YAChB,IAAI,IAAI,CAAC,iCAAiC,EAAE,CAAC;gBAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,iCAAiC,CAAC;gBACpD,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC;gBAC5C,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,WAAW,CAAC;YACxC,CAAC;YAED,gBAAgB;YAChB,IAAI,IAAI,CAAC,oBAAoB,EAAE,KAAK,EAAE,CAAC;gBACrC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,CAAC;oBACnD,IAAI,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,uBAAuB,EAAE,CAAC;wBAC3D,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC,CAAC;oBAClD,CAAC;oBACD,IAAI,IAAI,CAAC,EAAE,KAAK,GAAG,IAAI,IAAI,CAAC,IAAI,KAAK,wBAAwB,EAAE,CAAC;wBAC9D,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC,CAAC;oBAC9C,CAAC;gBACH,CAAC;YACH,CAAC;YAED,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;QAAC,MAAM,CAAC;YACP,oCAAoC;QACtC,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { hostname } from "os";
|
|
2
|
+
import { readProcFile } from "../lib/parse.js";
|
|
3
|
+
import { run } from "../lib/exec.js";
|
|
4
|
+
export async function collectSystem() {
|
|
5
|
+
const osRelease = readProcFile("/etc/os-release") || "";
|
|
6
|
+
const osName = osRelease.match(/PRETTY_NAME="(.+?)"/)?.[1] || "Unknown";
|
|
7
|
+
const kernel = (await run("uname", ["-r"]))?.trim() || "unknown";
|
|
8
|
+
const uptimeRaw = readProcFile("/proc/uptime") || "0";
|
|
9
|
+
const uptimeSeconds = Math.floor(parseFloat(uptimeRaw.split(" ")[0]));
|
|
10
|
+
const ip = (await run("hostname", ["-I"]))?.trim().split(" ")[0] || "unknown";
|
|
11
|
+
return {
|
|
12
|
+
hostname: hostname(),
|
|
13
|
+
ip,
|
|
14
|
+
os: osName,
|
|
15
|
+
kernel,
|
|
16
|
+
uptime_seconds: uptimeSeconds,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=system.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system.js","sourceRoot":"","sources":["../../src/collect/system.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAGrC,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,SAAS,GAAG,YAAY,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC;IACxD,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;IACxE,MAAM,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;IACjE,MAAM,SAAS,GAAG,YAAY,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC;IACtD,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtE,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;IAE9E,OAAO;QACL,QAAQ,EAAE,QAAQ,EAAE;QACpB,EAAE;QACF,EAAE,EAAE,MAAM;QACV,MAAM;QACN,cAAc,EAAE,aAAa;KAC9B,CAAC;AACJ,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
declare const ConfigSchema: z.ZodObject<{
|
|
3
|
+
server_name: z.ZodDefault<z.ZodString>;
|
|
4
|
+
collection: z.ZodDefault<z.ZodObject<{
|
|
5
|
+
interval_seconds: z.ZodDefault<z.ZodNumber>;
|
|
6
|
+
ipmi: z.ZodDefault<z.ZodBoolean>;
|
|
7
|
+
smart: z.ZodDefault<z.ZodBoolean>;
|
|
8
|
+
}, "strip", z.ZodTypeAny, {
|
|
9
|
+
interval_seconds: number;
|
|
10
|
+
ipmi: boolean;
|
|
11
|
+
smart: boolean;
|
|
12
|
+
}, {
|
|
13
|
+
interval_seconds?: number | undefined;
|
|
14
|
+
ipmi?: boolean | undefined;
|
|
15
|
+
smart?: boolean | undefined;
|
|
16
|
+
}>>;
|
|
17
|
+
forge: z.ZodDefault<z.ZodObject<{
|
|
18
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
19
|
+
url: z.ZodDefault<z.ZodString>;
|
|
20
|
+
api_key: z.ZodDefault<z.ZodString>;
|
|
21
|
+
}, "strip", z.ZodTypeAny, {
|
|
22
|
+
enabled: boolean;
|
|
23
|
+
url: string;
|
|
24
|
+
api_key: string;
|
|
25
|
+
}, {
|
|
26
|
+
enabled?: boolean | undefined;
|
|
27
|
+
url?: string | undefined;
|
|
28
|
+
api_key?: string | undefined;
|
|
29
|
+
}>>;
|
|
30
|
+
thresholds: z.ZodDefault<z.ZodObject<{
|
|
31
|
+
ram_percent: z.ZodDefault<z.ZodNumber>;
|
|
32
|
+
swap_alert: z.ZodDefault<z.ZodBoolean>;
|
|
33
|
+
disk_percent: z.ZodDefault<z.ZodNumber>;
|
|
34
|
+
iowait_percent: z.ZodDefault<z.ZodNumber>;
|
|
35
|
+
nvme_wear_percent: z.ZodDefault<z.ZodNumber>;
|
|
36
|
+
disk_latency_nvme_ms: z.ZodDefault<z.ZodNumber>;
|
|
37
|
+
disk_latency_hdd_ms: z.ZodDefault<z.ZodNumber>;
|
|
38
|
+
cpu_temp_warning_c: z.ZodDefault<z.ZodNumber>;
|
|
39
|
+
cpu_temp_critical_c: z.ZodDefault<z.ZodNumber>;
|
|
40
|
+
interface_utilization_percent: z.ZodDefault<z.ZodNumber>;
|
|
41
|
+
}, "strip", z.ZodTypeAny, {
|
|
42
|
+
ram_percent: number;
|
|
43
|
+
swap_alert: boolean;
|
|
44
|
+
disk_percent: number;
|
|
45
|
+
iowait_percent: number;
|
|
46
|
+
nvme_wear_percent: number;
|
|
47
|
+
disk_latency_nvme_ms: number;
|
|
48
|
+
disk_latency_hdd_ms: number;
|
|
49
|
+
cpu_temp_warning_c: number;
|
|
50
|
+
cpu_temp_critical_c: number;
|
|
51
|
+
interface_utilization_percent: number;
|
|
52
|
+
}, {
|
|
53
|
+
ram_percent?: number | undefined;
|
|
54
|
+
swap_alert?: boolean | undefined;
|
|
55
|
+
disk_percent?: number | undefined;
|
|
56
|
+
iowait_percent?: number | undefined;
|
|
57
|
+
nvme_wear_percent?: number | undefined;
|
|
58
|
+
disk_latency_nvme_ms?: number | undefined;
|
|
59
|
+
disk_latency_hdd_ms?: number | undefined;
|
|
60
|
+
cpu_temp_warning_c?: number | undefined;
|
|
61
|
+
cpu_temp_critical_c?: number | undefined;
|
|
62
|
+
interface_utilization_percent?: number | undefined;
|
|
63
|
+
}>>;
|
|
64
|
+
channels: z.ZodDefault<z.ZodObject<{
|
|
65
|
+
telegram: z.ZodDefault<z.ZodObject<{
|
|
66
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
67
|
+
bot_token: z.ZodDefault<z.ZodString>;
|
|
68
|
+
chat_id: z.ZodDefault<z.ZodString>;
|
|
69
|
+
}, "strip", z.ZodTypeAny, {
|
|
70
|
+
enabled: boolean;
|
|
71
|
+
bot_token: string;
|
|
72
|
+
chat_id: string;
|
|
73
|
+
}, {
|
|
74
|
+
enabled?: boolean | undefined;
|
|
75
|
+
bot_token?: string | undefined;
|
|
76
|
+
chat_id?: string | undefined;
|
|
77
|
+
}>>;
|
|
78
|
+
email: z.ZodDefault<z.ZodObject<{
|
|
79
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
80
|
+
to: z.ZodDefault<z.ZodString>;
|
|
81
|
+
}, "strip", z.ZodTypeAny, {
|
|
82
|
+
enabled: boolean;
|
|
83
|
+
to: string;
|
|
84
|
+
}, {
|
|
85
|
+
enabled?: boolean | undefined;
|
|
86
|
+
to?: string | undefined;
|
|
87
|
+
}>>;
|
|
88
|
+
slack: z.ZodDefault<z.ZodObject<{
|
|
89
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
90
|
+
webhook_url: z.ZodDefault<z.ZodString>;
|
|
91
|
+
}, "strip", z.ZodTypeAny, {
|
|
92
|
+
enabled: boolean;
|
|
93
|
+
webhook_url: string;
|
|
94
|
+
}, {
|
|
95
|
+
enabled?: boolean | undefined;
|
|
96
|
+
webhook_url?: string | undefined;
|
|
97
|
+
}>>;
|
|
98
|
+
}, "strip", z.ZodTypeAny, {
|
|
99
|
+
telegram: {
|
|
100
|
+
enabled: boolean;
|
|
101
|
+
bot_token: string;
|
|
102
|
+
chat_id: string;
|
|
103
|
+
};
|
|
104
|
+
email: {
|
|
105
|
+
enabled: boolean;
|
|
106
|
+
to: string;
|
|
107
|
+
};
|
|
108
|
+
slack: {
|
|
109
|
+
enabled: boolean;
|
|
110
|
+
webhook_url: string;
|
|
111
|
+
};
|
|
112
|
+
}, {
|
|
113
|
+
telegram?: {
|
|
114
|
+
enabled?: boolean | undefined;
|
|
115
|
+
bot_token?: string | undefined;
|
|
116
|
+
chat_id?: string | undefined;
|
|
117
|
+
} | undefined;
|
|
118
|
+
email?: {
|
|
119
|
+
enabled?: boolean | undefined;
|
|
120
|
+
to?: string | undefined;
|
|
121
|
+
} | undefined;
|
|
122
|
+
slack?: {
|
|
123
|
+
enabled?: boolean | undefined;
|
|
124
|
+
webhook_url?: string | undefined;
|
|
125
|
+
} | undefined;
|
|
126
|
+
}>>;
|
|
127
|
+
}, "strip", z.ZodTypeAny, {
|
|
128
|
+
server_name: string;
|
|
129
|
+
collection: {
|
|
130
|
+
interval_seconds: number;
|
|
131
|
+
ipmi: boolean;
|
|
132
|
+
smart: boolean;
|
|
133
|
+
};
|
|
134
|
+
forge: {
|
|
135
|
+
enabled: boolean;
|
|
136
|
+
url: string;
|
|
137
|
+
api_key: string;
|
|
138
|
+
};
|
|
139
|
+
thresholds: {
|
|
140
|
+
ram_percent: number;
|
|
141
|
+
swap_alert: boolean;
|
|
142
|
+
disk_percent: number;
|
|
143
|
+
iowait_percent: number;
|
|
144
|
+
nvme_wear_percent: number;
|
|
145
|
+
disk_latency_nvme_ms: number;
|
|
146
|
+
disk_latency_hdd_ms: number;
|
|
147
|
+
cpu_temp_warning_c: number;
|
|
148
|
+
cpu_temp_critical_c: number;
|
|
149
|
+
interface_utilization_percent: number;
|
|
150
|
+
};
|
|
151
|
+
channels: {
|
|
152
|
+
telegram: {
|
|
153
|
+
enabled: boolean;
|
|
154
|
+
bot_token: string;
|
|
155
|
+
chat_id: string;
|
|
156
|
+
};
|
|
157
|
+
email: {
|
|
158
|
+
enabled: boolean;
|
|
159
|
+
to: string;
|
|
160
|
+
};
|
|
161
|
+
slack: {
|
|
162
|
+
enabled: boolean;
|
|
163
|
+
webhook_url: string;
|
|
164
|
+
};
|
|
165
|
+
};
|
|
166
|
+
}, {
|
|
167
|
+
server_name?: string | undefined;
|
|
168
|
+
collection?: {
|
|
169
|
+
interval_seconds?: number | undefined;
|
|
170
|
+
ipmi?: boolean | undefined;
|
|
171
|
+
smart?: boolean | undefined;
|
|
172
|
+
} | undefined;
|
|
173
|
+
forge?: {
|
|
174
|
+
enabled?: boolean | undefined;
|
|
175
|
+
url?: string | undefined;
|
|
176
|
+
api_key?: string | undefined;
|
|
177
|
+
} | undefined;
|
|
178
|
+
thresholds?: {
|
|
179
|
+
ram_percent?: number | undefined;
|
|
180
|
+
swap_alert?: boolean | undefined;
|
|
181
|
+
disk_percent?: number | undefined;
|
|
182
|
+
iowait_percent?: number | undefined;
|
|
183
|
+
nvme_wear_percent?: number | undefined;
|
|
184
|
+
disk_latency_nvme_ms?: number | undefined;
|
|
185
|
+
disk_latency_hdd_ms?: number | undefined;
|
|
186
|
+
cpu_temp_warning_c?: number | undefined;
|
|
187
|
+
cpu_temp_critical_c?: number | undefined;
|
|
188
|
+
interface_utilization_percent?: number | undefined;
|
|
189
|
+
} | undefined;
|
|
190
|
+
channels?: {
|
|
191
|
+
telegram?: {
|
|
192
|
+
enabled?: boolean | undefined;
|
|
193
|
+
bot_token?: string | undefined;
|
|
194
|
+
chat_id?: string | undefined;
|
|
195
|
+
} | undefined;
|
|
196
|
+
email?: {
|
|
197
|
+
enabled?: boolean | undefined;
|
|
198
|
+
to?: string | undefined;
|
|
199
|
+
} | undefined;
|
|
200
|
+
slack?: {
|
|
201
|
+
enabled?: boolean | undefined;
|
|
202
|
+
webhook_url?: string | undefined;
|
|
203
|
+
} | undefined;
|
|
204
|
+
} | undefined;
|
|
205
|
+
}>;
|
|
206
|
+
export type Config = z.infer<typeof ConfigSchema>;
|
|
207
|
+
export declare function loadConfig(path: string): Config;
|
|
208
|
+
export {};
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { readFileSync } from "fs";
|
|
2
|
+
import { parse } from "yaml";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
const ConfigSchema = z.object({
|
|
5
|
+
server_name: z.string().default("unnamed-server"),
|
|
6
|
+
collection: z.object({
|
|
7
|
+
interval_seconds: z.number().min(60).max(3600).default(300),
|
|
8
|
+
ipmi: z.boolean().default(true),
|
|
9
|
+
smart: z.boolean().default(true),
|
|
10
|
+
}).default({}),
|
|
11
|
+
forge: z.object({
|
|
12
|
+
enabled: z.boolean().default(false),
|
|
13
|
+
url: z.string().default("https://forge.glassmkr.com"),
|
|
14
|
+
api_key: z.string().default(""),
|
|
15
|
+
}).default({}),
|
|
16
|
+
thresholds: z.object({
|
|
17
|
+
ram_percent: z.number().default(90),
|
|
18
|
+
swap_alert: z.boolean().default(true),
|
|
19
|
+
disk_percent: z.number().default(85),
|
|
20
|
+
iowait_percent: z.number().default(20),
|
|
21
|
+
nvme_wear_percent: z.number().default(85),
|
|
22
|
+
disk_latency_nvme_ms: z.number().default(50),
|
|
23
|
+
disk_latency_hdd_ms: z.number().default(200),
|
|
24
|
+
cpu_temp_warning_c: z.number().default(80),
|
|
25
|
+
cpu_temp_critical_c: z.number().default(90),
|
|
26
|
+
interface_utilization_percent: z.number().default(90),
|
|
27
|
+
}).default({}),
|
|
28
|
+
channels: z.object({
|
|
29
|
+
telegram: z.object({
|
|
30
|
+
enabled: z.boolean().default(false),
|
|
31
|
+
bot_token: z.string().default(""),
|
|
32
|
+
chat_id: z.string().default(""),
|
|
33
|
+
}).default({}),
|
|
34
|
+
email: z.object({
|
|
35
|
+
enabled: z.boolean().default(false),
|
|
36
|
+
to: z.string().default(""),
|
|
37
|
+
}).default({}),
|
|
38
|
+
slack: z.object({
|
|
39
|
+
enabled: z.boolean().default(false),
|
|
40
|
+
webhook_url: z.string().default(""),
|
|
41
|
+
}).default({}),
|
|
42
|
+
}).default({}),
|
|
43
|
+
});
|
|
44
|
+
export function loadConfig(path) {
|
|
45
|
+
try {
|
|
46
|
+
const raw = readFileSync(path, "utf-8");
|
|
47
|
+
const parsed = parse(raw);
|
|
48
|
+
return ConfigSchema.parse(parsed);
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
if (err.code === "ENOENT") {
|
|
52
|
+
console.log(`[config] No config file at ${path}, using defaults`);
|
|
53
|
+
return ConfigSchema.parse({});
|
|
54
|
+
}
|
|
55
|
+
throw err;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED