7.6 KiB
Data model
Canonical shapes for metrics, anomalies, alerts, health, and jobs.
Implemented in shared/data-model.js, shared/metrics.js, and agent services.
NodeInfo
{
"nodeId": "a1b2c3…",
"hostname": "homelab-1",
"publicKeyHex": "…64 hex…",
"platform": "linux",
"arch": "x64",
"release": "6.x",
"cpus": 8,
"totalMemMiB": 32000,
"agentVersion": "0.1.0",
"protocolVersion": 1,
"startedAt": 1710000000000,
"charts": ["system.cpu", "system.ram", "…"],
"sampleIntervalMs": 1000,
"sampleCount": 42
}
Metric contexts & charts
Canonical catalog lives in shared/metrics.js (STATIC_CHART_DEFS + runtime instance charts). Collector fills these from /proc + /sys on Linux (os / bare-os fallback elsewhere).
Host-wide (static)
| Family | Contexts / charts | Units (typical) |
|---|---|---|
| CPU / scheduler | system.cpu, system.intr, system.ctxt, system.forks, system.processes, system.active_processes, system.load, system.uptime, system.entropy |
%, interrupts/s, load, seconds |
| Memory | system.ram, mem.available, mem.swap, mem.swap_cached, mem.kernel, mem.slab, mem.writeback, mem.committed, mem.swapio, system.pgpgio, system.pgfaults |
MiB, KiB/s, faults/s |
| Disk aggregate | system.io |
KiB/s (in / out) |
| Network aggregate | system.net, system.ip, system.ipv6 |
kilobits/s |
| TCP / IPv4 | ip.tcppackets, ip.tcperrors, ip.tcpopens, ip.tcpsock, ipv4.packets, ipv4.errors, ipv4.udppackets, ipv4.udperrors |
packets/s, connections |
| PSI pressure | system.*_{some,full}_pressure |
% (avg10/60/300) |
| Memory deep | mem.zswap, mem.hugepages, mem.thp*, mem.reclaiming, mem.oom_kill, mem.numa, mem.ksm* |
MiB / events/s |
| TCP advanced | ip.tcpsyncookies, ip.tcp_*_queue, ip.tcpconnaborts, ip.tcpofo, ip.tcpreorders, ip.tcphandshake, ip.tcpmemorypressures |
events/s |
| Softnet / ICMP | system.softnet_stat, ipv4.icmp, ipv4.icmp_errors |
events/s |
See also shared/metrics-deep.js and gaps in MISSING_METRICS.md.
system.cpu dimensions: guest_nice, guest, steal, softirq, irq, user, system, nice, iowait, idle.
Instance charts (registered at runtime)
| Context | Chart id pattern | Notes |
|---|---|---|
cpu.cpu |
cpu.cpu{N} |
Per-core utilization (same dims as system.cpu) |
disk.io / ops / util / await / avgsz / qops / busy / iotime / discard |
disk_*.{dev} |
Per-disk from /proc/diskstats |
disk.space / disk.inodes |
disk_space.{mount}, disk_inodes.{mount} |
Per-mount via statfs |
net.net / packets / errors / drops / speed |
net*.{iface} |
/proc/net/dev + sysfs speed |
cgroup.cpu / mem / io |
cgroup.*.{id} |
cgroup v2 (default on Linux) |
sensors.temperature / thermal |
sensors.* |
hwmon + thermal zones |
Chart summary objects use fields: id, context, units, dimensions, update_every, first_entry, last_entry, …
MetricSample (live push)
{
"chart": "system.cpu",
"context": "system.cpu",
"ts": 1710000000123,
"values": { "user": 12.4, "system": 3.1, "idle": 84.0 }
}
QueryResult (history)
{
"chart": "system.cpu",
"context": "system.cpu",
"labels": ["time", "user", "system", "nice", "iowait", "irq", "softirq", "idle"],
"data": [[1710000000, 12.4, 3.1, 0, 0, 0, 0, 84.0]],
"view_update_every": 1,
"after": 1709999940,
"before": 1710000000,
"points": 60,
"format": "json"
}
time is unix seconds. Nulls allowed for missing dimensions.
Storage tiers
| Tier | Resolution | Default retention | Env / control |
|---|---|---|---|
| 0 (hot RAM) | 1s | 3600 points (~1h) | PEARDATA_TIER0_POINTS → seeds Data Manager |
| 1 (warm RAM) | avg every N samples (default 60 → ~1m) | 1440 points (~24h in RAM) | PEARDATA_TIER1_POINTS, PEARDATA_TIER1_EVERY |
| HyperDB warm | tier1 flush (static charts only) | 3 months age rotate + 1 GiB soft disk budget (defaults) | PEARDATA_WARM_RETENTION_MS / PEARDATA_WARM_MAX_BYTES seed; live policy in retention.json |
Live retention, soft disk budgets, and auto-prune are managed via desktop Settings → Data (RPC getStorageInfo / setRetentionConfig / pruneHistory). See STORAGE-HYPERDB.md and user-guide/settings.md.
AnomalyEvent
{
"id": "cpu_user_high:1710000000123",
"chart": "system.cpu",
"context": "system.cpu",
"dimension": "user",
"severity": "warning",
"score": 0.6,
"value": 88.2,
"threshold": 80,
"comparator": ">",
"message": "CPU user time high: user=88.2 > 80",
"ts": 1710000000123,
"cleared": false
}
AlertConfig / AlertState
Config fields: id, chart, dimension, warn, crit, comparator, lookbackSec, enabled, info.
State adds: status (CLEAR|WARNING|CRITICAL|UNDEFINED), value, lastStatusChange.
HealthSnapshot
{
"status": "ok",
"score": 1,
"checks": [{ "id": "cpu_user_high", "ok": true, "detail": "…" }],
"ts": 1710000000123
}
Aggregate: any CRITICAL → critical; else any WARNING → degraded; else ok.
JobRecord
{
"id": "uuid",
"name": "snapshot",
"status": "done",
"startedAt": 1710000000000,
"finishedAt": 1710000000500,
"result": { "ok": true }
}
Weights / Metric Correlations
Engine: server/services/weights.js. Not Pearson pairwise correlation — highlight-vs-baseline (or single-window) scoring.
| Method | Windows | Score meaning |
|---|---|---|
volume |
highlight + baseline | Average change × time above/below baseline |
ks2 |
highlight + baseline | Two-sample KS on pairwise diffs |
anomaly-rate |
highlight | Anomaly / alert activity in window |
value |
highlight | Aggregated value (default time_group=cv) |
alerts |
none | Legacy active-alert ranking (Related panel boost) |
Default baseline when omitted: ends at highlight start, duration ≈ highlight × 4 (power-of-two snap). Reject if fewer than ~15 usable points.
Response shape:
{
"method": "volume",
"view": {
"highlight": { "after": 1710000000, "before": 1710000060 },
"baseline": { "after": 1710000000, "before": 1710000000 }
},
"results": [
{ "id": "system.cpu", "weight": 0.91, "context": "system.cpu", "family": "cpu" }
],
"stats": { "scored": 100, "elapsed_ms": 35 }
}
Desktop UX: user-guide/metric-correlations.md. Related (Pearson/taxonomy) is separate: shared/related-metrics.js.
Log entries
Normalized shape from queryLogs / GET /api/v*/logs:
{
"id": "anomaly:1710000000000:system.cpu",
"ts": 1710000000000,
"source": "anomaly",
"severity": "warning",
"unit": "system.cpu",
"message": "…",
"fields": {}
}
Sources: anomaly | audit | journal. Desktop UI and omitted source default to journal (admin); viewers fall back to anomalies. See user-guide/logs.md.
REST ↔ RPC parity
| Concept | RPC | REST |
|---|---|---|
| Charts | listCharts |
GET /api/v1/charts |
| Data | queryData |
GET /api/v3/data |
| Weights | getWeights |
GET /api/v1|v2|v3/weights |
| Logs | queryLogs |
GET /api/v1|v2|v3/logs |
| Contexts | listContexts |
GET /api/v3/contexts |
| Nodes | getNodeInfo |
GET /api/v3/nodes |
| Alerts | listAlerts |
GET /api/v3/alerts |
| Export | getAllMetrics |
GET /api/v3/allmetrics |
| Health | getHealth |
GET /api/v3/health |