@glassmkr/crucible 0.9.0 → 0.9.1

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.
@@ -0,0 +1,74 @@
1
+ // Per-socket pre-filter for IPMI CPU thermal sensors.
2
+ //
3
+ // Background: Gigabyte BMC firmware (observed on H262-Z63 and MC12-LE0
4
+ // with firmware 12.61) reports a `CPU<N>_DTS` sensor that runs ~30°C
5
+ // hotter than the actual AMD die temperature read directly via the
6
+ // kernel's k10temp driver. The same boards also expose a much closer
7
+ // `CPU<N>_TEMP` sensor on each socket. The IPMI fallback path of
8
+ // Forge's `cpu_temperature_high` evaluator picks the maximum across
9
+ // all CPU thermal sensors, which over-fires when both are present.
10
+ //
11
+ // Fix: when the IPMI sensor list contains both `CPU<N>_TEMP` and
12
+ // `CPU<N>_DTS` for the same socket, drop the DTS variant. If only DTS
13
+ // exists for a socket (rare, but possible on firmware that doesn't
14
+ // expose `*_TEMP`), keep it as the only available CPU thermal reading.
15
+ //
16
+ // Tracked: glassmkr/crucible#2. Closed in 0.9.1.
17
+ //
18
+ // This filter only inspects names matching `^CPU\d+_DTS$` (Gigabyte's
19
+ // specific convention). Non-CPU sensors and DTS-shaped sensors that
20
+ // don't fit the per-socket prefix pattern are passed through unchanged
21
+ // so we don't accidentally hide a useful reading on a vendor we
22
+ // haven't characterised.
23
+ const DTS_RE = /^CPU(\d+)_DTS$/i;
24
+ function tempSensorPatternsForSocket(socket) {
25
+ // Match the two observed temperature naming conventions on the same
26
+ // socket: `CPU0_TEMP` (Gigabyte) and `CPU0 Temp` (Supermicro-style
27
+ // with a space). Either form being present means we have a non-DTS
28
+ // reading for this socket and can safely drop the DTS variant.
29
+ const escaped = socket.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
30
+ return [
31
+ new RegExp(`^CPU${escaped}_TEMP$`, "i"),
32
+ new RegExp(`^CPU${escaped}\\s+Temp$`, "i"),
33
+ ];
34
+ }
35
+ /**
36
+ * Drop `CPU<N>_DTS` sensors whose socket has a sibling `CPU<N>_TEMP`
37
+ * (or `CPU<N> Temp`) sensor in the same list. Returns a new array.
38
+ *
39
+ * Stable order: kept sensors retain their original input order. Pure
40
+ * function; safe to call multiple times.
41
+ */
42
+ export function filterRedundantCpuDtsSensors(sensors) {
43
+ const sockets = new Set();
44
+ const dtsBySocket = new Map();
45
+ for (const s of sensors) {
46
+ const m = DTS_RE.exec(s.name);
47
+ if (!m)
48
+ continue;
49
+ sockets.add(m[1]);
50
+ const list = dtsBySocket.get(m[1]) ?? [];
51
+ list.push(s);
52
+ dtsBySocket.set(m[1], list);
53
+ }
54
+ if (sockets.size === 0)
55
+ return sensors.slice();
56
+ // For each socket with a DTS sensor, check whether any non-DTS CPU
57
+ // thermal sensor exists for the same socket.
58
+ const dropDts = new Set();
59
+ for (const socket of sockets) {
60
+ const patterns = tempSensorPatternsForSocket(socket);
61
+ const hasTemp = sensors.some((s) => patterns.some((re) => re.test(s.name)));
62
+ if (hasTemp)
63
+ dropDts.add(socket);
64
+ }
65
+ if (dropDts.size === 0)
66
+ return sensors.slice();
67
+ return sensors.filter((s) => {
68
+ const m = DTS_RE.exec(s.name);
69
+ if (!m)
70
+ return true;
71
+ return !dropDts.has(m[1]);
72
+ });
73
+ }
74
+ //# sourceMappingURL=ipmi-sensor-filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ipmi-sensor-filter.js","sourceRoot":"","sources":["../../src/lib/ipmi-sensor-filter.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,EAAE;AACF,uEAAuE;AACvE,qEAAqE;AACrE,mEAAmE;AACnE,qEAAqE;AACrE,iEAAiE;AACjE,oEAAoE;AACpE,mEAAmE;AACnE,EAAE;AACF,iEAAiE;AACjE,sEAAsE;AACtE,mEAAmE;AACnE,uEAAuE;AACvE,EAAE;AACF,iDAAiD;AACjD,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,uEAAuE;AACvE,gEAAgE;AAChE,yBAAyB;AAMzB,MAAM,MAAM,GAAG,iBAAiB,CAAC;AAEjC,SAAS,2BAA2B,CAAC,MAAc;IACjD,oEAAoE;IACpE,mEAAmE;IACnE,mEAAmE;IACnE,+DAA+D;IAC/D,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;IAC9D,OAAO;QACL,IAAI,MAAM,CAAC,OAAO,OAAO,QAAQ,EAAE,GAAG,CAAC;QACvC,IAAI,MAAM,CAAC,OAAO,OAAO,WAAW,EAAE,GAAG,CAAC;KAC3C,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,4BAA4B,CAAuB,OAAY;IAC7E,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAe,CAAC;IAC3C,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClB,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACzC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC9B,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC,KAAK,EAAE,CAAC;IAE/C,mEAAmE;IACnE,6CAA6C;IAC7C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,2BAA2B,CAAC,MAAM,CAAC,CAAC;QACrD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5E,IAAI,OAAO;YAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC,KAAK,EAAE,CAAC;IAE/C,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QAC1B,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QACpB,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACL,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glassmkr/crucible",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "description": "Lightweight bare metal server monitoring. IPMI, SMART, OS, network. Opinionated alerts.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",