@camstack/system 1.2.455 → 1.2.457
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/dist/addon-runner.js +96 -10
- package/dist/addon-runner.mjs +96 -10
- package/dist/{agent-https-CLWrOO3o.mjs → agent-https-CK9Z4sSR.mjs} +32 -5
- package/dist/{agent-https-CCvlRQKV.js → agent-https-CoyOZ3pC.js} +37 -4
- package/dist/auth/auth-manager.d.ts +9 -0
- package/dist/auth/legacy-token-tables.d.ts +16 -0
- package/dist/auth/user-management-internal.d.ts +9 -28
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +2 -2
- package/dist/builtins/alerts/alerts.addon.mjs +2 -2
- package/dist/builtins/autotrack/index.js +1 -1
- package/dist/builtins/autotrack/index.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2 -2
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
- package/dist/builtins/calendars/calendars.addon.js +1 -1
- package/dist/builtins/calendars/calendars.addon.mjs +1 -1
- package/dist/builtins/camera-grid/index.js +1 -1
- package/dist/builtins/camera-grid/index.mjs +1 -1
- package/dist/builtins/composer/composer.addon.js +2 -2
- package/dist/builtins/composer/composer.addon.mjs +2 -2
- package/dist/builtins/console-logging/console-destination.d.ts +1 -2
- package/dist/builtins/console-logging/index.js +1 -4
- package/dist/builtins/console-logging/index.mjs +1 -4
- package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
- package/dist/builtins/device-history/capture/capture-engine.d.ts +6 -0
- package/dist/builtins/device-history/device-history.addon.js +441 -83
- package/dist/builtins/device-history/device-history.addon.mjs +441 -83
- package/dist/builtins/device-history/query/history-query.d.ts +35 -9
- package/dist/builtins/device-history/query/point-shape.d.ts +33 -0
- package/dist/builtins/device-history/retention/retention.d.ts +1 -1
- package/dist/builtins/device-history/rollup/rollup-engine.d.ts +2 -0
- package/dist/builtins/device-history/rollup/rollup-math.d.ts +6 -0
- package/dist/builtins/device-history/store/history-store.d.ts +7 -0
- package/dist/builtins/device-history/store/series-registry.d.ts +26 -1
- package/dist/builtins/device-manager/device-manager.addon.js +1 -1
- package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
- package/dist/builtins/hub-forwarder/hub-forwarder-destination.d.ts +1 -2
- package/dist/builtins/hub-forwarder/index.js +1 -4
- package/dist/builtins/hub-forwarder/index.mjs +1 -4
- package/dist/builtins/keychain/index.js +4 -4
- package/dist/builtins/keychain/index.mjs +4 -4
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/auth-schema.d.ts +4 -7
- package/dist/builtins/local-auth/local-auth.addon.d.ts +7 -8
- package/dist/builtins/local-auth/local-auth.addon.js +1086 -1329
- package/dist/builtins/local-auth/local-auth.addon.mjs +1085 -1326
- package/dist/builtins/local-auth/preferences-record-kinds.d.ts +27 -0
- package/dist/builtins/local-auth/record-kinds.d.ts +4 -3
- package/dist/builtins/local-auth/user-preferences-store.d.ts +56 -0
- package/dist/builtins/local-network/local-network.addon.d.ts +8 -0
- package/dist/builtins/local-network/local-network.addon.js +30 -5
- package/dist/builtins/local-network/local-network.addon.mjs +30 -5
- package/dist/builtins/loki-logging/index.js +323 -7
- package/dist/builtins/loki-logging/index.mjs +323 -7
- package/dist/builtins/loki-logging/loki-destination.d.ts +20 -3
- package/dist/builtins/loki-logging/loki-read.d.ts +51 -0
- package/dist/builtins/native-metrics/native-metrics.addon.js +290 -112
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +290 -112
- package/dist/builtins/native-metrics/node-metrics-history-recorder.d.ts +106 -35
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/record-entries/index.js +1 -1
- package/dist/builtins/record-entries/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/index.js +1 -1
- package/dist/builtins/sqlite-storage/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/records/records-engine-types.d.ts +1 -0
- package/dist/builtins/sqlite-storage/records/records-provider.d.ts +13 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +52 -6
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +52 -6
- package/dist/builtins/storage-orchestrator/location-history-recorder.d.ts +76 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +9 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +144 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +144 -1
- package/dist/builtins/system-config/system-config.addon.js +3 -3
- package/dist/builtins/system-config/system-config.addon.mjs +3 -3
- package/dist/builtins/winston-logging/index.js +165 -3
- package/dist/builtins/winston-logging/index.mjs +165 -3
- package/dist/builtins/winston-logging/log-file-cursor.d.ts +12 -0
- package/dist/builtins/winston-logging/log-file-index-store.d.ts +11 -0
- package/dist/builtins/winston-logging/log-file-index.d.ts +77 -0
- package/dist/builtins/winston-logging/log-file-read-client.d.ts +44 -0
- package/dist/builtins/winston-logging/log-file-read-protocol.d.ts +41 -0
- package/dist/builtins/winston-logging/log-file-read-worker.d.ts +1 -0
- package/dist/builtins/winston-logging/log-file-reader.d.ts +51 -0
- package/dist/builtins/winston-logging/winston-destination.d.ts +20 -2
- package/dist/{composition-sources-CSzD5_qX.mjs → composition-sources-B_jeZDRJ.mjs} +1 -1
- package/dist/{composition-sources-BxUkLNSo.js → composition-sources-qKyvMAvc.js} +1 -1
- package/dist/{constants-DruwCkfp.js → constants-B_X9cWEK.js} +1 -1
- package/dist/{constants-DOlYt1t1.mjs → constants-cxKcZRMi.mjs} +1 -1
- package/dist/{device-ca-uFbTyY_o.mjs → device-ca-BB6nHAL5.mjs} +1 -1
- package/dist/{device-ca-QPBgfqVY.js → device-ca-CVK3YcR_.js} +1 -1
- package/dist/{dist-DjQ8C-ku.js → dist-C89nqNnn.js} +721 -154
- package/dist/{dist-BpSENkRJ.mjs → dist-Dhux90yB.mjs} +668 -155
- package/dist/file-host-worker.js +1 -1
- package/dist/file-host-worker.mjs +1 -1
- package/dist/{hub-mdns-ciao-DlgkFJVY.mjs → hub-mdns-ciao-B8olZqqd.mjs} +20 -13
- package/dist/{hub-mdns-ciao-Bkrvgnma.js → hub-mdns-ciao-DB1Y9agt.js} +20 -13
- package/dist/index.d.ts +3 -4
- package/dist/index.js +145 -24
- package/dist/index.mjs +138 -22
- package/dist/kernel/config-schema.d.ts +5 -0
- package/dist/kernel/moleculer/accessory-prune-gate.d.ts +55 -0
- package/dist/log-file-read-protocol-B7M3X3bT.mjs +785 -0
- package/dist/log-file-read-protocol-D0WcLbIV.js +817 -0
- package/dist/log-file-read-worker.js +64 -0
- package/dist/log-file-read-worker.mjs +64 -0
- package/dist/log-read-filter-Bi066jwU.js +134 -0
- package/dist/log-read-filter-D7Ev3zm-.mjs +93 -0
- package/dist/logging/log-manager.d.ts +10 -6
- package/dist/logging/log-read-filter.d.ts +43 -0
- package/dist/{phase6-declare-gate-DrmTtz7F.js → phase6-declare-gate-BO-_jLh_.js} +1 -1
- package/dist/{phase6-declare-gate-JQUqgQgq.mjs → phase6-declare-gate-x9ZCbQJP.mjs} +1 -1
- package/dist/{restore-archive-4OP0EYg6.js → restore-archive-4DOUR5Gu.js} +1 -1
- package/dist/{restore-archive-YFSJRtKy.mjs → restore-archive-DyOaPeAr.mjs} +1 -1
- package/dist/tls/cert-issue.d.ts +16 -1
- package/dist/tls/cert-manager.d.ts +6 -0
- package/dist/tls/index.d.ts +1 -1
- package/dist/{wal-maintenance-TyuOEVy1.mjs → wal-maintenance-BMiX6UIa.mjs} +0 -0
- package/dist/{wal-maintenance-Bl0ZKjVR.js → wal-maintenance-DVN-DiVP.js} +0 -0
- package/package.json +1 -1
- package/dist/auth/admin-token-manager.d.ts +0 -51
- package/dist/auth/scoped-token-manager.d.ts +0 -25
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-C89nqNnn.js");
|
|
7
7
|
let node_fs_promises = require("node:fs/promises");
|
|
8
8
|
let node_util = require("node:util");
|
|
9
9
|
let node_os = require("node:os");
|
|
@@ -1025,16 +1025,107 @@ function mergeLoadSeries(input) {
|
|
|
1025
1025
|
}
|
|
1026
1026
|
//#endregion
|
|
1027
1027
|
//#region src/builtins/native-metrics/node-metrics-history-recorder.ts
|
|
1028
|
+
/**
|
|
1029
|
+
* Node load history via device-history (D850, LTS P4) — hub only: the hub's
|
|
1030
|
+
* bus carries every node's snapshots, so the hub's writer is the cluster's.
|
|
1031
|
+
*
|
|
1032
|
+
* Per RUNNER, never per PID. A series was once scoped by process id, and a pid
|
|
1033
|
+
* changes on every runner restart: the hub held ~11.8k node series, most of
|
|
1034
|
+
* them one restart long, and no chart could follow a runner across a respawn.
|
|
1035
|
+
* The scope is now the fold's own function key (`load-series-fold.ts`): the
|
|
1036
|
+
* runner's addon id, or `__root__` / `__unattributed__`, so a runner keeps ONE
|
|
1037
|
+
* series for life and the cold tier folds exactly like the hot ring. The old
|
|
1038
|
+
* `process-*` keys are no longer written; their rows age out by retention.
|
|
1039
|
+
*
|
|
1040
|
+
* Node TOTALS ride the resources snapshot: CPU %, memory %, CPU temperature
|
|
1041
|
+
* and, when the node has one, GPU utilisation and temperature. A reading the
|
|
1042
|
+
* node did not take (`null`) is no point — never 0 (D393).
|
|
1043
|
+
*
|
|
1044
|
+
* The in-memory rings still serve the last hour for charts.
|
|
1045
|
+
*/
|
|
1028
1046
|
var ADDON_ID = "metrics-native";
|
|
1029
|
-
var
|
|
1030
|
-
|
|
1031
|
-
|
|
1047
|
+
var MIB = 1048576;
|
|
1048
|
+
function keyOf(name) {
|
|
1049
|
+
return `addon:${ADDON_ID}/${name}`;
|
|
1050
|
+
}
|
|
1051
|
+
/** Per-runner series (scope = the fold key). */
|
|
1052
|
+
var RUNNER_CPU_MAIN_KEY = keyOf("runner-cpu-main-percent");
|
|
1053
|
+
var RUNNER_CPU_GC_KEY = keyOf("runner-cpu-gc-percent");
|
|
1054
|
+
var RUNNER_CPU_LIFETIME_KEY = keyOf("runner-cpu-lifetime-percent");
|
|
1055
|
+
var RUNNER_RSS_KEY = keyOf("runner-rss-mib");
|
|
1056
|
+
var RUNNER_PROCESSES_KEY = keyOf("runner-processes");
|
|
1057
|
+
/** Node totals (scope ''). */
|
|
1058
|
+
var NODE_CPU_KEY = keyOf("node-cpu-percent");
|
|
1059
|
+
var NODE_MEMORY_KEY = keyOf("node-memory-percent");
|
|
1060
|
+
var NODE_CPU_TEMPERATURE_KEY = keyOf("node-cpu-temperature");
|
|
1061
|
+
var NODE_GPU_KEY = keyOf("node-gpu-percent");
|
|
1062
|
+
var NODE_GPU_TEMPERATURE_KEY = keyOf("node-gpu-temperature");
|
|
1063
|
+
var NODE_CONTAINER_CURRENT_KEY = keyOf("container-current-mib");
|
|
1064
|
+
keyOf("process-cpu-percent");
|
|
1065
|
+
keyOf("process-rss-mib");
|
|
1066
|
+
var DECLARATIONS = [
|
|
1067
|
+
{
|
|
1068
|
+
name: "runner-cpu-main-percent",
|
|
1069
|
+
displayName: "Runner CPU % (main thread)",
|
|
1070
|
+
unit: "%"
|
|
1071
|
+
},
|
|
1072
|
+
{
|
|
1073
|
+
name: "runner-cpu-gc-percent",
|
|
1074
|
+
displayName: "Runner CPU % (GC)",
|
|
1075
|
+
unit: "%"
|
|
1076
|
+
},
|
|
1077
|
+
{
|
|
1078
|
+
name: "runner-cpu-lifetime-percent",
|
|
1079
|
+
displayName: "Runner CPU % (lifetime average)",
|
|
1080
|
+
unit: "%"
|
|
1081
|
+
},
|
|
1082
|
+
{
|
|
1083
|
+
name: "runner-rss-mib",
|
|
1084
|
+
displayName: "Runner RSS (MiB)",
|
|
1085
|
+
unit: "MiB"
|
|
1086
|
+
},
|
|
1087
|
+
{
|
|
1088
|
+
name: "runner-processes",
|
|
1089
|
+
displayName: "Runner processes",
|
|
1090
|
+
unit: "count"
|
|
1091
|
+
},
|
|
1092
|
+
{
|
|
1093
|
+
name: "node-cpu-percent",
|
|
1094
|
+
displayName: "Node CPU %",
|
|
1095
|
+
unit: "%"
|
|
1096
|
+
},
|
|
1097
|
+
{
|
|
1098
|
+
name: "node-memory-percent",
|
|
1099
|
+
displayName: "Node memory %",
|
|
1100
|
+
unit: "%"
|
|
1101
|
+
},
|
|
1102
|
+
{
|
|
1103
|
+
name: "node-cpu-temperature",
|
|
1104
|
+
displayName: "Node CPU temperature",
|
|
1105
|
+
unit: "°C"
|
|
1106
|
+
},
|
|
1107
|
+
{
|
|
1108
|
+
name: "node-gpu-percent",
|
|
1109
|
+
displayName: "Node GPU %",
|
|
1110
|
+
unit: "%"
|
|
1111
|
+
},
|
|
1112
|
+
{
|
|
1113
|
+
name: "node-gpu-temperature",
|
|
1114
|
+
displayName: "Node GPU temperature",
|
|
1115
|
+
unit: "°C"
|
|
1116
|
+
},
|
|
1117
|
+
{
|
|
1118
|
+
name: "container-current-mib",
|
|
1119
|
+
displayName: "Container memory current (MiB)",
|
|
1120
|
+
unit: "MiB"
|
|
1121
|
+
}
|
|
1122
|
+
];
|
|
1032
1123
|
function nodeMetricsHistoryClient(api) {
|
|
1033
1124
|
return {
|
|
1034
1125
|
declareSeries: (input) => api.declareSeries.mutate(input),
|
|
1035
1126
|
record: (input) => api.record.mutate({ points: [...input.points] }),
|
|
1036
1127
|
queryNode: async (input) => {
|
|
1037
|
-
return { series: (await api.queryNode.query(input)).series.map((s) => ({
|
|
1128
|
+
return { series: (await api.queryNode.query({ ...input })).series.map((s) => ({
|
|
1038
1129
|
scope: s.scope,
|
|
1039
1130
|
points: s.points.map((p) => ({
|
|
1040
1131
|
t: p.t,
|
|
@@ -1050,78 +1141,112 @@ function refusalCounts(result) {
|
|
|
1050
1141
|
for (const r of result.refused) counts[r.reason] = (counts[r.reason] ?? 0) + r.count;
|
|
1051
1142
|
return counts;
|
|
1052
1143
|
}
|
|
1144
|
+
/** The fold's function key of a process: the same rule as `foldSnapshotByFunction`. */
|
|
1145
|
+
function runnerScopeOf(process) {
|
|
1146
|
+
if (process.addonId !== null) return process.addonId;
|
|
1147
|
+
return process.classification === "root" ? require_dist.ROOT_BUCKET_KEY : require_dist.UNATTRIBUTED_BUCKET_KEY;
|
|
1148
|
+
}
|
|
1149
|
+
function round1(value) {
|
|
1150
|
+
return Math.round(value * 10) / 10;
|
|
1151
|
+
}
|
|
1053
1152
|
var NodeMetricsHistoryRecorder = class {
|
|
1054
1153
|
deps;
|
|
1055
1154
|
declared = false;
|
|
1155
|
+
lastTotalsAt = /* @__PURE__ */ new Map();
|
|
1156
|
+
/** A not-ready skip was logged and device-history has not been ready since. */
|
|
1157
|
+
waitLogged = false;
|
|
1056
1158
|
constructor(deps) {
|
|
1057
1159
|
this.deps = deps;
|
|
1058
1160
|
}
|
|
1059
1161
|
async declare() {
|
|
1060
1162
|
if (this.declared) return;
|
|
1061
|
-
const
|
|
1062
|
-
|
|
1063
|
-
name: "process-cpu-percent",
|
|
1163
|
+
for (const d of DECLARATIONS) await this.deps.deviceHistory.declareSeries({
|
|
1164
|
+
name: d.name,
|
|
1064
1165
|
subjectKind: "node",
|
|
1065
1166
|
kind: "gauge",
|
|
1066
|
-
displayName:
|
|
1167
|
+
displayName: d.displayName,
|
|
1067
1168
|
ingest: "points",
|
|
1068
|
-
unit:
|
|
1069
|
-
});
|
|
1070
|
-
await deviceHistory.declareSeries({
|
|
1071
|
-
name: "process-rss-mib",
|
|
1072
|
-
subjectKind: "node",
|
|
1073
|
-
kind: "gauge",
|
|
1074
|
-
displayName: "Process RSS (MiB)",
|
|
1075
|
-
ingest: "points",
|
|
1076
|
-
unit: "MiB"
|
|
1077
|
-
});
|
|
1078
|
-
await deviceHistory.declareSeries({
|
|
1079
|
-
name: "container-current-mib",
|
|
1080
|
-
subjectKind: "node",
|
|
1081
|
-
kind: "gauge",
|
|
1082
|
-
displayName: "Container memory current (MiB)",
|
|
1083
|
-
ingest: "points",
|
|
1084
|
-
unit: "MiB"
|
|
1169
|
+
unit: d.unit
|
|
1085
1170
|
});
|
|
1086
1171
|
this.declared = true;
|
|
1087
1172
|
}
|
|
1173
|
+
/** One process snapshot: per-runner sums plus the container's memory. */
|
|
1088
1174
|
async recordSample(nodeId, atMs, processes, containerMemory) {
|
|
1089
|
-
|
|
1090
|
-
|
|
1175
|
+
const subject = {
|
|
1176
|
+
kind: "node",
|
|
1177
|
+
nodeId
|
|
1178
|
+
};
|
|
1179
|
+
const point = (key, scope, value) => ({
|
|
1180
|
+
key,
|
|
1181
|
+
subject,
|
|
1182
|
+
scope,
|
|
1183
|
+
ts: atMs,
|
|
1184
|
+
value
|
|
1185
|
+
});
|
|
1186
|
+
const byRunner = /* @__PURE__ */ new Map();
|
|
1091
1187
|
for (const p of processes) {
|
|
1092
|
-
const scope =
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1188
|
+
const scope = runnerScopeOf(p);
|
|
1189
|
+
const t = byRunner.get(scope) ?? {
|
|
1190
|
+
main: 0,
|
|
1191
|
+
gc: 0,
|
|
1192
|
+
splitKnown: true,
|
|
1193
|
+
lifetime: 0,
|
|
1194
|
+
rss: 0,
|
|
1195
|
+
count: 0
|
|
1196
|
+
};
|
|
1197
|
+
const known = p.cpuMainPercent !== null && p.cpuGcPercent !== null;
|
|
1198
|
+
byRunner.set(scope, {
|
|
1199
|
+
main: t.main + (p.cpuMainPercent ?? 0),
|
|
1200
|
+
gc: t.gc + (p.cpuGcPercent ?? 0),
|
|
1201
|
+
splitKnown: t.splitKnown && known,
|
|
1202
|
+
lifetime: t.lifetime + p.cpuPercent,
|
|
1203
|
+
rss: t.rss + p.memoryRssBytes,
|
|
1204
|
+
count: t.count + 1
|
|
1102
1205
|
});
|
|
1206
|
+
}
|
|
1207
|
+
const points = [];
|
|
1208
|
+
for (const [scope, t] of byRunner) {
|
|
1209
|
+
if (t.splitKnown) {
|
|
1210
|
+
points.push(point(RUNNER_CPU_MAIN_KEY, scope, round1(t.main)));
|
|
1211
|
+
points.push(point(RUNNER_CPU_GC_KEY, scope, round1(t.gc)));
|
|
1212
|
+
}
|
|
1213
|
+
points.push(point(RUNNER_CPU_LIFETIME_KEY, scope, round1(t.lifetime)));
|
|
1214
|
+
points.push(point(RUNNER_RSS_KEY, scope, Math.round(t.rss / MIB)));
|
|
1215
|
+
points.push(point(RUNNER_PROCESSES_KEY, scope, t.count));
|
|
1216
|
+
}
|
|
1217
|
+
if (containerMemory !== null) points.push(point(NODE_CONTAINER_CURRENT_KEY, "", Math.round(containerMemory.currentBytes / MIB)));
|
|
1218
|
+
await this.write(nodeId, atMs, points);
|
|
1219
|
+
}
|
|
1220
|
+
/** One resources snapshot: the node's totals, at most every {@link NODE_TOTALS_MIN_INTERVAL_MS}. */
|
|
1221
|
+
async recordTotals(nodeId, atMs, snapshot) {
|
|
1222
|
+
const last = this.lastTotalsAt.get(nodeId);
|
|
1223
|
+
if (last !== void 0 && atMs >= last && atMs - last < 15e3) return;
|
|
1224
|
+
this.lastTotalsAt.set(nodeId, atMs);
|
|
1225
|
+
const subject = {
|
|
1226
|
+
kind: "node",
|
|
1227
|
+
nodeId
|
|
1228
|
+
};
|
|
1229
|
+
const points = [];
|
|
1230
|
+
const add = (key, value) => {
|
|
1231
|
+
if (value === null || !Number.isFinite(value)) return;
|
|
1103
1232
|
points.push({
|
|
1104
|
-
key
|
|
1105
|
-
subject
|
|
1106
|
-
|
|
1107
|
-
nodeId
|
|
1108
|
-
},
|
|
1109
|
-
scope,
|
|
1233
|
+
key,
|
|
1234
|
+
subject,
|
|
1235
|
+
scope: "",
|
|
1110
1236
|
ts: atMs,
|
|
1111
|
-
value:
|
|
1237
|
+
value: round1(value)
|
|
1112
1238
|
});
|
|
1113
|
-
}
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
value: Math.round(containerMemory.currentBytes / 1048576)
|
|
1123
|
-
});
|
|
1239
|
+
};
|
|
1240
|
+
add(NODE_CPU_KEY, snapshot.cpu.total);
|
|
1241
|
+
add(NODE_MEMORY_KEY, snapshot.memory.percent);
|
|
1242
|
+
add(NODE_CPU_TEMPERATURE_KEY, snapshot.cpuTemperature);
|
|
1243
|
+
add(NODE_GPU_KEY, snapshot.gpu?.utilization ?? null);
|
|
1244
|
+
add(NODE_GPU_TEMPERATURE_KEY, snapshot.gpu?.temperature ?? null);
|
|
1245
|
+
await this.write(nodeId, atMs, points);
|
|
1246
|
+
}
|
|
1247
|
+
async write(nodeId, atMs, points) {
|
|
1124
1248
|
if (points.length === 0) return;
|
|
1249
|
+
if (!await this.ensureDeclared()) return;
|
|
1125
1250
|
try {
|
|
1126
1251
|
const result = await this.deps.deviceHistory.record({ points });
|
|
1127
1252
|
if (result.refused.length > 0) {
|
|
@@ -1143,7 +1268,7 @@ var NodeMetricsHistoryRecorder = class {
|
|
|
1143
1268
|
async readContainerPoints(nodeId, sinceMs, maxPoints) {
|
|
1144
1269
|
if (!await this.ensureDeclared()) return [];
|
|
1145
1270
|
const result = await this.deps.deviceHistory.queryNode({
|
|
1146
|
-
nodeId,
|
|
1271
|
+
forNodeId: nodeId,
|
|
1147
1272
|
key: NODE_CONTAINER_CURRENT_KEY,
|
|
1148
1273
|
from: sinceMs + 1,
|
|
1149
1274
|
to: Date.now(),
|
|
@@ -1156,7 +1281,7 @@ var NodeMetricsHistoryRecorder = class {
|
|
|
1156
1281
|
out.push({
|
|
1157
1282
|
atMs: p.t,
|
|
1158
1283
|
source: "cgroup-v2",
|
|
1159
|
-
currentBytes: p.value *
|
|
1284
|
+
currentBytes: p.value * MIB,
|
|
1160
1285
|
limitBytes: null,
|
|
1161
1286
|
anonBytes: null,
|
|
1162
1287
|
fileBytes: null,
|
|
@@ -1167,63 +1292,46 @@ var NodeMetricsHistoryRecorder = class {
|
|
|
1167
1292
|
}
|
|
1168
1293
|
return out.toSorted((a, b) => a.atMs - b.atMs);
|
|
1169
1294
|
}
|
|
1295
|
+
/**
|
|
1296
|
+
* The cold tier as process samples the fold reads like the hot ring's. A
|
|
1297
|
+
* runner's sums come back as `processes` equal rows (sums preserved, count
|
|
1298
|
+
* right); its CPU split is `null` where it was not recorded.
|
|
1299
|
+
*/
|
|
1170
1300
|
async readProcessSamples(nodeId, sinceMs, maxPoints) {
|
|
1171
1301
|
if (!await this.ensureDeclared()) return [];
|
|
1172
1302
|
const to = Date.now();
|
|
1173
|
-
const
|
|
1174
|
-
nodeId,
|
|
1175
|
-
key
|
|
1303
|
+
const read = (key) => this.deps.deviceHistory.queryNode({
|
|
1304
|
+
forNodeId: nodeId,
|
|
1305
|
+
key,
|
|
1176
1306
|
from: sinceMs + 1,
|
|
1177
1307
|
to,
|
|
1178
1308
|
resolution: "raw",
|
|
1179
1309
|
maxPoints
|
|
1180
|
-
})
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
let perPid = byAt.get(p.t);
|
|
1196
|
-
if (perPid === void 0) {
|
|
1197
|
-
perPid = /* @__PURE__ */ new Map();
|
|
1198
|
-
byAt.set(p.t, perPid);
|
|
1199
|
-
}
|
|
1200
|
-
const base = perPid.get(pid) ?? {
|
|
1201
|
-
pid,
|
|
1202
|
-
addonId: null,
|
|
1203
|
-
classification: "managed",
|
|
1204
|
-
cpuPercent: 0,
|
|
1205
|
-
memoryRssBytes: 0,
|
|
1206
|
-
cpuMainPercent: null,
|
|
1207
|
-
cpuGcPercent: null
|
|
1208
|
-
};
|
|
1209
|
-
perPid.set(pid, field === "cpuPercent" ? {
|
|
1210
|
-
...base,
|
|
1211
|
-
cpuPercent: p.value
|
|
1212
|
-
} : {
|
|
1213
|
-
...base,
|
|
1214
|
-
memoryRssBytes: p.value * 1048576
|
|
1215
|
-
});
|
|
1216
|
-
}
|
|
1217
|
-
}
|
|
1218
|
-
};
|
|
1219
|
-
ingest(cpuResult.series, "cpuPercent");
|
|
1220
|
-
ingest(rssResult.series, "memoryRssBytes");
|
|
1221
|
-
return [...byAt.entries()].toSorted((a, b) => a[0] - b[0]).map(([atMs, perPid]) => ({
|
|
1222
|
-
atMs,
|
|
1223
|
-
processes: [...perPid.values()]
|
|
1224
|
-
}));
|
|
1310
|
+
});
|
|
1311
|
+
const [main, gc, lifetime, rss, count] = await Promise.all([
|
|
1312
|
+
read(RUNNER_CPU_MAIN_KEY),
|
|
1313
|
+
read(RUNNER_CPU_GC_KEY),
|
|
1314
|
+
read(RUNNER_CPU_LIFETIME_KEY),
|
|
1315
|
+
read(RUNNER_RSS_KEY),
|
|
1316
|
+
read(RUNNER_PROCESSES_KEY)
|
|
1317
|
+
]);
|
|
1318
|
+
return assembleRunnerSamples({
|
|
1319
|
+
main,
|
|
1320
|
+
gc,
|
|
1321
|
+
lifetime,
|
|
1322
|
+
rss,
|
|
1323
|
+
count
|
|
1324
|
+
});
|
|
1225
1325
|
}
|
|
1226
1326
|
async ensureDeclared() {
|
|
1327
|
+
if (this.deps.historyReady !== void 0 && !this.deps.historyReady()) {
|
|
1328
|
+
if (!this.waitLogged) {
|
|
1329
|
+
this.waitLogged = true;
|
|
1330
|
+
this.deps.logger.info("node metrics history waits for device-history — samples until it is ready are not stored");
|
|
1331
|
+
}
|
|
1332
|
+
return false;
|
|
1333
|
+
}
|
|
1334
|
+
this.waitLogged = false;
|
|
1227
1335
|
try {
|
|
1228
1336
|
await this.declare();
|
|
1229
1337
|
return true;
|
|
@@ -1233,6 +1341,55 @@ var NodeMetricsHistoryRecorder = class {
|
|
|
1233
1341
|
}
|
|
1234
1342
|
}
|
|
1235
1343
|
};
|
|
1344
|
+
/** `atMs -> scope -> value` of one key's answer, finite values only. */
|
|
1345
|
+
function indexAnswer(answer) {
|
|
1346
|
+
const out = /* @__PURE__ */ new Map();
|
|
1347
|
+
for (const s of answer.series) for (const p of s.points) {
|
|
1348
|
+
if (p.value === null || !Number.isFinite(p.value)) continue;
|
|
1349
|
+
const at = out.get(p.t) ?? /* @__PURE__ */ new Map();
|
|
1350
|
+
at.set(s.scope, p.value);
|
|
1351
|
+
out.set(p.t, at);
|
|
1352
|
+
}
|
|
1353
|
+
return out;
|
|
1354
|
+
}
|
|
1355
|
+
/**
|
|
1356
|
+
* Per-runner cold points back into process rows. A sample exists where the
|
|
1357
|
+
* runner's lifetime CPU and RSS were both recorded (always written together).
|
|
1358
|
+
*/
|
|
1359
|
+
function assembleRunnerSamples(answers) {
|
|
1360
|
+
const main = indexAnswer(answers.main);
|
|
1361
|
+
const gc = indexAnswer(answers.gc);
|
|
1362
|
+
const rss = indexAnswer(answers.rss);
|
|
1363
|
+
const count = indexAnswer(answers.count);
|
|
1364
|
+
const samples = [];
|
|
1365
|
+
for (const [atMs, lifetimeByScope] of indexAnswer(answers.lifetime)) {
|
|
1366
|
+
const processes = [];
|
|
1367
|
+
for (const [scope, lifetime] of lifetimeByScope) {
|
|
1368
|
+
const rssMib = rss.get(atMs)?.get(scope);
|
|
1369
|
+
if (rssMib === void 0) continue;
|
|
1370
|
+
const n = Math.max(1, Math.round(count.get(atMs)?.get(scope) ?? 1));
|
|
1371
|
+
const m = main.get(atMs)?.get(scope);
|
|
1372
|
+
const g = gc.get(atMs)?.get(scope);
|
|
1373
|
+
const split = m !== void 0 && g !== void 0;
|
|
1374
|
+
const isRoot = scope === require_dist.ROOT_BUCKET_KEY;
|
|
1375
|
+
const isUnattributed = scope === require_dist.UNATTRIBUTED_BUCKET_KEY;
|
|
1376
|
+
for (let i = 0; i < n; i += 1) processes.push({
|
|
1377
|
+
pid: 0,
|
|
1378
|
+
addonId: isRoot || isUnattributed ? null : scope,
|
|
1379
|
+
classification: isRoot ? "root" : isUnattributed ? "system" : "managed",
|
|
1380
|
+
cpuPercent: lifetime / n,
|
|
1381
|
+
memoryRssBytes: rssMib * MIB / n,
|
|
1382
|
+
cpuMainPercent: split ? m / n : null,
|
|
1383
|
+
cpuGcPercent: split ? g / n : null
|
|
1384
|
+
});
|
|
1385
|
+
}
|
|
1386
|
+
if (processes.length > 0) samples.push({
|
|
1387
|
+
atMs,
|
|
1388
|
+
processes
|
|
1389
|
+
});
|
|
1390
|
+
}
|
|
1391
|
+
return samples.toSorted((a, b) => a.atMs - b.atMs);
|
|
1392
|
+
}
|
|
1236
1393
|
//#endregion
|
|
1237
1394
|
//#region src/builtins/native-metrics/gpu-probe.ts
|
|
1238
1395
|
/**
|
|
@@ -2196,6 +2353,8 @@ var ThreadCpuTracker = class {
|
|
|
2196
2353
|
};
|
|
2197
2354
|
//#endregion
|
|
2198
2355
|
//#region src/builtins/native-metrics/native-metrics.addon.ts
|
|
2356
|
+
/** The hub's node id — `isHub` below is the same test; device-history lives there. */
|
|
2357
|
+
var HUB_NODE_ID = "hub";
|
|
2199
2358
|
/**
|
|
2200
2359
|
* Cadence for the per-node metric snapshot bus events. ~5 s matches
|
|
2201
2360
|
* the existing UI polling cadence (ProcessesTab, ProcessResources)
|
|
@@ -2317,7 +2476,7 @@ var NativeMetricsAddon = class NativeMetricsAddon extends require_dist.BaseAddon
|
|
|
2317
2476
|
}
|
|
2318
2477
|
/** Is this the hub? The same test every other addon uses (`addon-ai`). */
|
|
2319
2478
|
get isHub() {
|
|
2320
|
-
return (this.ctx.kernel.cluster?.broker?.nodeID ??
|
|
2479
|
+
return (this.ctx.kernel.cluster?.broker?.nodeID ?? HUB_NODE_ID) === HUB_NODE_ID;
|
|
2321
2480
|
}
|
|
2322
2481
|
/** Process rows observed across the whole fleet, for the cost projection. */
|
|
2323
2482
|
observedFleetRows() {
|
|
@@ -2368,19 +2527,38 @@ var NativeMetricsAddon = class NativeMetricsAddon extends require_dist.BaseAddon
|
|
|
2368
2527
|
};
|
|
2369
2528
|
this.applyLoadSeriesConfig();
|
|
2370
2529
|
if (this.isHub) {
|
|
2371
|
-
|
|
2530
|
+
const historyScope = {
|
|
2531
|
+
type: "node",
|
|
2532
|
+
nodeId: HUB_NODE_ID
|
|
2533
|
+
};
|
|
2534
|
+
const historyHandle = this.ctx.useCapability("device-history", historyScope);
|
|
2535
|
+
const recorder = new NodeMetricsHistoryRecorder({
|
|
2372
2536
|
deviceHistory: nodeMetricsHistoryClient(this.ctx.api.deviceHistory),
|
|
2373
|
-
logger: this.ctx.logger.child("NodeMetricsHistory")
|
|
2374
|
-
|
|
2375
|
-
this.metricsHistory.declare().catch((err) => {
|
|
2376
|
-
this.ctx.logger.warn("node metrics history declare failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
2537
|
+
logger: this.ctx.logger.child("NodeMetricsHistory"),
|
|
2538
|
+
historyReady: () => historyHandle.isReady
|
|
2377
2539
|
});
|
|
2540
|
+
this.metricsHistory = recorder;
|
|
2541
|
+
const declareNow = () => {
|
|
2542
|
+
recorder.declare().catch((err) => {
|
|
2543
|
+
this.ctx.logger.warn("node metrics history declare failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
2544
|
+
});
|
|
2545
|
+
};
|
|
2546
|
+
this.ctx.addDisposer(this.ctx.onCapabilityStateChange("device-history", historyScope, (state) => {
|
|
2547
|
+
if (state === "ready") declareNow();
|
|
2548
|
+
}));
|
|
2549
|
+
if (historyHandle.isReady) declareNow();
|
|
2378
2550
|
}
|
|
2379
2551
|
this.memoryProbe = new ContainerMemoryProbe({ logger: this.ctx.logger.child("ContainerMemory") });
|
|
2380
2552
|
this.pidsProbe = new ContainerPidsProbe({ logger: this.ctx.logger.child("ContainerPids") });
|
|
2381
2553
|
if (this.snapshotTimer) clearInterval(this.snapshotTimer);
|
|
2382
2554
|
this.snapshotTimer = setInterval(() => this.runTick("resources snapshot", () => this.emitResourcesSnapshot()), METRICS_SNAPSHOT_INTERVAL_MS);
|
|
2383
2555
|
this.startProcessSnapshotTimer();
|
|
2556
|
+
if (this.metricsHistory !== null) {
|
|
2557
|
+
const history = this.metricsHistory;
|
|
2558
|
+
this.ctx.addDisposer(this.ctx.eventBus.subscribe({ category: require_dist.EventCategory.MetricsNodeResourcesSnapshot }, (event) => {
|
|
2559
|
+
history.recordTotals(event.data.nodeId, event.data.timestamp, event.data.snapshot);
|
|
2560
|
+
}));
|
|
2561
|
+
}
|
|
2384
2562
|
this.ctx.addDisposer(this.ctx.eventBus.subscribe({ category: require_dist.EventCategory.MetricsNodeProcessesSnapshot }, (event) => this.retainSnapshot(event.data.nodeId, event.data.timestamp, event.data.processes, event.data.containerMemory)));
|
|
2385
2563
|
return [{
|
|
2386
2564
|
capability: require_dist.metricsProviderCapability,
|