@glassmkr/crucible 0.13.7 → 0.13.8

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.
@@ -7,7 +7,8 @@
7
7
  //
8
8
  // Per CC_SPEC_CRUCIBLE_C7_C10_NETWORK_PROCESS_COLLECTION_2026-05-19.md §3.
9
9
  import { readProcFile } from "../lib/parse.js";
10
- let previous = null;
10
+ import { RateTracker } from "../lib/rate.js";
11
+ const rates = new RateTracker();
11
12
  export function collectConntrack() {
12
13
  const countRaw = readProcFile("/proc/sys/net/netfilter/nf_conntrack_count");
13
14
  const maxRaw = readProcFile("/proc/sys/net/netfilter/nf_conntrack_max");
@@ -27,23 +28,14 @@ export function collectConntrack() {
27
28
  if (!stat) {
28
29
  return { available: true, count, max, percent };
29
30
  }
31
+ // Per-second rates over the most recent interval; null on first
32
+ // snapshot or after a counter reset (host reboot, container restart,
33
+ // rollover). One capture instant for both counters so their baselines
34
+ // advance together (matches the prior single-`previous`-snapshot
35
+ // bookkeeping). RateTracker owns the reset/first-snapshot handling.
30
36
  const nowMs = Date.now();
31
- let insertRate = null;
32
- let dropRate = null;
33
- if (previous) {
34
- const elapsedSec = (nowMs - previous.capturedAtMs) / 1000;
35
- if (elapsedSec > 0) {
36
- const insertDelta = stat.insert_failed - previous.insert_failed;
37
- const dropDelta = stat.drop - previous.drop;
38
- // Negative delta = counter reset (host reboot, container restart,
39
- // or rollover). Treat as a fresh baseline; rates null this tick.
40
- if (insertDelta >= 0)
41
- insertRate = insertDelta / elapsedSec;
42
- if (dropDelta >= 0)
43
- dropRate = dropDelta / elapsedSec;
44
- }
45
- }
46
- previous = { ...stat, capturedAtMs: nowMs };
37
+ const insertRate = rates.computeRate("insert_failed", stat.insert_failed, nowMs);
38
+ const dropRate = rates.computeRate("drop", stat.drop, nowMs);
47
39
  return {
48
40
  available: true,
49
41
  count,
@@ -91,7 +83,7 @@ function parseConntrackStat() {
91
83
  export const __test_only = {
92
84
  parseConntrackStat,
93
85
  resetForTests: () => {
94
- previous = null;
86
+ rates.reset();
95
87
  },
96
88
  };
97
89
  //# sourceMappingURL=conntrack.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"conntrack.js","sourceRoot":"","sources":["../../src/collect/conntrack.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"conntrack.js","sourceRoot":"","sources":["../../src/collect/conntrack.ts"],"names":[],"mappings":"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"}
@@ -17,7 +17,8 @@
17
17
  //
18
18
  // Per CC_SPEC_CRUCIBLE_C11_C18_FULL_BUNDLE_2026-05-19.md §1.4.
19
19
  import { readProcFile } from "../lib/parse.js";
20
- let previous = null;
20
+ import { RateTracker } from "../lib/rate.js";
21
+ const rates = new RateTracker();
21
22
  const TIME_SQUEEZE_COL = 1;
22
23
  const DROPPED_COL = 2;
23
24
  export function collectSoftnet() {
@@ -52,19 +53,10 @@ export function collectSoftnet() {
52
53
  total_dropped_rate_per_sec: null,
53
54
  };
54
55
  }
55
- const nowMs = Date.now();
56
- let ratePerSec = null;
57
- if (previous) {
58
- const elapsedSec = (nowMs - previous.capturedAtMs) / 1000;
59
- if (elapsedSec > 0) {
60
- const delta = total - previous.totalDropped;
61
- // Negative delta = counter reset (host reboot, etc.); leave rate
62
- // null this tick and reset baseline.
63
- if (delta >= 0)
64
- ratePerSec = delta / elapsedSec;
65
- }
66
- }
67
- previous = { totalDropped: total, capturedAtMs: nowMs };
56
+ // Per-second drop rate; null on first snapshot or after a counter
57
+ // reset (host reboot, etc.). RateTracker owns the baseline + reset
58
+ // bookkeeping.
59
+ const ratePerSec = rates.computeRate("dropped", total, Date.now());
68
60
  return {
69
61
  available: true,
70
62
  total_dropped_cumulative: total,
@@ -76,7 +68,7 @@ export const __test_only = {
76
68
  TIME_SQUEEZE_COL,
77
69
  DROPPED_COL,
78
70
  resetForTests: () => {
79
- previous = null;
71
+ rates.reset();
80
72
  },
81
73
  };
82
74
  //# sourceMappingURL=softnet.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"softnet.js","sourceRoot":"","sources":["../../src/collect/softnet.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,EAAE;AACF,+DAA+D;AAC/D,6BAA6B;AAC7B,mEAAmE;AACnE,qDAAqD;AACrD,oEAAoE;AACpE,kEAAkE;AAClE,oEAAoE;AACpE,kCAAkC;AAClC,EAAE;AACF,2DAA2D;AAC3D,iEAAiE;AACjE,2DAA2D;AAC3D,uEAAuE;AACvE,wDAAwD;AACxD,EAAE;AACF,+DAA+D;AAE/D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAmB/C,IAAI,QAAQ,GAA2B,IAAI,CAAC;AAE5C,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAC3B,MAAM,WAAW,GAAG,CAAC,CAAC;AAEtB,MAAM,UAAU,cAAc;IAC5B,MAAM,GAAG,GAAG,YAAY,CAAC,wBAAwB,CAAC,CAAC;IACnD,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,MAAM,EAAE,qCAAqC;YAC7C,wBAAwB,EAAE,CAAC;YAC3B,eAAe,EAAE,EAAE;YACnB,0BAA0B,EAAE,IAAI;SACjC,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACpE,IAAI,MAAM,CAAC,MAAM,IAAI,WAAW;YAAE,SAAS;QAC3C,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,SAAS;QACxC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrB,KAAK,IAAI,OAAO,CAAC;IACnB,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,MAAM,EAAE,2CAA2C;YACnD,wBAAwB,EAAE,CAAC;YAC3B,eAAe,EAAE,EAAE;YACnB,0BAA0B,EAAE,IAAI;SACjC,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,IAAI,UAAU,GAAkB,IAAI,CAAC;IACrC,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,UAAU,GAAG,CAAC,KAAK,GAAG,QAAQ,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC;QAC1D,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;YACnB,MAAM,KAAK,GAAG,KAAK,GAAG,QAAQ,CAAC,YAAY,CAAC;YAC5C,iEAAiE;YACjE,qCAAqC;YACrC,IAAI,KAAK,IAAI,CAAC;gBAAE,UAAU,GAAG,KAAK,GAAG,UAAU,CAAC;QAClD,CAAC;IACH,CAAC;IACD,QAAQ,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IAExD,OAAO;QACL,SAAS,EAAE,IAAI;QACf,wBAAwB,EAAE,KAAK;QAC/B,eAAe,EAAE,MAAM;QACvB,0BAA0B,EAAE,UAAU;KACvC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,gBAAgB;IAChB,WAAW;IACX,aAAa,EAAE,GAAG,EAAE;QAClB,QAAQ,GAAG,IAAI,CAAC;IAClB,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"softnet.js","sourceRoot":"","sources":["../../src/collect/softnet.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,EAAE;AACF,+DAA+D;AAC/D,6BAA6B;AAC7B,mEAAmE;AACnE,qDAAqD;AACrD,oEAAoE;AACpE,kEAAkE;AAClE,oEAAoE;AACpE,kCAAkC;AAClC,EAAE;AACF,2DAA2D;AAC3D,iEAAiE;AACjE,2DAA2D;AAC3D,uEAAuE;AACvE,wDAAwD;AACxD,EAAE;AACF,+DAA+D;AAE/D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAc7C,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC;AAEhC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAC3B,MAAM,WAAW,GAAG,CAAC,CAAC;AAEtB,MAAM,UAAU,cAAc;IAC5B,MAAM,GAAG,GAAG,YAAY,CAAC,wBAAwB,CAAC,CAAC;IACnD,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,MAAM,EAAE,qCAAqC;YAC7C,wBAAwB,EAAE,CAAC;YAC3B,eAAe,EAAE,EAAE;YACnB,0BAA0B,EAAE,IAAI;SACjC,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACpE,IAAI,MAAM,CAAC,MAAM,IAAI,WAAW;YAAE,SAAS;QAC3C,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,SAAS;QACxC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrB,KAAK,IAAI,OAAO,CAAC;IACnB,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,MAAM,EAAE,2CAA2C;YACnD,wBAAwB,EAAE,CAAC;YAC3B,eAAe,EAAE,EAAE;YACnB,0BAA0B,EAAE,IAAI;SACjC,CAAC;IACJ,CAAC;IAED,kEAAkE;IAClE,mEAAmE;IACnE,eAAe;IACf,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAEnE,OAAO;QACL,SAAS,EAAE,IAAI;QACf,wBAAwB,EAAE,KAAK;QAC/B,eAAe,EAAE,MAAM;QACvB,0BAA0B,EAAE,UAAU;KACvC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,gBAAgB;IAChB,WAAW;IACX,aAAa,EAAE,GAAG,EAAE;QAClB,KAAK,CAAC,KAAK,EAAE,CAAC;IAChB,CAAC;CACF,CAAC"}
@@ -30,7 +30,14 @@ export interface SystemdData {
30
30
  failed_unit_details?: Record<string, SystemdFailedUnit>;
31
31
  }
32
32
  export declare function collectSystemd(extraExcludes?: string[]): Promise<SystemdData>;
33
+ /**
34
+ * Map a `systemctl show` `Key=Value` block to a SystemdFailedUnit.
35
+ * Pure: no I/O. Unrecognized Result values collapse to "unknown";
36
+ * a non-numeric NRestarts defaults to 0.
37
+ */
38
+ declare function parseUnitDetailsOutput(unit: string, out: string): SystemdFailedUnit;
33
39
  export declare const __test_only: {
34
40
  RESULT_VALUES: ReadonlySet<SystemdUnitResult>;
35
- parseUnitDetailsOutput: (unit: string, out: string) => SystemdFailedUnit;
41
+ parseUnitDetailsOutput: typeof parseUnitDetailsOutput;
36
42
  };
43
+ export {};
@@ -9,6 +9,7 @@
9
9
  //
10
10
  // Per CC_SPEC_CRUCIBLE_C11_C18_FULL_BUNDLE_2026-05-19.md §1.1.
11
11
  import { run } from "../lib/exec.js";
12
+ import { parseEqualsKeyValue } from "../lib/parse.js";
12
13
  // Units commonly in failed state by design or misconfiguration
13
14
  const DEFAULT_EXCLUDES = [
14
15
  "systemd-networkd-wait-online.service",
@@ -100,19 +101,19 @@ async function readUnitDetails(unit) {
100
101
  ]);
101
102
  if (!out)
102
103
  return fallback;
103
- const props = {};
104
- for (const line of out.split("\n")) {
105
- const eq = line.indexOf("=");
106
- if (eq === -1)
107
- continue;
108
- props[line.slice(0, eq).trim()] = line.slice(eq + 1).trim();
109
- }
104
+ return parseUnitDetailsOutput(unit, out);
105
+ }
106
+ /**
107
+ * Map a `systemctl show` `Key=Value` block to a SystemdFailedUnit.
108
+ * Pure: no I/O. Unrecognized Result values collapse to "unknown";
109
+ * a non-numeric NRestarts defaults to 0.
110
+ */
111
+ function parseUnitDetailsOutput(unit, out) {
112
+ const props = parseEqualsKeyValue(out);
110
113
  const rawResult = props.Result ?? "";
111
114
  const result = RESULT_VALUES.has(rawResult)
112
115
  ? rawResult
113
- : rawResult.length > 0
114
- ? "unknown"
115
- : "unknown";
116
+ : "unknown";
116
117
  const nRestarts = Number.parseInt(props.NRestarts ?? "0", 10);
117
118
  return {
118
119
  name: unit,
@@ -124,26 +125,6 @@ async function readUnitDetails(unit) {
124
125
  }
125
126
  export const __test_only = {
126
127
  RESULT_VALUES,
127
- parseUnitDetailsOutput: (unit, out) => {
128
- const props = {};
129
- for (const line of out.split("\n")) {
130
- const eq = line.indexOf("=");
131
- if (eq === -1)
132
- continue;
133
- props[line.slice(0, eq).trim()] = line.slice(eq + 1).trim();
134
- }
135
- const rawResult = props.Result ?? "";
136
- const result = RESULT_VALUES.has(rawResult)
137
- ? rawResult
138
- : "unknown";
139
- const nRestarts = Number.parseInt(props.NRestarts ?? "0", 10);
140
- return {
141
- name: unit,
142
- result,
143
- active_state: props.ActiveState ?? "",
144
- sub_state: props.SubState ?? "",
145
- n_restarts: Number.isFinite(nRestarts) ? nRestarts : 0,
146
- };
147
- },
128
+ parseUnitDetailsOutput,
148
129
  };
149
130
  //# sourceMappingURL=systemd.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"systemd.js","sourceRoot":"","sources":["../../src/collect/systemd.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"systemd.js","sourceRoot":"","sources":["../../src/collect/systemd.ts"],"names":[],"mappings":"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"}
@@ -14,7 +14,7 @@
14
14
  // Rate calculation mirrors vmstat (C3) and conntrack (C9): module-level
15
15
  // previous-counters Map, null rates on first snapshot, counter-reset
16
16
  // detection.
17
- import { readProcFile } from "../lib/parse.js";
17
+ import { parseColumnarStat, readProcFile } from "../lib/parse.js";
18
18
  let previous = null;
19
19
  export function collectTcpStats() {
20
20
  const snmp = parseTcpSnmp();
@@ -87,33 +87,14 @@ export function parseTcpSnmp() {
87
87
  const raw = readProcFile("/proc/net/snmp");
88
88
  if (!raw)
89
89
  return null;
90
- const lines = raw.split("\n");
91
- let header = null;
92
- for (let i = 0; i < lines.length; i++) {
93
- if (!lines[i].startsWith("Tcp:"))
94
- continue;
95
- const fields = lines[i].slice("Tcp:".length).trim().split(/\s+/);
96
- if (!header) {
97
- header = fields;
98
- continue;
99
- }
100
- // This is the value row.
101
- const inIdx = header.indexOf("InSegs");
102
- const outIdx = header.indexOf("OutSegs");
103
- const retIdx = header.indexOf("RetransSegs");
104
- if (inIdx === -1 || outIdx === -1 || retIdx === -1)
105
- return null;
106
- const inSegs = Number(fields[inIdx]);
107
- const outSegs = Number(fields[outIdx]);
108
- const retransSegs = Number(fields[retIdx]);
109
- if (!Number.isFinite(inSegs) ||
110
- !Number.isFinite(outSegs) ||
111
- !Number.isFinite(retransSegs)) {
112
- return null;
113
- }
114
- return { out_segs: outSegs, retrans_segs: retransSegs, in_segs: inSegs };
115
- }
116
- return null;
90
+ const cols = parseColumnarStat(raw, "Tcp:", ["InSegs", "OutSegs", "RetransSegs"]);
91
+ if (!cols)
92
+ return null;
93
+ return {
94
+ out_segs: cols.OutSegs,
95
+ retrans_segs: cols.RetransSegs,
96
+ in_segs: cols.InSegs,
97
+ };
117
98
  }
118
99
  /**
119
100
  * Parse /proc/net/netstat's `TcpExt:` two-line section for the listen-
@@ -123,27 +104,13 @@ export function parseTcpExt() {
123
104
  const raw = readProcFile("/proc/net/netstat");
124
105
  if (!raw)
125
106
  return null;
126
- const lines = raw.split("\n");
127
- let header = null;
128
- for (let i = 0; i < lines.length; i++) {
129
- if (!lines[i].startsWith("TcpExt:"))
130
- continue;
131
- const fields = lines[i].slice("TcpExt:".length).trim().split(/\s+/);
132
- if (!header) {
133
- header = fields;
134
- continue;
135
- }
136
- const overflowsIdx = header.indexOf("ListenOverflows");
137
- const dropsIdx = header.indexOf("ListenDrops");
138
- if (overflowsIdx === -1 || dropsIdx === -1)
139
- return null;
140
- const overflows = Number(fields[overflowsIdx]);
141
- const drops = Number(fields[dropsIdx]);
142
- if (!Number.isFinite(overflows) || !Number.isFinite(drops))
143
- return null;
144
- return { listen_overflows: overflows, listen_drops: drops };
145
- }
146
- return null;
107
+ const cols = parseColumnarStat(raw, "TcpExt:", ["ListenOverflows", "ListenDrops"]);
108
+ if (!cols)
109
+ return null;
110
+ return {
111
+ listen_overflows: cols.ListenOverflows,
112
+ listen_drops: cols.ListenDrops,
113
+ };
147
114
  }
148
115
  export const __test_only = {
149
116
  resetForTests: () => {
@@ -1 +1 @@
1
- {"version":3,"file":"tcp-stats.js","sourceRoot":"","sources":["../../src/collect/tcp-stats.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tcp-stats.js","sourceRoot":"","sources":["../../src/collect/tcp-stats.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@ import { afterAll, beforeAll, describe, it, expect } from "vitest";
2
2
  import { mkdtempSync, rmSync, writeFileSync } from "fs";
3
3
  import { tmpdir } from "os";
4
4
  import { join } from "path";
5
- import { parseKeyValue, parseKb, readDirSafe, readFileInt, readFileTrim } from "../parse.js";
5
+ import { parseColumnarStat, parseEqualsKeyValue, parseKeyValue, parseKb, readDirSafe, readFileInt, readFileTrim, } from "../parse.js";
6
6
  describe("parseKeyValue", () => {
7
7
  it("parses colon-delimited key/value lines", () => {
8
8
  const out = parseKeyValue("Name: foo\nVersion: 1.2.3\n");
@@ -15,6 +15,67 @@ describe("parseKeyValue", () => {
15
15
  expect(parseKeyValue(" A : 1 \n")).toEqual({ A: "1" });
16
16
  });
17
17
  });
18
+ describe("parseEqualsKeyValue", () => {
19
+ it("parses equals-delimited key/value lines (systemctl show shape)", () => {
20
+ const out = parseEqualsKeyValue("Result=exit-code\nActiveState=failed\nSubState=failed\nNRestarts=2");
21
+ expect(out).toEqual({
22
+ Result: "exit-code",
23
+ ActiveState: "failed",
24
+ SubState: "failed",
25
+ NRestarts: "2",
26
+ });
27
+ });
28
+ it("ignores lines with no equals sign", () => {
29
+ expect(parseEqualsKeyValue("no equals here\nA=1\n")).toEqual({ A: "1" });
30
+ });
31
+ it("trims whitespace around keys and values", () => {
32
+ expect(parseEqualsKeyValue(" A = 1 \n")).toEqual({ A: "1" });
33
+ });
34
+ it("splits on the first equals so values may contain equals", () => {
35
+ expect(parseEqualsKeyValue("ExecStart=/bin/sh -c x=1")).toEqual({
36
+ ExecStart: "/bin/sh -c x=1",
37
+ });
38
+ });
39
+ it("returns {} for empty input", () => {
40
+ expect(parseEqualsKeyValue("")).toEqual({});
41
+ });
42
+ });
43
+ describe("parseColumnarStat", () => {
44
+ // Shape of /proc/net/snmp's Tcp: section.
45
+ const snmp = "Tcp: RtoAlgorithm RtoMin InSegs OutSegs RetransSegs\n" +
46
+ "Tcp: 1 200 9876543 8765432 1234\n";
47
+ it("extracts requested columns from the header+value rows", () => {
48
+ expect(parseColumnarStat(snmp, "Tcp:", ["InSegs", "OutSegs", "RetransSegs"])).toEqual({
49
+ InSegs: 9876543,
50
+ OutSegs: 8765432,
51
+ RetransSegs: 1234,
52
+ });
53
+ });
54
+ it("ignores other prefixed sections in the same file", () => {
55
+ const mixed = "Ip: Forwarding DefaultTTL\nIp: 1 64\n" + snmp + "Udp: InDatagrams\nUdp: 5\n";
56
+ expect(parseColumnarStat(mixed, "Tcp:", ["InSegs"])).toEqual({ InSegs: 9876543 });
57
+ });
58
+ it("returns null when the section is absent", () => {
59
+ expect(parseColumnarStat("Ip: Forwarding\nIp: 1\n", "Tcp:", ["InSegs"])).toBeNull();
60
+ });
61
+ it("returns null when only the header row is present (no value row)", () => {
62
+ expect(parseColumnarStat("Tcp: InSegs OutSegs\n", "Tcp:", ["InSegs"])).toBeNull();
63
+ });
64
+ it("returns null when a requested column is missing from the header", () => {
65
+ expect(parseColumnarStat(snmp, "Tcp:", ["InSegs", "Nope"])).toBeNull();
66
+ });
67
+ it("returns null when a requested value is non-numeric", () => {
68
+ const bad = "Tcp: InSegs OutSegs\nTcp: 100 notanumber\n";
69
+ expect(parseColumnarStat(bad, "Tcp:", ["OutSegs"])).toBeNull();
70
+ });
71
+ it("strips the prefix token before splitting (longer prefix)", () => {
72
+ const ext = "TcpExt: ListenOverflows ListenDrops\nTcpExt: 7 3\n";
73
+ expect(parseColumnarStat(ext, "TcpExt:", ["ListenOverflows", "ListenDrops"])).toEqual({
74
+ ListenOverflows: 7,
75
+ ListenDrops: 3,
76
+ });
77
+ });
78
+ });
18
79
  describe("parseKb", () => {
19
80
  it("parses a numeric kB value", () => {
20
81
  expect(parseKb("16384 kB")).toBe(16384);
@@ -1 +1 @@
1
- {"version":3,"file":"parse.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/parse.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parse.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/parse.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,67 @@
1
+ import { describe, it, expect, beforeEach } from "vitest";
2
+ import { RateTracker } from "../rate.js";
3
+ describe("RateTracker.computeRate", () => {
4
+ let r;
5
+ beforeEach(() => {
6
+ r = new RateTracker();
7
+ });
8
+ it("returns null on the first observation of a key (no baseline)", () => {
9
+ expect(r.computeRate("c", 100, 1000)).toBeNull();
10
+ });
11
+ it("computes per-second rate from a normal positive delta", () => {
12
+ expect(r.computeRate("c", 100, 1000)).toBeNull(); // baseline
13
+ // +50 counts over 2 seconds = 25/s
14
+ expect(r.computeRate("c", 150, 3000)).toBe(25);
15
+ });
16
+ it("computes a fractional rate", () => {
17
+ r.computeRate("c", 0, 0);
18
+ // +1 over 0.5s = 2/s
19
+ expect(r.computeRate("c", 1, 500)).toBe(2);
20
+ });
21
+ it("returns 0 for a zero delta over a positive interval", () => {
22
+ r.computeRate("c", 100, 1000);
23
+ expect(r.computeRate("c", 100, 2000)).toBe(0);
24
+ });
25
+ it("returns null and rebaselines on a counter reset (negative delta)", () => {
26
+ r.computeRate("c", 100, 1000);
27
+ // Counter went backwards (reboot / rollover): null this tick.
28
+ expect(r.computeRate("c", 10, 2000)).toBeNull();
29
+ // ...and the baseline is now the post-reset value, so the next tick
30
+ // rates against 10, not 100. +20 over 1s = 20/s.
31
+ expect(r.computeRate("c", 30, 3000)).toBe(20);
32
+ });
33
+ it("returns null for a zero elapsed interval but still rebaselines the value", () => {
34
+ r.computeRate("c", 100, 1000);
35
+ // Same instant: elapsedSec == 0 -> null (no divide).
36
+ expect(r.computeRate("c", 200, 1000)).toBeNull();
37
+ // Baseline value advanced to 200 at t=1000; next tick rates against
38
+ // 200. +50 over 1s = 50/s.
39
+ expect(r.computeRate("c", 250, 2000)).toBe(50);
40
+ });
41
+ it("returns null for a negative elapsed interval (clock went backwards)", () => {
42
+ r.computeRate("c", 100, 2000);
43
+ expect(r.computeRate("c", 200, 1000)).toBeNull();
44
+ });
45
+ it("tracks multiple keys independently", () => {
46
+ r.computeRate("a", 100, 1000);
47
+ r.computeRate("b", 200, 1000);
48
+ // a: +10/1s = 10; b: +40/1s = 40. Same nowMs (callers share one
49
+ // capture instant for counters that must advance together).
50
+ expect(r.computeRate("a", 110, 2000)).toBe(10);
51
+ expect(r.computeRate("b", 240, 2000)).toBe(40);
52
+ });
53
+ it("does not let one key's reset affect another key", () => {
54
+ r.computeRate("a", 100, 1000);
55
+ r.computeRate("b", 100, 1000);
56
+ expect(r.computeRate("a", 50, 2000)).toBeNull(); // a reset
57
+ expect(r.computeRate("b", 150, 2000)).toBe(50); // b unaffected
58
+ });
59
+ it("reset() drops all baselines so the next call is treated as first", () => {
60
+ r.computeRate("c", 100, 1000);
61
+ r.reset();
62
+ expect(r.computeRate("c", 150, 2000)).toBeNull();
63
+ // And tracking resumes from the new baseline.
64
+ expect(r.computeRate("c", 200, 3000)).toBe(50);
65
+ });
66
+ });
67
+ //# sourceMappingURL=rate.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/rate.test.ts"],"names":[],"mappings":"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"}
@@ -3,5 +3,7 @@ export declare function readFileTrim(path: string): string | null;
3
3
  export declare function readFileInt(path: string): number | null;
4
4
  export declare function readDirSafe(path: string): string[];
5
5
  export declare function parseKeyValue(raw: string): Record<string, string>;
6
+ export declare function parseEqualsKeyValue(raw: string): Record<string, string>;
7
+ export declare function parseColumnarStat(raw: string, prefix: string, wantedCols: string[]): Record<string, number> | null;
6
8
  export declare function parseKb(val: string | undefined): number;
7
9
  export declare function sleep(ms: number): Promise<void>;
package/dist/lib/parse.js CHANGED
@@ -50,6 +50,56 @@ export function parseKeyValue(raw) {
50
50
  }
51
51
  return result;
52
52
  }
53
+ // `Key=Value` block parser (the `=`-delimited cousin of parseKeyValue).
54
+ // Used by `systemctl show` output. Splits on the first `=` per line so
55
+ // values containing `=` survive intact; lines without `=` are skipped.
56
+ // Keys and values are trimmed. Shared by the systemd collector, which
57
+ // previously inlined this loop (twice).
58
+ export function parseEqualsKeyValue(raw) {
59
+ const result = {};
60
+ for (const line of raw.split("\n")) {
61
+ const idx = line.indexOf("=");
62
+ if (idx === -1)
63
+ continue;
64
+ result[line.slice(0, idx).trim()] = line.slice(idx + 1).trim();
65
+ }
66
+ return result;
67
+ }
68
+ // Parse the prefixed two-line header+values shape of /proc/net/snmp and
69
+ // /proc/net/netstat sections (e.g. `Tcp:` / `TcpExt:`). The first line
70
+ // starting with `prefix` supplies the column names; the second supplies
71
+ // the values. The prefix token is stripped from both lines before the
72
+ // remainder is whitespace-split. Values are parsed in base 10 via
73
+ // Number(). Returns a record of the requested columns, or null if the
74
+ // section/value-row is missing, a requested column is absent from the
75
+ // header, or any requested value is non-finite (all-or-nothing, matching
76
+ // the tcp-stats callers' strictness).
77
+ export function parseColumnarStat(raw, prefix, wantedCols) {
78
+ const lines = raw.split("\n");
79
+ let header = null;
80
+ for (const line of lines) {
81
+ if (!line.startsWith(prefix))
82
+ continue;
83
+ const fields = line.slice(prefix.length).trim().split(/\s+/);
84
+ if (!header) {
85
+ header = fields;
86
+ continue;
87
+ }
88
+ // This is the value row.
89
+ const out = {};
90
+ for (const col of wantedCols) {
91
+ const idx = header.indexOf(col);
92
+ if (idx === -1)
93
+ return null;
94
+ const value = Number(fields[idx]);
95
+ if (!Number.isFinite(value))
96
+ return null;
97
+ out[col] = value;
98
+ }
99
+ return out;
100
+ }
101
+ return null;
102
+ }
53
103
  export function parseKb(val) {
54
104
  if (!val)
55
105
  return 0;
@@ -1 +1 @@
1
- {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/lib/parse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AAE/C,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,sEAAsE;AACtE,sEAAsE;AACtE,yEAAyE;AACzE,wEAAwE;AACxE,+BAA+B;AAC/B,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,yEAAyE;AACzE,wEAAwE;AACxE,kEAAkE;AAClE,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,MAAM,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAC7B,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAChD,OAAO,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACzB,CAAC;AAED,2EAA2E;AAC3E,2EAA2E;AAC3E,yCAAyC;AACzC,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,IAAI,CAAC;QACH,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,GAAG,KAAK,CAAC,CAAC;YAAE,SAAS;QACzB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACjE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,GAAuB;IAC7C,IAAI,CAAC,GAAG;QAAE,OAAO,CAAC,CAAC;IACnB,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACrD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,EAAU;IAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AAC/C,CAAC"}
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/lib/parse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export declare class RateTracker {
2
+ private readonly previous;
3
+ /**
4
+ * Record `value` for `key` at `nowMs` and return the per-second rate
5
+ * since the previous observation, or null on the first observation,
6
+ * after a counter reset (negative delta), or for a non-positive
7
+ * elapsed interval. The baseline is always updated.
8
+ */
9
+ computeRate(key: string, value: number, nowMs: number): number | null;
10
+ /** Drop all stored baselines (test hook + reset-on-counter-source-loss). */
11
+ reset(): void;
12
+ }
@@ -0,0 +1,52 @@
1
+ // Shared cumulative-counter -> per-second-rate state machine.
2
+ //
3
+ // Several collectors read a monotonically increasing /proc counter and
4
+ // report its per-second rate of change across snapshot intervals. They
5
+ // all duplicated the same bookkeeping: hold the previous value + capture
6
+ // time, return null on the first snapshot (no baseline to delta against)
7
+ // and after a counter reset (negative delta = host reboot / rollover),
8
+ // and guard against a zero/negative elapsed interval. This centralizes
9
+ // that logic so each collector keeps only its own parse + output shape.
10
+ //
11
+ // Semantics (must match the inline versions this replaced, byte for
12
+ // byte):
13
+ // - First observation of a key: returns null, stores the baseline.
14
+ // - elapsedSec = (nowMs - prevCapturedAtMs) / 1000. Rate is only
15
+ // computed when elapsedSec > 0; otherwise null.
16
+ // - delta = value - prevValue. Rate is only computed when delta >= 0;
17
+ // a negative delta (counter reset / wraparound) returns null.
18
+ // - On EVERY call after the first, the stored baseline is replaced
19
+ // with {value, capturedAtMs: nowMs} regardless of whether a rate was
20
+ // produced (so a reset tick rebaselines and the next tick can rate
21
+ // again).
22
+ //
23
+ // Callers tracking multiple counters that must share one capture instant
24
+ // (so their baselines advance together) capture nowMs once and pass the
25
+ // same value to each computeRate call.
26
+ export class RateTracker {
27
+ previous = new Map();
28
+ /**
29
+ * Record `value` for `key` at `nowMs` and return the per-second rate
30
+ * since the previous observation, or null on the first observation,
31
+ * after a counter reset (negative delta), or for a non-positive
32
+ * elapsed interval. The baseline is always updated.
33
+ */
34
+ computeRate(key, value, nowMs) {
35
+ const prev = this.previous.get(key);
36
+ this.previous.set(key, { value, capturedAtMs: nowMs });
37
+ if (!prev)
38
+ return null;
39
+ const elapsedSec = (nowMs - prev.capturedAtMs) / 1000;
40
+ if (elapsedSec <= 0)
41
+ return null;
42
+ const delta = value - prev.value;
43
+ if (delta < 0)
44
+ return null;
45
+ return delta / elapsedSec;
46
+ }
47
+ /** Drop all stored baselines (test hook + reset-on-counter-source-loss). */
48
+ reset() {
49
+ this.previous.clear();
50
+ }
51
+ }
52
+ //# sourceMappingURL=rate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate.js","sourceRoot":"","sources":["../../src/lib/rate.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,EAAE;AACF,uEAAuE;AACvE,uEAAuE;AACvE,yEAAyE;AACzE,yEAAyE;AACzE,uEAAuE;AACvE,uEAAuE;AACvE,wEAAwE;AACxE,EAAE;AACF,oEAAoE;AACpE,SAAS;AACT,qEAAqE;AACrE,mEAAmE;AACnE,oDAAoD;AACpD,wEAAwE;AACxE,kEAAkE;AAClE,qEAAqE;AACrE,yEAAyE;AACzE,uEAAuE;AACvE,cAAc;AACd,EAAE;AACF,yEAAyE;AACzE,wEAAwE;AACxE,uCAAuC;AAOvC,MAAM,OAAO,WAAW;IACL,QAAQ,GAAG,IAAI,GAAG,EAAoB,CAAC;IAExD;;;;;OAKG;IACH,WAAW,CAAC,GAAW,EAAE,KAAa,EAAE,KAAa;QACnD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC;QACvD,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,MAAM,UAAU,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC;QACtD,IAAI,UAAU,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACjC,MAAM,KAAK,GAAG,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACjC,IAAI,KAAK,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QAC3B,OAAO,KAAK,GAAG,UAAU,CAAC;IAC5B,CAAC;IAED,4EAA4E;IAC5E,KAAK;QACH,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glassmkr/crucible",
3
- "version": "0.13.7",
3
+ "version": "0.13.8",
4
4
  "description": "Lightweight bare metal server monitoring. IPMI, SMART, OS, network. Opinionated alerts.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",