camstack 1.2.57 → 1.2.59
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.
|
@@ -23633,9 +23633,9 @@ var require_zod = __commonJS({
|
|
|
23633
23633
|
}
|
|
23634
23634
|
});
|
|
23635
23635
|
|
|
23636
|
-
// ../system/dist/dist-
|
|
23637
|
-
var
|
|
23638
|
-
"../system/dist/dist-
|
|
23636
|
+
// ../system/dist/dist-C7uZ_fOb.js
|
|
23637
|
+
var require_dist_C7uZ_fOb = __commonJS({
|
|
23638
|
+
"../system/dist/dist-C7uZ_fOb.js"(exports) {
|
|
23639
23639
|
"use strict";
|
|
23640
23640
|
var zod = require_zod();
|
|
23641
23641
|
var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
|
|
@@ -32718,6 +32718,38 @@ var require_dist_CImxMt5h = __commonJS({
|
|
|
32718
32718
|
/** Wall-clock uptime (seconds). Parsed from `ps etime`. */
|
|
32719
32719
|
uptimeSec: zod.z.number()
|
|
32720
32720
|
});
|
|
32721
|
+
var ContainerMemoryPointSchema = zod.z.object({
|
|
32722
|
+
/** Which hierarchy answered, so a reading is never ambiguous. */
|
|
32723
|
+
source: zod.z.enum(["cgroup-v2", "cgroup-v1"]),
|
|
32724
|
+
/** `memory.current` (v2) / `memory.usage_in_bytes` (v1). Always known. */
|
|
32725
|
+
currentBytes: zod.z.number(),
|
|
32726
|
+
/** The cgroup's ceiling. `null` = NO LIMIT — never a sentinel, never zero. */
|
|
32727
|
+
limitBytes: zod.z.number().nullable(),
|
|
32728
|
+
/** Anonymous pages: the closest thing to "what the processes allocated". */
|
|
32729
|
+
anonBytes: zod.z.number().nullable(),
|
|
32730
|
+
/** Page cache. Charged to the cgroup, owned by no process. */
|
|
32731
|
+
fileBytes: zod.z.number().nullable(),
|
|
32732
|
+
/**
|
|
32733
|
+
* Shared memory — and the field that explained the largest single surprise.
|
|
32734
|
+
* The i915 driver backs GPU buffers with shmem, so an inference pool or a
|
|
32735
|
+
* hardware-decode session holding DRM objects is charged HERE and appears
|
|
32736
|
+
* nowhere in a `ps` scan.
|
|
32737
|
+
*/
|
|
32738
|
+
shmemBytes: zod.z.number().nullable(),
|
|
32739
|
+
/** Kernel slab charged to this cgroup. `null` on v1, which never publishes it. */
|
|
32740
|
+
slabBytes: zod.z.number().nullable(),
|
|
32741
|
+
/**
|
|
32742
|
+
* Shrinkable i915 GEM object bytes, from debugfs.
|
|
32743
|
+
*
|
|
32744
|
+
* **Host-wide across every DRM client, NOT cgroup-scoped.** It is not a
|
|
32745
|
+
* component of `currentBytes` and must not be subtracted from it; it says
|
|
32746
|
+
* what put the shmem there, where `shmemBytes` only says how much.
|
|
32747
|
+
*
|
|
32748
|
+
* `null` wherever debugfs is not mounted — which is inside every camstack
|
|
32749
|
+
* container today — and on any node with no Intel GPU.
|
|
32750
|
+
*/
|
|
32751
|
+
gpuShmemBytes: zod.z.number().nullable()
|
|
32752
|
+
}).extend({ atMs: zod.z.number() });
|
|
32721
32753
|
var DumpHeapSnapshotInputSchema = zod.z.object({
|
|
32722
32754
|
/** The addon whose runner should dump a heap snapshot. */
|
|
32723
32755
|
addonId: zod.z.string()
|
|
@@ -32767,6 +32799,21 @@ var require_dist_CImxMt5h = __commonJS({
|
|
|
32767
32799
|
/** One entry per function seen in the window, heaviest-first. */
|
|
32768
32800
|
series: zod.z.array(LoadFunctionSeriesSchema).readonly(),
|
|
32769
32801
|
/**
|
|
32802
|
+
* The CONTAINER's memory over the same window, oldest-first.
|
|
32803
|
+
*
|
|
32804
|
+
* Sits next to `series` rather than in a method of its own because the whole
|
|
32805
|
+
* question is a subtraction: the per-process rows in `series` sum to one
|
|
32806
|
+
* number and this one is another, and an operator who has to issue two calls
|
|
32807
|
+
* to compare them will compare two different instants. Same reader, same
|
|
32808
|
+
* `sinceMs`, same `bucketMs`, same timestamps.
|
|
32809
|
+
*
|
|
32810
|
+
* **EMPTY means ABSENT, never zero.** A node with no cgroup — a developer
|
|
32811
|
+
* Mac, a bare-metal host, a container with the hierarchy hidden — reports no
|
|
32812
|
+
* points at all. A zero here would be indistinguishable from a healthy
|
|
32813
|
+
* container and is precisely the lie this field exists to avoid.
|
|
32814
|
+
*/
|
|
32815
|
+
containerMemory: zod.z.array(ContainerMemoryPointSchema).readonly(),
|
|
32816
|
+
/**
|
|
32770
32817
|
* Width of one returned bucket, in ms. Equals the sampling cadence when no
|
|
32771
32818
|
* reduction was needed — so a caller can always say what one point covers
|
|
32772
32819
|
* without having to know whether it was reduced.
|
|
@@ -58639,7 +58686,7 @@ var require_alerts_addon = __commonJS({
|
|
|
58639
58686
|
[Symbol.toStringTag]: { value: "Module" }
|
|
58640
58687
|
});
|
|
58641
58688
|
require_chunk_Cek0wNdY();
|
|
58642
|
-
var require_dist10 =
|
|
58689
|
+
var require_dist10 = require_dist_C7uZ_fOb();
|
|
58643
58690
|
function selectExpired(alerts, cutoffMs) {
|
|
58644
58691
|
return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
|
|
58645
58692
|
}
|
|
@@ -59458,7 +59505,7 @@ var require_console_logging = __commonJS({
|
|
|
59458
59505
|
[Symbol.toStringTag]: { value: "Module" }
|
|
59459
59506
|
});
|
|
59460
59507
|
require_chunk_Cek0wNdY();
|
|
59461
|
-
var require_dist10 =
|
|
59508
|
+
var require_dist10 = require_dist_C7uZ_fOb();
|
|
59462
59509
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
59463
59510
|
var LEVEL_RANK = {
|
|
59464
59511
|
debug: 0,
|
|
@@ -59552,7 +59599,7 @@ var require_core_blocks_addon = __commonJS({
|
|
|
59552
59599
|
"use strict";
|
|
59553
59600
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
59554
59601
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
59555
|
-
var require_dist10 =
|
|
59602
|
+
var require_dist10 = require_dist_C7uZ_fOb();
|
|
59556
59603
|
var node_crypto = __require("crypto");
|
|
59557
59604
|
var node_fs_promises = __require("fs/promises");
|
|
59558
59605
|
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
@@ -60449,11 +60496,11 @@ var require_core_blocks = __commonJS({
|
|
|
60449
60496
|
}
|
|
60450
60497
|
});
|
|
60451
60498
|
|
|
60452
|
-
// ../system/dist/retired-settings-keys-
|
|
60453
|
-
var
|
|
60454
|
-
"../system/dist/retired-settings-keys-
|
|
60499
|
+
// ../system/dist/retired-settings-keys-CBU4-TJO.js
|
|
60500
|
+
var require_retired_settings_keys_CBU4_TJO = __commonJS({
|
|
60501
|
+
"../system/dist/retired-settings-keys-CBU4-TJO.js"(exports) {
|
|
60455
60502
|
"use strict";
|
|
60456
|
-
var require_dist10 =
|
|
60503
|
+
var require_dist10 = require_dist_C7uZ_fOb();
|
|
60457
60504
|
function settingsStoreIsAuthoritativeHere(env) {
|
|
60458
60505
|
const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
|
|
60459
60506
|
return raw === "" || raw === "hub";
|
|
@@ -62667,8 +62714,8 @@ var require_device_manager_addon = __commonJS({
|
|
|
62667
62714
|
[Symbol.toStringTag]: { value: "Module" }
|
|
62668
62715
|
});
|
|
62669
62716
|
require_chunk_Cek0wNdY();
|
|
62670
|
-
var require_dist10 =
|
|
62671
|
-
var require_retired_settings_keys =
|
|
62717
|
+
var require_dist10 = require_dist_C7uZ_fOb();
|
|
62718
|
+
var require_retired_settings_keys = require_retired_settings_keys_CBU4_TJO();
|
|
62672
62719
|
var node_crypto = __require("crypto");
|
|
62673
62720
|
var _camstack_types_node = require_node();
|
|
62674
62721
|
var JOB_HISTORY = 20;
|
|
@@ -67417,7 +67464,7 @@ var require_hub_forwarder = __commonJS({
|
|
|
67417
67464
|
[Symbol.toStringTag]: { value: "Module" }
|
|
67418
67465
|
});
|
|
67419
67466
|
require_chunk_Cek0wNdY();
|
|
67420
|
-
var require_dist10 =
|
|
67467
|
+
var require_dist10 = require_dist_C7uZ_fOb();
|
|
67421
67468
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
67422
67469
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
67423
67470
|
var HubForwarderDestination = class {
|
|
@@ -67554,7 +67601,7 @@ var require_liveness_monitor_addon = __commonJS({
|
|
|
67554
67601
|
"use strict";
|
|
67555
67602
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
67556
67603
|
require_chunk_Cek0wNdY();
|
|
67557
|
-
var require_dist10 =
|
|
67604
|
+
var require_dist10 = require_dist_C7uZ_fOb();
|
|
67558
67605
|
var NO_DEVICES = "liveness:no-devices";
|
|
67559
67606
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
67560
67607
|
var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
|
|
@@ -67744,7 +67791,7 @@ var require_local_auth_addon = __commonJS({
|
|
|
67744
67791
|
[Symbol.toStringTag]: { value: "Module" }
|
|
67745
67792
|
});
|
|
67746
67793
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
67747
|
-
var require_dist10 =
|
|
67794
|
+
var require_dist10 = require_dist_C7uZ_fOb();
|
|
67748
67795
|
var node_crypto = __require("crypto");
|
|
67749
67796
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
67750
67797
|
var crypto$1 = __require("crypto");
|
|
@@ -75557,7 +75604,7 @@ var require_loki_logging = __commonJS({
|
|
|
75557
75604
|
[Symbol.toStringTag]: { value: "Module" }
|
|
75558
75605
|
});
|
|
75559
75606
|
require_chunk_Cek0wNdY();
|
|
75560
|
-
var require_dist10 =
|
|
75607
|
+
var require_dist10 = require_dist_C7uZ_fOb();
|
|
75561
75608
|
function sanitizeLabelName(raw) {
|
|
75562
75609
|
const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
|
|
75563
75610
|
return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
|
|
@@ -76122,14 +76169,859 @@ var require_native_metrics_addon = __commonJS({
|
|
|
76122
76169
|
[Symbol.toStringTag]: { value: "Module" }
|
|
76123
76170
|
});
|
|
76124
76171
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
76125
|
-
var require_dist10 =
|
|
76172
|
+
var require_dist10 = require_dist_C7uZ_fOb();
|
|
76126
76173
|
var node_fs_promises = __require("fs/promises");
|
|
76127
76174
|
var node_child_process = __require("child_process");
|
|
76128
76175
|
var node_util = __require("util");
|
|
76129
|
-
var node_os = __require("os");
|
|
76130
|
-
node_os = require_chunk.__toESM(node_os);
|
|
76131
76176
|
var node_fs = __require("fs");
|
|
76132
76177
|
node_fs = require_chunk.__toESM(node_fs);
|
|
76178
|
+
var node_os = __require("os");
|
|
76179
|
+
node_os = require_chunk.__toESM(node_os);
|
|
76180
|
+
var nodeCgroupFileReader = { read(path) {
|
|
76181
|
+
try {
|
|
76182
|
+
return (0, node_fs.readFileSync)(path, "utf8");
|
|
76183
|
+
} catch {
|
|
76184
|
+
return null;
|
|
76185
|
+
}
|
|
76186
|
+
} };
|
|
76187
|
+
var CGROUP_MOUNT_ROOT = "/sys/fs/cgroup";
|
|
76188
|
+
var I915_GEM_OBJECTS_PATH = "/sys/kernel/debug/dri/0/i915_gem_objects";
|
|
76189
|
+
var V1_UNLIMITED_SENTINEL = 9223372036854772e3;
|
|
76190
|
+
function parseCgroupSelf(text) {
|
|
76191
|
+
let v1 = null;
|
|
76192
|
+
for (const rawLine of text.split("\n")) {
|
|
76193
|
+
const line = rawLine.trim();
|
|
76194
|
+
if (line.length === 0) continue;
|
|
76195
|
+
const first = line.indexOf(":");
|
|
76196
|
+
if (first < 0) continue;
|
|
76197
|
+
const second = line.indexOf(":", first + 1);
|
|
76198
|
+
if (second < 0) continue;
|
|
76199
|
+
const controllers = line.slice(first + 1, second);
|
|
76200
|
+
const path = line.slice(second + 1);
|
|
76201
|
+
if (path.length === 0) continue;
|
|
76202
|
+
const normalized = path.startsWith("/") ? path : `/${path}`;
|
|
76203
|
+
if (controllers.length === 0) return {
|
|
76204
|
+
version: "v2",
|
|
76205
|
+
path: normalized
|
|
76206
|
+
};
|
|
76207
|
+
if (v1 === null && controllers.split(",").includes("memory")) v1 = {
|
|
76208
|
+
version: "v1",
|
|
76209
|
+
path: normalized
|
|
76210
|
+
};
|
|
76211
|
+
}
|
|
76212
|
+
return v1;
|
|
76213
|
+
}
|
|
76214
|
+
function parseCgroupStat(text) {
|
|
76215
|
+
const out = /* @__PURE__ */ new Map();
|
|
76216
|
+
for (const rawLine of text.split("\n")) {
|
|
76217
|
+
const line = rawLine.trim();
|
|
76218
|
+
if (line.length === 0) continue;
|
|
76219
|
+
const space = line.indexOf(" ");
|
|
76220
|
+
if (space <= 0) continue;
|
|
76221
|
+
const key = line.slice(0, space);
|
|
76222
|
+
const value = Number(line.slice(space + 1).trim());
|
|
76223
|
+
if (!Number.isFinite(value)) continue;
|
|
76224
|
+
out.set(key, value);
|
|
76225
|
+
}
|
|
76226
|
+
return out;
|
|
76227
|
+
}
|
|
76228
|
+
function parseCgroupScalar(text) {
|
|
76229
|
+
const trimmed = text.trim();
|
|
76230
|
+
if (trimmed.length === 0) return null;
|
|
76231
|
+
if (trimmed === "max") return null;
|
|
76232
|
+
const value = Number(trimmed);
|
|
76233
|
+
if (!Number.isFinite(value) || value < 0) return null;
|
|
76234
|
+
if (value >= V1_UNLIMITED_SENTINEL) return null;
|
|
76235
|
+
return value;
|
|
76236
|
+
}
|
|
76237
|
+
function parseI915GemObjects(text) {
|
|
76238
|
+
const match = text.match(/^\s*\d+\s+shrinkable\b[^,\n]*,\s*(\d+)\s+bytes/m);
|
|
76239
|
+
if (match === null) return null;
|
|
76240
|
+
const bytes = Number(match[1]);
|
|
76241
|
+
return Number.isFinite(bytes) ? bytes : null;
|
|
76242
|
+
}
|
|
76243
|
+
function resolveCgroupMemoryLayout(fs) {
|
|
76244
|
+
const selfText = fs.read("/proc/self/cgroup");
|
|
76245
|
+
if (selfText === null) return null;
|
|
76246
|
+
const entry = parseCgroupSelf(selfText);
|
|
76247
|
+
if (entry === null) return null;
|
|
76248
|
+
const suffix = entry.path === "/" ? "" : entry.path;
|
|
76249
|
+
const candidates = entry.version === "v2" ? [`${CGROUP_MOUNT_ROOT}${suffix}`, CGROUP_MOUNT_ROOT] : [`${CGROUP_MOUNT_ROOT}/memory${suffix}`, `${CGROUP_MOUNT_ROOT}/memory`];
|
|
76250
|
+
const usageFile = entry.version === "v2" ? "memory.current" : "memory.usage_in_bytes";
|
|
76251
|
+
const limitFile = entry.version === "v2" ? "memory.max" : "memory.limit_in_bytes";
|
|
76252
|
+
for (const directory of candidates) {
|
|
76253
|
+
if (fs.read(`${directory}/${usageFile}`) === null) continue;
|
|
76254
|
+
return {
|
|
76255
|
+
source: entry.version === "v2" ? "cgroup-v2" : "cgroup-v1",
|
|
76256
|
+
directory,
|
|
76257
|
+
currentPath: `${directory}/${usageFile}`,
|
|
76258
|
+
limitPath: `${directory}/${limitFile}`,
|
|
76259
|
+
statPath: `${directory}/memory.stat`
|
|
76260
|
+
};
|
|
76261
|
+
}
|
|
76262
|
+
return null;
|
|
76263
|
+
}
|
|
76264
|
+
function statValue(stat, key) {
|
|
76265
|
+
const value = stat.get(key);
|
|
76266
|
+
return value === void 0 ? null : value;
|
|
76267
|
+
}
|
|
76268
|
+
function resolveSlab(stat) {
|
|
76269
|
+
const direct = statValue(stat, "slab");
|
|
76270
|
+
if (direct !== null) return direct;
|
|
76271
|
+
const reclaimable = stat.get("slab_reclaimable");
|
|
76272
|
+
const unreclaimable = stat.get("slab_unreclaimable");
|
|
76273
|
+
if (reclaimable === void 0 || unreclaimable === void 0) return null;
|
|
76274
|
+
return reclaimable + unreclaimable;
|
|
76275
|
+
}
|
|
76276
|
+
function buildContainerMemorySnapshot(input) {
|
|
76277
|
+
const currentBytes = parseCgroupScalar(input.currentText);
|
|
76278
|
+
if (currentBytes === null) return null;
|
|
76279
|
+
const stat = input.statText === null ? /* @__PURE__ */ new Map() : parseCgroupStat(input.statText);
|
|
76280
|
+
const isV2 = input.source === "cgroup-v2";
|
|
76281
|
+
return {
|
|
76282
|
+
source: input.source,
|
|
76283
|
+
currentBytes,
|
|
76284
|
+
limitBytes: input.limitText === null ? null : parseCgroupScalar(input.limitText),
|
|
76285
|
+
anonBytes: statValue(stat, isV2 ? "anon" : "rss"),
|
|
76286
|
+
fileBytes: statValue(stat, isV2 ? "file" : "cache"),
|
|
76287
|
+
shmemBytes: statValue(stat, "shmem"),
|
|
76288
|
+
slabBytes: isV2 ? resolveSlab(stat) : null,
|
|
76289
|
+
gpuShmemBytes: input.gpuShmemBytes
|
|
76290
|
+
};
|
|
76291
|
+
}
|
|
76292
|
+
var ContainerMemoryProbe = class {
|
|
76293
|
+
logger;
|
|
76294
|
+
fs;
|
|
76295
|
+
wantGpu;
|
|
76296
|
+
resolved = false;
|
|
76297
|
+
layout = null;
|
|
76298
|
+
gpuProbed = false;
|
|
76299
|
+
gpuReadable = false;
|
|
76300
|
+
/** `null` until the first sample — so the FIRST outcome is a transition too. */
|
|
76301
|
+
lastReadOk = null;
|
|
76302
|
+
constructor(deps) {
|
|
76303
|
+
this.logger = deps.logger;
|
|
76304
|
+
this.fs = deps.fs ?? nodeCgroupFileReader;
|
|
76305
|
+
this.wantGpu = deps.readGpu ?? true;
|
|
76306
|
+
}
|
|
76307
|
+
/** Did this node resolve a cgroup at all? Absent is a reportable fact. */
|
|
76308
|
+
get available() {
|
|
76309
|
+
return this.layout !== null;
|
|
76310
|
+
}
|
|
76311
|
+
/**
|
|
76312
|
+
* One reading, or `null` when this node has no cgroup or the cgroup stopped
|
|
76313
|
+
* answering. `null` is ABSENT — the caller contributes no point, and no
|
|
76314
|
+
* point is what a chart must show, never a zero.
|
|
76315
|
+
*/
|
|
76316
|
+
sample() {
|
|
76317
|
+
const layout = this.resolveOnce();
|
|
76318
|
+
if (layout === null) return null;
|
|
76319
|
+
const currentText = this.fs.read(layout.currentPath);
|
|
76320
|
+
if (currentText === null) {
|
|
76321
|
+
this.noteRead(false, `unreadable: ${layout.currentPath}`);
|
|
76322
|
+
return null;
|
|
76323
|
+
}
|
|
76324
|
+
const snapshot = buildContainerMemorySnapshot({
|
|
76325
|
+
source: layout.source,
|
|
76326
|
+
currentText,
|
|
76327
|
+
limitText: this.fs.read(layout.limitPath),
|
|
76328
|
+
statText: this.fs.read(layout.statPath),
|
|
76329
|
+
gpuShmemBytes: this.readGpuShmem()
|
|
76330
|
+
});
|
|
76331
|
+
if (snapshot === null) {
|
|
76332
|
+
this.noteRead(false, `unparseable: ${layout.currentPath}`);
|
|
76333
|
+
return null;
|
|
76334
|
+
}
|
|
76335
|
+
this.noteRead(true, null);
|
|
76336
|
+
return snapshot;
|
|
76337
|
+
}
|
|
76338
|
+
/** Resolve on first use and never again — a cgroup does not move under a pid. */
|
|
76339
|
+
resolveOnce() {
|
|
76340
|
+
if (this.resolved) return this.layout;
|
|
76341
|
+
this.resolved = true;
|
|
76342
|
+
try {
|
|
76343
|
+
this.layout = resolveCgroupMemoryLayout(this.fs);
|
|
76344
|
+
} catch (err) {
|
|
76345
|
+
this.layout = null;
|
|
76346
|
+
this.logger.warn("cgroup memory resolution failed \u2014 container memory will be ABSENT", { meta: { error: require_dist10.errMsg(err) } });
|
|
76347
|
+
return null;
|
|
76348
|
+
}
|
|
76349
|
+
if (this.layout === null) {
|
|
76350
|
+
this.logger.info("no cgroup on this node \u2014 container memory is ABSENT, not zero, for every sample", { meta: {
|
|
76351
|
+
platform: process.platform,
|
|
76352
|
+
probed: "/proc/self/cgroup"
|
|
76353
|
+
} });
|
|
76354
|
+
return null;
|
|
76355
|
+
}
|
|
76356
|
+
this.logger.info("container memory resolved from the cgroup", { meta: {
|
|
76357
|
+
source: this.layout.source,
|
|
76358
|
+
directory: this.layout.directory
|
|
76359
|
+
} });
|
|
76360
|
+
return this.layout;
|
|
76361
|
+
}
|
|
76362
|
+
/**
|
|
76363
|
+
* The GPU number, probed once.
|
|
76364
|
+
*
|
|
76365
|
+
* It is host-wide and lives in debugfs, so it is absent far more often than
|
|
76366
|
+
* it is present — inside every camstack container today. One `open` decides
|
|
76367
|
+
* it for the life of the process; after that an unreadable file costs
|
|
76368
|
+
* nothing at all, not even a syscall.
|
|
76369
|
+
*/
|
|
76370
|
+
readGpuShmem() {
|
|
76371
|
+
if (!this.wantGpu) return null;
|
|
76372
|
+
if (!this.gpuProbed) {
|
|
76373
|
+
this.gpuProbed = true;
|
|
76374
|
+
const text2 = this.fs.read(I915_GEM_OBJECTS_PATH);
|
|
76375
|
+
this.gpuReadable = text2 !== null && parseI915GemObjects(text2) !== null;
|
|
76376
|
+
this.logger.info(this.gpuReadable ? "i915 GEM accounting is readable \u2014 GPU-backed shmem will be reported" : "i915 GEM accounting is NOT readable \u2014 gpuShmemBytes stays UNKNOWN (this is normal: debugfs is not mounted in the container, and a node with no Intel GPU has no such file)", { meta: { path: I915_GEM_OBJECTS_PATH } });
|
|
76377
|
+
if (!this.gpuReadable) return null;
|
|
76378
|
+
return text2 === null ? null : parseI915GemObjects(text2);
|
|
76379
|
+
}
|
|
76380
|
+
if (!this.gpuReadable) return null;
|
|
76381
|
+
const text = this.fs.read(I915_GEM_OBJECTS_PATH);
|
|
76382
|
+
return text === null ? null : parseI915GemObjects(text);
|
|
76383
|
+
}
|
|
76384
|
+
/** Log a read outcome only when it CHANGES. Never once per tick. */
|
|
76385
|
+
noteRead(ok, reason) {
|
|
76386
|
+
if (this.lastReadOk === ok) return;
|
|
76387
|
+
const first = this.lastReadOk === null;
|
|
76388
|
+
this.lastReadOk = ok;
|
|
76389
|
+
if (!ok) {
|
|
76390
|
+
this.logger.warn("cgroup memory stopped answering \u2014 container memory is ABSENT until it returns", { meta: { reason: reason ?? "unknown" } });
|
|
76391
|
+
return;
|
|
76392
|
+
}
|
|
76393
|
+
if (!first) this.logger.info("cgroup memory is answering again");
|
|
76394
|
+
}
|
|
76395
|
+
};
|
|
76396
|
+
var LoadPartition = class {
|
|
76397
|
+
capacity;
|
|
76398
|
+
slots;
|
|
76399
|
+
head = 0;
|
|
76400
|
+
count = 0;
|
|
76401
|
+
rows = 0;
|
|
76402
|
+
/** Newest retained sample's timestamp — the monotonic gate for `push`. */
|
|
76403
|
+
newestAtMs = null;
|
|
76404
|
+
constructor(capacity) {
|
|
76405
|
+
this.capacity = capacity;
|
|
76406
|
+
this.slots = Array.from({ length: capacity });
|
|
76407
|
+
}
|
|
76408
|
+
/**
|
|
76409
|
+
* Accept a sample.
|
|
76410
|
+
*
|
|
76411
|
+
* A sample at or before the newest one already held is REFUSED. The bus drops
|
|
76412
|
+
* a node's own broadcast echo, but a cross-node redelivery or a replayed
|
|
76413
|
+
* subscription must not be able to double a point — and idempotence here is
|
|
76414
|
+
* what lets every reader above treat the series as a set.
|
|
76415
|
+
*
|
|
76416
|
+
* `accepted` is reported separately from `rowDelta` on purpose: a full ring
|
|
76417
|
+
* that evicts a sample of the same size has a delta of zero and is not a
|
|
76418
|
+
* refusal, and conflating the two would silently stop advancing the write
|
|
76419
|
+
* ordinal on a steady-state cluster.
|
|
76420
|
+
*/
|
|
76421
|
+
push(sample) {
|
|
76422
|
+
if (this.newestAtMs !== null && sample.atMs <= this.newestAtMs) return {
|
|
76423
|
+
accepted: false,
|
|
76424
|
+
rowDelta: 0
|
|
76425
|
+
};
|
|
76426
|
+
const evicted = this.count === this.capacity ? this.slots[this.head]?.processes.length ?? 0 : 0;
|
|
76427
|
+
this.slots[this.head] = sample;
|
|
76428
|
+
this.head = (this.head + 1) % this.capacity;
|
|
76429
|
+
if (this.count < this.capacity) this.count++;
|
|
76430
|
+
this.newestAtMs = sample.atMs;
|
|
76431
|
+
const rowDelta = sample.processes.length - evicted;
|
|
76432
|
+
this.rows += rowDelta;
|
|
76433
|
+
return {
|
|
76434
|
+
accepted: true,
|
|
76435
|
+
rowDelta
|
|
76436
|
+
};
|
|
76437
|
+
}
|
|
76438
|
+
/** Drop the oldest sample. Returns the rows reclaimed (0 when empty). */
|
|
76439
|
+
dropOldest() {
|
|
76440
|
+
if (this.count === 0) return 0;
|
|
76441
|
+
const index = (this.head - this.count + this.capacity) % this.capacity;
|
|
76442
|
+
const victim = this.slots[index];
|
|
76443
|
+
this.slots[index] = void 0;
|
|
76444
|
+
this.count--;
|
|
76445
|
+
const reclaimed = victim?.processes.length ?? 0;
|
|
76446
|
+
this.rows -= reclaimed;
|
|
76447
|
+
if (this.count === 0) this.newestAtMs = null;
|
|
76448
|
+
return reclaimed;
|
|
76449
|
+
}
|
|
76450
|
+
/** Oldest-first, optionally only what is strictly newer than `sinceMs`. */
|
|
76451
|
+
list(sinceMs) {
|
|
76452
|
+
const out = [];
|
|
76453
|
+
for (let i = 0; i < this.count; i++) {
|
|
76454
|
+
const index = (this.head - this.count + i + this.capacity) % this.capacity;
|
|
76455
|
+
const sample = this.slots[index];
|
|
76456
|
+
if (sample === void 0) continue;
|
|
76457
|
+
if (sinceMs !== void 0 && sample.atMs <= sinceMs) continue;
|
|
76458
|
+
out.push(sample);
|
|
76459
|
+
}
|
|
76460
|
+
return out;
|
|
76461
|
+
}
|
|
76462
|
+
size() {
|
|
76463
|
+
return this.count;
|
|
76464
|
+
}
|
|
76465
|
+
rowCount() {
|
|
76466
|
+
return this.rows;
|
|
76467
|
+
}
|
|
76468
|
+
oldestAtMs() {
|
|
76469
|
+
if (this.count === 0) return null;
|
|
76470
|
+
const index = (this.head - this.count + this.capacity) % this.capacity;
|
|
76471
|
+
return this.slots[index]?.atMs ?? null;
|
|
76472
|
+
}
|
|
76473
|
+
lastWriteAtMs() {
|
|
76474
|
+
return this.newestAtMs;
|
|
76475
|
+
}
|
|
76476
|
+
};
|
|
76477
|
+
var NodeLoadRing = class {
|
|
76478
|
+
partitions = /* @__PURE__ */ new Map();
|
|
76479
|
+
/**
|
|
76480
|
+
* Node id → write ordinal of its last accepted sample. A monotonic counter,
|
|
76481
|
+
* not a clock: partition eviction must follow the order writes actually
|
|
76482
|
+
* happened, and node clocks disagree.
|
|
76483
|
+
*/
|
|
76484
|
+
lastWriteSeq = /* @__PURE__ */ new Map();
|
|
76485
|
+
writeSeq = 0;
|
|
76486
|
+
totalRows = 0;
|
|
76487
|
+
samplesPerNode;
|
|
76488
|
+
maxTotalProcessRows;
|
|
76489
|
+
maxNodes;
|
|
76490
|
+
idleEvictionMs;
|
|
76491
|
+
now;
|
|
76492
|
+
constructor(options = {}) {
|
|
76493
|
+
this.samplesPerNode = options.samplesPerNode ?? 180;
|
|
76494
|
+
this.maxTotalProcessRows = options.maxTotalProcessRows ?? 32e3;
|
|
76495
|
+
this.maxNodes = options.maxNodes ?? 16;
|
|
76496
|
+
this.idleEvictionMs = options.idleEvictionMs ?? 36e5;
|
|
76497
|
+
this.now = options.now ?? Date.now;
|
|
76498
|
+
}
|
|
76499
|
+
/**
|
|
76500
|
+
* Retain one snapshot. `processes` is stored by reference — the payload is
|
|
76501
|
+
* already an immutable arrival off the bus, and copying it would double the
|
|
76502
|
+
* measured cost for nothing.
|
|
76503
|
+
*
|
|
76504
|
+
* Returns whether the sample was ACCEPTED — that is, whether it was new
|
|
76505
|
+
* rather than a replay of a timestamp this node has already delivered.
|
|
76506
|
+
*
|
|
76507
|
+
* The return value is not diagnostics. It is the idempotence gate the
|
|
76508
|
+
* DURABLE tier rides on (`load-series-store.ts`): only an accepted sample is
|
|
76509
|
+
* appended to the table, which is what lets that table carry an `INTEGER`
|
|
76510
|
+
* rowid key instead of a composite unique index over two million rows. The
|
|
76511
|
+
* gate is one monotonic comparison in memory; the index it replaces was
|
|
76512
|
+
* measured at ~40 bytes per row.
|
|
76513
|
+
*/
|
|
76514
|
+
record(nodeId, atMs, processes) {
|
|
76515
|
+
if (nodeId.length === 0) return false;
|
|
76516
|
+
this.sweepIdle();
|
|
76517
|
+
let partition = this.partitions.get(nodeId);
|
|
76518
|
+
if (partition === void 0) {
|
|
76519
|
+
partition = new LoadPartition(this.samplesPerNode);
|
|
76520
|
+
this.partitions.set(nodeId, partition);
|
|
76521
|
+
}
|
|
76522
|
+
const outcome = partition.push({
|
|
76523
|
+
atMs,
|
|
76524
|
+
processes
|
|
76525
|
+
});
|
|
76526
|
+
if (!outcome.accepted) {
|
|
76527
|
+
if (partition.size() === 0) this.partitions.delete(nodeId);
|
|
76528
|
+
return false;
|
|
76529
|
+
}
|
|
76530
|
+
this.totalRows += outcome.rowDelta;
|
|
76531
|
+
this.lastWriteSeq.set(nodeId, ++this.writeSeq);
|
|
76532
|
+
if (this.partitions.size > this.maxNodes) this.evictPartitions(this.partitions.size - this.maxNodes, nodeId);
|
|
76533
|
+
this.enforceRowBudget();
|
|
76534
|
+
return true;
|
|
76535
|
+
}
|
|
76536
|
+
/**
|
|
76537
|
+
* Read one node's retained series, oldest-first.
|
|
76538
|
+
*
|
|
76539
|
+
* `sinceMs` is EXCLUSIVE: a caller passes the newest timestamp it already
|
|
76540
|
+
* holds and gets back only what it is missing. That is the whole contract
|
|
76541
|
+
* that lets the admin UI seed from here and then continue live without
|
|
76542
|
+
* doubling a point it already drew.
|
|
76543
|
+
*
|
|
76544
|
+
* A node nobody has recorded answers with an empty series, not an error —
|
|
76545
|
+
* unknown is the truth about a node that has not reported.
|
|
76546
|
+
*/
|
|
76547
|
+
read(nodeId, sinceMs) {
|
|
76548
|
+
this.sweepIdle();
|
|
76549
|
+
const partition = this.partitions.get(nodeId);
|
|
76550
|
+
if (partition === void 0) return {
|
|
76551
|
+
nodeId,
|
|
76552
|
+
samples: [],
|
|
76553
|
+
retainedSamples: 0,
|
|
76554
|
+
oldestAtMs: null,
|
|
76555
|
+
capacity: this.samplesPerNode
|
|
76556
|
+
};
|
|
76557
|
+
return {
|
|
76558
|
+
nodeId,
|
|
76559
|
+
samples: partition.list(sinceMs),
|
|
76560
|
+
retainedSamples: partition.size(),
|
|
76561
|
+
oldestAtMs: partition.oldestAtMs(),
|
|
76562
|
+
capacity: this.samplesPerNode
|
|
76563
|
+
};
|
|
76564
|
+
}
|
|
76565
|
+
/** Node ids with a live partition. Observability for the fleet bound. */
|
|
76566
|
+
nodeIds() {
|
|
76567
|
+
return [...this.partitions.keys()];
|
|
76568
|
+
}
|
|
76569
|
+
/** Process rows retained across every partition — the number that IS memory. */
|
|
76570
|
+
rowCount() {
|
|
76571
|
+
return this.totalRows;
|
|
76572
|
+
}
|
|
76573
|
+
/** Samples retained across every partition. */
|
|
76574
|
+
sampleCount() {
|
|
76575
|
+
let total = 0;
|
|
76576
|
+
for (const partition of this.partitions.values()) total += partition.size();
|
|
76577
|
+
return total;
|
|
76578
|
+
}
|
|
76579
|
+
/**
|
|
76580
|
+
* Drop partitions whose newest sample is older than the retention window.
|
|
76581
|
+
*
|
|
76582
|
+
* Lazy, on write and on read — never a timer. A timer would be a new
|
|
76583
|
+
* periodic cost in a subsystem whose entire premise is that it adds none,
|
|
76584
|
+
* and a ring that nobody writes to and nobody reads is not growing either.
|
|
76585
|
+
*/
|
|
76586
|
+
sweepIdle() {
|
|
76587
|
+
const cutoff = this.now() - this.idleEvictionMs;
|
|
76588
|
+
for (const [nodeId, partition] of [...this.partitions.entries()]) {
|
|
76589
|
+
const lastWrite = partition.lastWriteAtMs();
|
|
76590
|
+
if (lastWrite !== null && lastWrite > cutoff) continue;
|
|
76591
|
+
this.dropPartition(nodeId);
|
|
76592
|
+
}
|
|
76593
|
+
}
|
|
76594
|
+
/**
|
|
76595
|
+
* Bring the fleet back under the row budget by dropping the OLDEST sample of
|
|
76596
|
+
* the HEAVIEST partition, repeatedly.
|
|
76597
|
+
*
|
|
76598
|
+
* Terminates: every iteration removes one sample from a non-empty partition,
|
|
76599
|
+
* and the population of samples is finite and strictly decreasing.
|
|
76600
|
+
*/
|
|
76601
|
+
enforceRowBudget() {
|
|
76602
|
+
while (this.totalRows > this.maxTotalProcessRows) {
|
|
76603
|
+
const victim = this.heaviestPartition();
|
|
76604
|
+
if (victim === null) return;
|
|
76605
|
+
const [nodeId, partition] = victim;
|
|
76606
|
+
this.totalRows -= partition.dropOldest();
|
|
76607
|
+
if (partition.size() === 0) this.dropPartition(nodeId);
|
|
76608
|
+
}
|
|
76609
|
+
}
|
|
76610
|
+
heaviestPartition() {
|
|
76611
|
+
let best = null;
|
|
76612
|
+
for (const entry of this.partitions.entries()) {
|
|
76613
|
+
if (entry[1].size() === 0) continue;
|
|
76614
|
+
if (best === null || entry[1].rowCount() > best[1].rowCount()) best = entry;
|
|
76615
|
+
}
|
|
76616
|
+
return best;
|
|
76617
|
+
}
|
|
76618
|
+
/** Drop `count` whole partitions, least-recently-written first. */
|
|
76619
|
+
evictPartitions(count, protectedNodeId) {
|
|
76620
|
+
const order = [...this.partitions.keys()].filter((nodeId) => nodeId !== protectedNodeId).toSorted((a, b) => (this.lastWriteSeq.get(a) ?? 0) - (this.lastWriteSeq.get(b) ?? 0));
|
|
76621
|
+
let remaining = count;
|
|
76622
|
+
for (const nodeId of order) {
|
|
76623
|
+
if (remaining <= 0) return;
|
|
76624
|
+
this.dropPartition(nodeId);
|
|
76625
|
+
remaining -= 1;
|
|
76626
|
+
}
|
|
76627
|
+
}
|
|
76628
|
+
/** Remove a partition and everything that indexes it. */
|
|
76629
|
+
dropPartition(nodeId) {
|
|
76630
|
+
const partition = this.partitions.get(nodeId);
|
|
76631
|
+
if (partition === void 0) return;
|
|
76632
|
+
this.totalRows -= partition.rowCount();
|
|
76633
|
+
this.partitions.delete(nodeId);
|
|
76634
|
+
this.lastWriteSeq.delete(nodeId);
|
|
76635
|
+
}
|
|
76636
|
+
};
|
|
76637
|
+
var CONTAINER_MEMORY_COLLECTION = "metrics:node-memory-samples";
|
|
76638
|
+
var CONTAINER_MEMORY_MAX_TOTAL_ROWS = 2880;
|
|
76639
|
+
var CONTAINER_MEMORY_MAX_ROWS = 5e4;
|
|
76640
|
+
var CONTAINER_MEMORY_COLUMNS = [
|
|
76641
|
+
{
|
|
76642
|
+
name: "id",
|
|
76643
|
+
type: "INTEGER",
|
|
76644
|
+
primaryKey: true,
|
|
76645
|
+
notNull: true
|
|
76646
|
+
},
|
|
76647
|
+
{
|
|
76648
|
+
name: "nodeId",
|
|
76649
|
+
type: "TEXT",
|
|
76650
|
+
notNull: true
|
|
76651
|
+
},
|
|
76652
|
+
/** Shared with the process rows of the same tick — that is the whole point. */
|
|
76653
|
+
{
|
|
76654
|
+
name: "atMs",
|
|
76655
|
+
type: "INTEGER",
|
|
76656
|
+
notNull: true
|
|
76657
|
+
},
|
|
76658
|
+
{
|
|
76659
|
+
name: "source",
|
|
76660
|
+
type: "TEXT",
|
|
76661
|
+
notNull: true
|
|
76662
|
+
},
|
|
76663
|
+
/**
|
|
76664
|
+
* Whole MiB, like `rssMib` on the process row and for the same reason: a
|
|
76665
|
+
* byte-exact residency on a value in the tens of gigabytes is precision no
|
|
76666
|
+
* chart can draw, and it costs bytes on every row forever.
|
|
76667
|
+
*/
|
|
76668
|
+
{
|
|
76669
|
+
name: "currentMib",
|
|
76670
|
+
type: "INTEGER",
|
|
76671
|
+
notNull: true
|
|
76672
|
+
},
|
|
76673
|
+
/** `NULL` = NO LIMIT. Never a sentinel. */
|
|
76674
|
+
{
|
|
76675
|
+
name: "limitMib",
|
|
76676
|
+
type: "INTEGER"
|
|
76677
|
+
},
|
|
76678
|
+
/** `NULL` = UNKNOWN on all four. Never zero. */
|
|
76679
|
+
{
|
|
76680
|
+
name: "anonMib",
|
|
76681
|
+
type: "INTEGER"
|
|
76682
|
+
},
|
|
76683
|
+
{
|
|
76684
|
+
name: "fileMib",
|
|
76685
|
+
type: "INTEGER"
|
|
76686
|
+
},
|
|
76687
|
+
{
|
|
76688
|
+
name: "shmemMib",
|
|
76689
|
+
type: "INTEGER"
|
|
76690
|
+
},
|
|
76691
|
+
{
|
|
76692
|
+
name: "slabMib",
|
|
76693
|
+
type: "INTEGER"
|
|
76694
|
+
},
|
|
76695
|
+
/** Host-wide i915 GEM bytes. `NULL` wherever debugfs is not mounted. */
|
|
76696
|
+
{
|
|
76697
|
+
name: "gpuShmemMib",
|
|
76698
|
+
type: "INTEGER"
|
|
76699
|
+
}
|
|
76700
|
+
];
|
|
76701
|
+
var CONTAINER_MEMORY_INDEXES = [
|
|
76702
|
+
/** The one index, and it serves both the read and the prune — see the
|
|
76703
|
+
* process table's `idx_load_samples_node_at` for the full reasoning. */
|
|
76704
|
+
{
|
|
76705
|
+
name: "idx_node_memory_node_at",
|
|
76706
|
+
columns: ["nodeId", "atMs"]
|
|
76707
|
+
}
|
|
76708
|
+
];
|
|
76709
|
+
var BYTES_PER_MIB$1 = 1048576;
|
|
76710
|
+
function toMib(value) {
|
|
76711
|
+
return value === null ? null : Math.round(value / BYTES_PER_MIB$1);
|
|
76712
|
+
}
|
|
76713
|
+
function fromMib(value) {
|
|
76714
|
+
return value === null ? null : value * BYTES_PER_MIB$1;
|
|
76715
|
+
}
|
|
76716
|
+
function snapshotToRow(nodeId, atMs, snapshot) {
|
|
76717
|
+
return {
|
|
76718
|
+
nodeId,
|
|
76719
|
+
atMs,
|
|
76720
|
+
source: snapshot.source,
|
|
76721
|
+
currentMib: Math.round(snapshot.currentBytes / BYTES_PER_MIB$1),
|
|
76722
|
+
limitMib: toMib(snapshot.limitBytes),
|
|
76723
|
+
anonMib: toMib(snapshot.anonBytes),
|
|
76724
|
+
fileMib: toMib(snapshot.fileBytes),
|
|
76725
|
+
shmemMib: toMib(snapshot.shmemBytes),
|
|
76726
|
+
slabMib: toMib(snapshot.slabBytes),
|
|
76727
|
+
gpuShmemMib: toMib(snapshot.gpuShmemBytes)
|
|
76728
|
+
};
|
|
76729
|
+
}
|
|
76730
|
+
function rowToPoint(row) {
|
|
76731
|
+
if (row.source !== "cgroup-v2" && row.source !== "cgroup-v1") return null;
|
|
76732
|
+
return {
|
|
76733
|
+
atMs: row.atMs,
|
|
76734
|
+
source: row.source,
|
|
76735
|
+
currentBytes: row.currentMib * BYTES_PER_MIB$1,
|
|
76736
|
+
limitBytes: fromMib(row.limitMib),
|
|
76737
|
+
anonBytes: fromMib(row.anonMib),
|
|
76738
|
+
fileBytes: fromMib(row.fileMib),
|
|
76739
|
+
shmemBytes: fromMib(row.shmemMib),
|
|
76740
|
+
slabBytes: fromMib(row.slabMib),
|
|
76741
|
+
gpuShmemBytes: fromMib(row.gpuShmemMib)
|
|
76742
|
+
};
|
|
76743
|
+
}
|
|
76744
|
+
function recordToMemoryRow(data) {
|
|
76745
|
+
const nodeId = data["nodeId"];
|
|
76746
|
+
const source = data["source"];
|
|
76747
|
+
if (typeof nodeId !== "string" || typeof source !== "string") return null;
|
|
76748
|
+
const atMs = Number(data["atMs"]);
|
|
76749
|
+
const currentMib = Number(data["currentMib"]);
|
|
76750
|
+
if (!Number.isFinite(atMs) || !Number.isFinite(currentMib)) return null;
|
|
76751
|
+
const optional = (raw) => {
|
|
76752
|
+
if (raw === null || raw === void 0) return null;
|
|
76753
|
+
const n = Number(raw);
|
|
76754
|
+
return Number.isFinite(n) ? n : null;
|
|
76755
|
+
};
|
|
76756
|
+
return {
|
|
76757
|
+
nodeId,
|
|
76758
|
+
atMs,
|
|
76759
|
+
source,
|
|
76760
|
+
currentMib,
|
|
76761
|
+
limitMib: optional(data["limitMib"]),
|
|
76762
|
+
anonMib: optional(data["anonMib"]),
|
|
76763
|
+
fileMib: optional(data["fileMib"]),
|
|
76764
|
+
shmemMib: optional(data["shmemMib"]),
|
|
76765
|
+
slabMib: optional(data["slabMib"]),
|
|
76766
|
+
gpuShmemMib: optional(data["gpuShmemMib"])
|
|
76767
|
+
};
|
|
76768
|
+
}
|
|
76769
|
+
var ContainerMemoryRing = class {
|
|
76770
|
+
ring;
|
|
76771
|
+
constructor(options = {}) {
|
|
76772
|
+
this.ring = new NodeLoadRing({
|
|
76773
|
+
samplesPerNode: options.samplesPerNode ?? 180,
|
|
76774
|
+
maxTotalProcessRows: CONTAINER_MEMORY_MAX_TOTAL_ROWS,
|
|
76775
|
+
...options.now !== void 0 ? { now: options.now } : {}
|
|
76776
|
+
});
|
|
76777
|
+
}
|
|
76778
|
+
/** Retain one reading. `false` = a timestamp this node already delivered. */
|
|
76779
|
+
record(nodeId, atMs, snapshot) {
|
|
76780
|
+
return this.ring.record(nodeId, atMs, [snapshot]);
|
|
76781
|
+
}
|
|
76782
|
+
/**
|
|
76783
|
+
* Read one node's retained readings, oldest-first. `sinceMs` is EXCLUSIVE,
|
|
76784
|
+
* matching every other reader in this subsystem.
|
|
76785
|
+
*
|
|
76786
|
+
* A node nobody has recorded answers EMPTY — which is what "this node has no
|
|
76787
|
+
* cgroup" looks like, and it must stay distinguishable from a zero.
|
|
76788
|
+
*/
|
|
76789
|
+
read(nodeId, sinceMs) {
|
|
76790
|
+
const series = this.ring.read(nodeId, sinceMs);
|
|
76791
|
+
const out = [];
|
|
76792
|
+
for (const sample of series.samples) {
|
|
76793
|
+
const snapshot = sample.processes[0];
|
|
76794
|
+
if (snapshot === void 0) continue;
|
|
76795
|
+
out.push({
|
|
76796
|
+
...snapshot,
|
|
76797
|
+
atMs: sample.atMs
|
|
76798
|
+
});
|
|
76799
|
+
}
|
|
76800
|
+
return out;
|
|
76801
|
+
}
|
|
76802
|
+
};
|
|
76803
|
+
function reduceContainerMemory(points, bucketMs, origin) {
|
|
76804
|
+
if (bucketMs <= 0 || points.length === 0) return points;
|
|
76805
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
76806
|
+
for (const point of points) {
|
|
76807
|
+
const start = origin + Math.floor((point.atMs - origin) / bucketMs) * bucketMs;
|
|
76808
|
+
const held = buckets.get(start);
|
|
76809
|
+
if (held === void 0 || point.currentBytes > held.currentBytes) buckets.set(start, {
|
|
76810
|
+
...point,
|
|
76811
|
+
atMs: start
|
|
76812
|
+
});
|
|
76813
|
+
}
|
|
76814
|
+
return [...buckets.values()].toSorted((a, b) => a.atMs - b.atMs);
|
|
76815
|
+
}
|
|
76816
|
+
function mergeContainerMemory(cold, hot) {
|
|
76817
|
+
const byAt = /* @__PURE__ */ new Map();
|
|
76818
|
+
for (const point of cold) byAt.set(point.atMs, point);
|
|
76819
|
+
for (const point of hot) byAt.set(point.atMs, point);
|
|
76820
|
+
return [...byAt.values()].toSorted((a, b) => a.atMs - b.atMs);
|
|
76821
|
+
}
|
|
76822
|
+
var ContainerMemoryStore = class {
|
|
76823
|
+
declared = false;
|
|
76824
|
+
store;
|
|
76825
|
+
logger;
|
|
76826
|
+
nowFn;
|
|
76827
|
+
prunePageRows;
|
|
76828
|
+
constructor(deps) {
|
|
76829
|
+
this.store = deps.store;
|
|
76830
|
+
this.logger = deps.logger;
|
|
76831
|
+
this.nowFn = deps.now ?? (() => Date.now());
|
|
76832
|
+
this.prunePageRows = deps.prunePageRows ?? 2e4;
|
|
76833
|
+
}
|
|
76834
|
+
/** Idempotently declare the collection. `false` when the store refused. */
|
|
76835
|
+
async declare() {
|
|
76836
|
+
if (this.declared) return true;
|
|
76837
|
+
try {
|
|
76838
|
+
await this.store.declareCollection.mutate({
|
|
76839
|
+
collection: CONTAINER_MEMORY_COLLECTION,
|
|
76840
|
+
columns: [...CONTAINER_MEMORY_COLUMNS],
|
|
76841
|
+
indexes: CONTAINER_MEMORY_INDEXES.map((i) => ({
|
|
76842
|
+
name: i.name,
|
|
76843
|
+
columns: [...i.columns]
|
|
76844
|
+
}))
|
|
76845
|
+
});
|
|
76846
|
+
this.declared = true;
|
|
76847
|
+
return true;
|
|
76848
|
+
} catch (err) {
|
|
76849
|
+
this.logger.warn("container memory declareCollection failed \u2014 nothing will be retained on disk", { meta: {
|
|
76850
|
+
collection: CONTAINER_MEMORY_COLLECTION,
|
|
76851
|
+
error: require_dist10.errMsg(err)
|
|
76852
|
+
} });
|
|
76853
|
+
return false;
|
|
76854
|
+
}
|
|
76855
|
+
}
|
|
76856
|
+
/** Append ONE reading. */
|
|
76857
|
+
async append(nodeId, atMs, snapshot) {
|
|
76858
|
+
if (!await this.declare()) return 0;
|
|
76859
|
+
const record = { ...snapshotToRow(nodeId, atMs, snapshot) };
|
|
76860
|
+
try {
|
|
76861
|
+
const { inserted } = await this.store.insertMany.mutate({
|
|
76862
|
+
collection: CONTAINER_MEMORY_COLLECTION,
|
|
76863
|
+
records: [{ data: record }]
|
|
76864
|
+
});
|
|
76865
|
+
return inserted;
|
|
76866
|
+
} catch (err) {
|
|
76867
|
+
this.logger.warn("container memory reading not retained \u2014 this interval will be missing", { meta: {
|
|
76868
|
+
nodeId,
|
|
76869
|
+
atMs,
|
|
76870
|
+
error: require_dist10.errMsg(err)
|
|
76871
|
+
} });
|
|
76872
|
+
return 0;
|
|
76873
|
+
}
|
|
76874
|
+
}
|
|
76875
|
+
/** Read one node's cold readings, oldest-first. `sinceMs` is EXCLUSIVE. */
|
|
76876
|
+
async read(nodeId, sinceMs, limitRows) {
|
|
76877
|
+
if (!await this.declare()) return [];
|
|
76878
|
+
try {
|
|
76879
|
+
const records = await this.store.query.query({
|
|
76880
|
+
collection: CONTAINER_MEMORY_COLLECTION,
|
|
76881
|
+
filter: {
|
|
76882
|
+
where: { nodeId },
|
|
76883
|
+
whereBetween: { atMs: [sinceMs + 1, Number.MAX_SAFE_INTEGER] },
|
|
76884
|
+
orderBy: {
|
|
76885
|
+
field: "atMs",
|
|
76886
|
+
direction: "asc"
|
|
76887
|
+
},
|
|
76888
|
+
limit: limitRows
|
|
76889
|
+
}
|
|
76890
|
+
});
|
|
76891
|
+
const points = [];
|
|
76892
|
+
for (const record of records) {
|
|
76893
|
+
const row = recordToMemoryRow(record.data);
|
|
76894
|
+
if (row === null) continue;
|
|
76895
|
+
const point = rowToPoint(row);
|
|
76896
|
+
if (point !== null) points.push(point);
|
|
76897
|
+
}
|
|
76898
|
+
return points;
|
|
76899
|
+
} catch (err) {
|
|
76900
|
+
this.logger.warn("container memory cold read failed \u2014 answering from the hot window only", { meta: {
|
|
76901
|
+
nodeId,
|
|
76902
|
+
sinceMs,
|
|
76903
|
+
error: require_dist10.errMsg(err)
|
|
76904
|
+
} });
|
|
76905
|
+
return [];
|
|
76906
|
+
}
|
|
76907
|
+
}
|
|
76908
|
+
/**
|
|
76909
|
+
* Enforce BOTH bounds, oldest-first, through a bounded page each.
|
|
76910
|
+
*
|
|
76911
|
+
* Not rate-limited here: it is driven by the process store's own prune
|
|
76912
|
+
* cadence, so it runs at most once a minute by construction and a second
|
|
76913
|
+
* timer would be a second thing to get wrong.
|
|
76914
|
+
*/
|
|
76915
|
+
async prune(nodeIds, retention) {
|
|
76916
|
+
if (!await this.declare()) return null;
|
|
76917
|
+
const ageCutoff = this.nowFn() - retention.retentionHours * 36e5;
|
|
76918
|
+
let deletedByAge = 0;
|
|
76919
|
+
let rowsExamined = 0;
|
|
76920
|
+
for (const nodeId of nodeIds) {
|
|
76921
|
+
const outcome = await this.deleteOldestPage(nodeId, ageCutoff, this.prunePageRows);
|
|
76922
|
+
deletedByAge += outcome.deleted;
|
|
76923
|
+
rowsExamined += outcome.examined;
|
|
76924
|
+
}
|
|
76925
|
+
const total = await this.count();
|
|
76926
|
+
const excess = total === null ? 0 : total - CONTAINER_MEMORY_MAX_ROWS;
|
|
76927
|
+
let deletedByCap = 0;
|
|
76928
|
+
if (excess > 0) {
|
|
76929
|
+
let remaining = Math.min(excess, this.prunePageRows);
|
|
76930
|
+
for (const nodeId of nodeIds) {
|
|
76931
|
+
if (remaining <= 0) break;
|
|
76932
|
+
const outcome = await this.deleteOldestPage(nodeId, null, remaining);
|
|
76933
|
+
deletedByCap += outcome.deleted;
|
|
76934
|
+
remaining -= outcome.deleted;
|
|
76935
|
+
rowsExamined += outcome.examined;
|
|
76936
|
+
}
|
|
76937
|
+
this.logger.warn("container memory ROW CAP bit \u2014 evicting the oldest readings", { meta: {
|
|
76938
|
+
collection: CONTAINER_MEMORY_COLLECTION,
|
|
76939
|
+
rows: total,
|
|
76940
|
+
cap: CONTAINER_MEMORY_MAX_ROWS,
|
|
76941
|
+
over: excess,
|
|
76942
|
+
deleted: deletedByCap,
|
|
76943
|
+
hint: "lower the retention or the sampling cadence \u2014 the cap is the guarantee, not the intention"
|
|
76944
|
+
} });
|
|
76945
|
+
}
|
|
76946
|
+
return {
|
|
76947
|
+
deletedByAge,
|
|
76948
|
+
deletedByCap,
|
|
76949
|
+
rowsExamined,
|
|
76950
|
+
capBit: excess > 0
|
|
76951
|
+
};
|
|
76952
|
+
}
|
|
76953
|
+
/** Total rows, or `null` when the store could not answer. */
|
|
76954
|
+
async count() {
|
|
76955
|
+
if (!await this.declare()) return null;
|
|
76956
|
+
try {
|
|
76957
|
+
return await this.store.count.query({ collection: CONTAINER_MEMORY_COLLECTION });
|
|
76958
|
+
} catch (err) {
|
|
76959
|
+
this.logger.warn("container memory count failed \u2014 the row cap is not enforced this pass", { meta: { error: require_dist10.errMsg(err) } });
|
|
76960
|
+
return null;
|
|
76961
|
+
}
|
|
76962
|
+
}
|
|
76963
|
+
/**
|
|
76964
|
+
* Delete this node's oldest rows, at most one page's worth.
|
|
76965
|
+
*
|
|
76966
|
+
* `cutoff === null` means "the oldest rows, whatever their age" — the
|
|
76967
|
+
* row-cap path, which is bounded by `limitRows` instead. Either way the page
|
|
76968
|
+
* is READ FIRST, ordered by the one index, and its last `atMs` becomes the
|
|
76969
|
+
* effective cutoff for a single bounded delete. An unbounded `deleteWhere`
|
|
76970
|
+
* would be one statement and one stalling transaction the first time a
|
|
76971
|
+
* retention is lowered.
|
|
76972
|
+
*/
|
|
76973
|
+
async deleteOldestPage(nodeId, cutoff, limitRows) {
|
|
76974
|
+
if (limitRows <= 0) return {
|
|
76975
|
+
deleted: 0,
|
|
76976
|
+
examined: 0
|
|
76977
|
+
};
|
|
76978
|
+
try {
|
|
76979
|
+
const page = await this.store.query.query({
|
|
76980
|
+
collection: CONTAINER_MEMORY_COLLECTION,
|
|
76981
|
+
filter: {
|
|
76982
|
+
where: { nodeId },
|
|
76983
|
+
...cutoff === null ? {} : { whereBetween: { atMs: [0, cutoff] } },
|
|
76984
|
+
orderBy: {
|
|
76985
|
+
field: "atMs",
|
|
76986
|
+
direction: "asc"
|
|
76987
|
+
},
|
|
76988
|
+
limit: Math.min(limitRows, this.prunePageRows)
|
|
76989
|
+
},
|
|
76990
|
+
columns: ["atMs"]
|
|
76991
|
+
});
|
|
76992
|
+
if (page.length === 0) return {
|
|
76993
|
+
deleted: 0,
|
|
76994
|
+
examined: 0
|
|
76995
|
+
};
|
|
76996
|
+
const effectiveCutoff = Number(page.at(-1)?.data["atMs"]);
|
|
76997
|
+
if (!Number.isFinite(effectiveCutoff)) return {
|
|
76998
|
+
deleted: 0,
|
|
76999
|
+
examined: page.length
|
|
77000
|
+
};
|
|
77001
|
+
const { deleted } = await this.store.deleteWhere.mutate({
|
|
77002
|
+
collection: CONTAINER_MEMORY_COLLECTION,
|
|
77003
|
+
filter: {
|
|
77004
|
+
where: { nodeId },
|
|
77005
|
+
whereBetween: { atMs: [0, effectiveCutoff] }
|
|
77006
|
+
}
|
|
77007
|
+
});
|
|
77008
|
+
return {
|
|
77009
|
+
deleted,
|
|
77010
|
+
examined: page.length
|
|
77011
|
+
};
|
|
77012
|
+
} catch (err) {
|
|
77013
|
+
this.logger.warn("container memory prune failed \u2014 the table keeps growing this pass", { meta: {
|
|
77014
|
+
nodeId,
|
|
77015
|
+
cutoff,
|
|
77016
|
+
error: require_dist10.errMsg(err)
|
|
77017
|
+
} });
|
|
77018
|
+
return {
|
|
77019
|
+
deleted: 0,
|
|
77020
|
+
examined: 0
|
|
77021
|
+
};
|
|
77022
|
+
}
|
|
77023
|
+
}
|
|
77024
|
+
};
|
|
76133
77025
|
var IS_DARWIN = node_os.platform() === "darwin";
|
|
76134
77026
|
var IS_LINUX = node_os.platform() === "linux";
|
|
76135
77027
|
var NativeMetricsProvider = class {
|
|
@@ -76594,247 +77486,6 @@ var require_native_metrics_addon = __commonJS({
|
|
|
76594
77486
|
});
|
|
76595
77487
|
});
|
|
76596
77488
|
}
|
|
76597
|
-
var LoadPartition = class {
|
|
76598
|
-
capacity;
|
|
76599
|
-
slots;
|
|
76600
|
-
head = 0;
|
|
76601
|
-
count = 0;
|
|
76602
|
-
rows = 0;
|
|
76603
|
-
/** Newest retained sample's timestamp — the monotonic gate for `push`. */
|
|
76604
|
-
newestAtMs = null;
|
|
76605
|
-
constructor(capacity) {
|
|
76606
|
-
this.capacity = capacity;
|
|
76607
|
-
this.slots = Array.from({ length: capacity });
|
|
76608
|
-
}
|
|
76609
|
-
/**
|
|
76610
|
-
* Accept a sample.
|
|
76611
|
-
*
|
|
76612
|
-
* A sample at or before the newest one already held is REFUSED. The bus drops
|
|
76613
|
-
* a node's own broadcast echo, but a cross-node redelivery or a replayed
|
|
76614
|
-
* subscription must not be able to double a point — and idempotence here is
|
|
76615
|
-
* what lets every reader above treat the series as a set.
|
|
76616
|
-
*
|
|
76617
|
-
* `accepted` is reported separately from `rowDelta` on purpose: a full ring
|
|
76618
|
-
* that evicts a sample of the same size has a delta of zero and is not a
|
|
76619
|
-
* refusal, and conflating the two would silently stop advancing the write
|
|
76620
|
-
* ordinal on a steady-state cluster.
|
|
76621
|
-
*/
|
|
76622
|
-
push(sample) {
|
|
76623
|
-
if (this.newestAtMs !== null && sample.atMs <= this.newestAtMs) return {
|
|
76624
|
-
accepted: false,
|
|
76625
|
-
rowDelta: 0
|
|
76626
|
-
};
|
|
76627
|
-
const evicted = this.count === this.capacity ? this.slots[this.head]?.processes.length ?? 0 : 0;
|
|
76628
|
-
this.slots[this.head] = sample;
|
|
76629
|
-
this.head = (this.head + 1) % this.capacity;
|
|
76630
|
-
if (this.count < this.capacity) this.count++;
|
|
76631
|
-
this.newestAtMs = sample.atMs;
|
|
76632
|
-
const rowDelta = sample.processes.length - evicted;
|
|
76633
|
-
this.rows += rowDelta;
|
|
76634
|
-
return {
|
|
76635
|
-
accepted: true,
|
|
76636
|
-
rowDelta
|
|
76637
|
-
};
|
|
76638
|
-
}
|
|
76639
|
-
/** Drop the oldest sample. Returns the rows reclaimed (0 when empty). */
|
|
76640
|
-
dropOldest() {
|
|
76641
|
-
if (this.count === 0) return 0;
|
|
76642
|
-
const index = (this.head - this.count + this.capacity) % this.capacity;
|
|
76643
|
-
const victim = this.slots[index];
|
|
76644
|
-
this.slots[index] = void 0;
|
|
76645
|
-
this.count--;
|
|
76646
|
-
const reclaimed = victim?.processes.length ?? 0;
|
|
76647
|
-
this.rows -= reclaimed;
|
|
76648
|
-
if (this.count === 0) this.newestAtMs = null;
|
|
76649
|
-
return reclaimed;
|
|
76650
|
-
}
|
|
76651
|
-
/** Oldest-first, optionally only what is strictly newer than `sinceMs`. */
|
|
76652
|
-
list(sinceMs) {
|
|
76653
|
-
const out = [];
|
|
76654
|
-
for (let i = 0; i < this.count; i++) {
|
|
76655
|
-
const index = (this.head - this.count + i + this.capacity) % this.capacity;
|
|
76656
|
-
const sample = this.slots[index];
|
|
76657
|
-
if (sample === void 0) continue;
|
|
76658
|
-
if (sinceMs !== void 0 && sample.atMs <= sinceMs) continue;
|
|
76659
|
-
out.push(sample);
|
|
76660
|
-
}
|
|
76661
|
-
return out;
|
|
76662
|
-
}
|
|
76663
|
-
size() {
|
|
76664
|
-
return this.count;
|
|
76665
|
-
}
|
|
76666
|
-
rowCount() {
|
|
76667
|
-
return this.rows;
|
|
76668
|
-
}
|
|
76669
|
-
oldestAtMs() {
|
|
76670
|
-
if (this.count === 0) return null;
|
|
76671
|
-
const index = (this.head - this.count + this.capacity) % this.capacity;
|
|
76672
|
-
return this.slots[index]?.atMs ?? null;
|
|
76673
|
-
}
|
|
76674
|
-
lastWriteAtMs() {
|
|
76675
|
-
return this.newestAtMs;
|
|
76676
|
-
}
|
|
76677
|
-
};
|
|
76678
|
-
var NodeLoadRing = class {
|
|
76679
|
-
partitions = /* @__PURE__ */ new Map();
|
|
76680
|
-
/**
|
|
76681
|
-
* Node id → write ordinal of its last accepted sample. A monotonic counter,
|
|
76682
|
-
* not a clock: partition eviction must follow the order writes actually
|
|
76683
|
-
* happened, and node clocks disagree.
|
|
76684
|
-
*/
|
|
76685
|
-
lastWriteSeq = /* @__PURE__ */ new Map();
|
|
76686
|
-
writeSeq = 0;
|
|
76687
|
-
totalRows = 0;
|
|
76688
|
-
samplesPerNode;
|
|
76689
|
-
maxTotalProcessRows;
|
|
76690
|
-
maxNodes;
|
|
76691
|
-
idleEvictionMs;
|
|
76692
|
-
now;
|
|
76693
|
-
constructor(options = {}) {
|
|
76694
|
-
this.samplesPerNode = options.samplesPerNode ?? 180;
|
|
76695
|
-
this.maxTotalProcessRows = options.maxTotalProcessRows ?? 32e3;
|
|
76696
|
-
this.maxNodes = options.maxNodes ?? 16;
|
|
76697
|
-
this.idleEvictionMs = options.idleEvictionMs ?? 36e5;
|
|
76698
|
-
this.now = options.now ?? Date.now;
|
|
76699
|
-
}
|
|
76700
|
-
/**
|
|
76701
|
-
* Retain one snapshot. `processes` is stored by reference — the payload is
|
|
76702
|
-
* already an immutable arrival off the bus, and copying it would double the
|
|
76703
|
-
* measured cost for nothing.
|
|
76704
|
-
*
|
|
76705
|
-
* Returns whether the sample was ACCEPTED — that is, whether it was new
|
|
76706
|
-
* rather than a replay of a timestamp this node has already delivered.
|
|
76707
|
-
*
|
|
76708
|
-
* The return value is not diagnostics. It is the idempotence gate the
|
|
76709
|
-
* DURABLE tier rides on (`load-series-store.ts`): only an accepted sample is
|
|
76710
|
-
* appended to the table, which is what lets that table carry an `INTEGER`
|
|
76711
|
-
* rowid key instead of a composite unique index over two million rows. The
|
|
76712
|
-
* gate is one monotonic comparison in memory; the index it replaces was
|
|
76713
|
-
* measured at ~40 bytes per row.
|
|
76714
|
-
*/
|
|
76715
|
-
record(nodeId, atMs, processes) {
|
|
76716
|
-
if (nodeId.length === 0) return false;
|
|
76717
|
-
this.sweepIdle();
|
|
76718
|
-
let partition = this.partitions.get(nodeId);
|
|
76719
|
-
if (partition === void 0) {
|
|
76720
|
-
partition = new LoadPartition(this.samplesPerNode);
|
|
76721
|
-
this.partitions.set(nodeId, partition);
|
|
76722
|
-
}
|
|
76723
|
-
const outcome = partition.push({
|
|
76724
|
-
atMs,
|
|
76725
|
-
processes
|
|
76726
|
-
});
|
|
76727
|
-
if (!outcome.accepted) {
|
|
76728
|
-
if (partition.size() === 0) this.partitions.delete(nodeId);
|
|
76729
|
-
return false;
|
|
76730
|
-
}
|
|
76731
|
-
this.totalRows += outcome.rowDelta;
|
|
76732
|
-
this.lastWriteSeq.set(nodeId, ++this.writeSeq);
|
|
76733
|
-
if (this.partitions.size > this.maxNodes) this.evictPartitions(this.partitions.size - this.maxNodes, nodeId);
|
|
76734
|
-
this.enforceRowBudget();
|
|
76735
|
-
return true;
|
|
76736
|
-
}
|
|
76737
|
-
/**
|
|
76738
|
-
* Read one node's retained series, oldest-first.
|
|
76739
|
-
*
|
|
76740
|
-
* `sinceMs` is EXCLUSIVE: a caller passes the newest timestamp it already
|
|
76741
|
-
* holds and gets back only what it is missing. That is the whole contract
|
|
76742
|
-
* that lets the admin UI seed from here and then continue live without
|
|
76743
|
-
* doubling a point it already drew.
|
|
76744
|
-
*
|
|
76745
|
-
* A node nobody has recorded answers with an empty series, not an error —
|
|
76746
|
-
* unknown is the truth about a node that has not reported.
|
|
76747
|
-
*/
|
|
76748
|
-
read(nodeId, sinceMs) {
|
|
76749
|
-
this.sweepIdle();
|
|
76750
|
-
const partition = this.partitions.get(nodeId);
|
|
76751
|
-
if (partition === void 0) return {
|
|
76752
|
-
nodeId,
|
|
76753
|
-
samples: [],
|
|
76754
|
-
retainedSamples: 0,
|
|
76755
|
-
oldestAtMs: null,
|
|
76756
|
-
capacity: this.samplesPerNode
|
|
76757
|
-
};
|
|
76758
|
-
return {
|
|
76759
|
-
nodeId,
|
|
76760
|
-
samples: partition.list(sinceMs),
|
|
76761
|
-
retainedSamples: partition.size(),
|
|
76762
|
-
oldestAtMs: partition.oldestAtMs(),
|
|
76763
|
-
capacity: this.samplesPerNode
|
|
76764
|
-
};
|
|
76765
|
-
}
|
|
76766
|
-
/** Node ids with a live partition. Observability for the fleet bound. */
|
|
76767
|
-
nodeIds() {
|
|
76768
|
-
return [...this.partitions.keys()];
|
|
76769
|
-
}
|
|
76770
|
-
/** Process rows retained across every partition — the number that IS memory. */
|
|
76771
|
-
rowCount() {
|
|
76772
|
-
return this.totalRows;
|
|
76773
|
-
}
|
|
76774
|
-
/** Samples retained across every partition. */
|
|
76775
|
-
sampleCount() {
|
|
76776
|
-
let total = 0;
|
|
76777
|
-
for (const partition of this.partitions.values()) total += partition.size();
|
|
76778
|
-
return total;
|
|
76779
|
-
}
|
|
76780
|
-
/**
|
|
76781
|
-
* Drop partitions whose newest sample is older than the retention window.
|
|
76782
|
-
*
|
|
76783
|
-
* Lazy, on write and on read — never a timer. A timer would be a new
|
|
76784
|
-
* periodic cost in a subsystem whose entire premise is that it adds none,
|
|
76785
|
-
* and a ring that nobody writes to and nobody reads is not growing either.
|
|
76786
|
-
*/
|
|
76787
|
-
sweepIdle() {
|
|
76788
|
-
const cutoff = this.now() - this.idleEvictionMs;
|
|
76789
|
-
for (const [nodeId, partition] of [...this.partitions.entries()]) {
|
|
76790
|
-
const lastWrite = partition.lastWriteAtMs();
|
|
76791
|
-
if (lastWrite !== null && lastWrite > cutoff) continue;
|
|
76792
|
-
this.dropPartition(nodeId);
|
|
76793
|
-
}
|
|
76794
|
-
}
|
|
76795
|
-
/**
|
|
76796
|
-
* Bring the fleet back under the row budget by dropping the OLDEST sample of
|
|
76797
|
-
* the HEAVIEST partition, repeatedly.
|
|
76798
|
-
*
|
|
76799
|
-
* Terminates: every iteration removes one sample from a non-empty partition,
|
|
76800
|
-
* and the population of samples is finite and strictly decreasing.
|
|
76801
|
-
*/
|
|
76802
|
-
enforceRowBudget() {
|
|
76803
|
-
while (this.totalRows > this.maxTotalProcessRows) {
|
|
76804
|
-
const victim = this.heaviestPartition();
|
|
76805
|
-
if (victim === null) return;
|
|
76806
|
-
const [nodeId, partition] = victim;
|
|
76807
|
-
this.totalRows -= partition.dropOldest();
|
|
76808
|
-
if (partition.size() === 0) this.dropPartition(nodeId);
|
|
76809
|
-
}
|
|
76810
|
-
}
|
|
76811
|
-
heaviestPartition() {
|
|
76812
|
-
let best = null;
|
|
76813
|
-
for (const entry of this.partitions.entries()) {
|
|
76814
|
-
if (entry[1].size() === 0) continue;
|
|
76815
|
-
if (best === null || entry[1].rowCount() > best[1].rowCount()) best = entry;
|
|
76816
|
-
}
|
|
76817
|
-
return best;
|
|
76818
|
-
}
|
|
76819
|
-
/** Drop `count` whole partitions, least-recently-written first. */
|
|
76820
|
-
evictPartitions(count, protectedNodeId) {
|
|
76821
|
-
const order = [...this.partitions.keys()].filter((nodeId) => nodeId !== protectedNodeId).toSorted((a, b) => (this.lastWriteSeq.get(a) ?? 0) - (this.lastWriteSeq.get(b) ?? 0));
|
|
76822
|
-
let remaining = count;
|
|
76823
|
-
for (const nodeId of order) {
|
|
76824
|
-
if (remaining <= 0) return;
|
|
76825
|
-
this.dropPartition(nodeId);
|
|
76826
|
-
remaining -= 1;
|
|
76827
|
-
}
|
|
76828
|
-
}
|
|
76829
|
-
/** Remove a partition and everything that indexes it. */
|
|
76830
|
-
dropPartition(nodeId) {
|
|
76831
|
-
const partition = this.partitions.get(nodeId);
|
|
76832
|
-
if (partition === void 0) return;
|
|
76833
|
-
this.totalRows -= partition.rowCount();
|
|
76834
|
-
this.partitions.delete(nodeId);
|
|
76835
|
-
this.lastWriteSeq.delete(nodeId);
|
|
76836
|
-
}
|
|
76837
|
-
};
|
|
76838
77489
|
var LOAD_SERIES_COLLECTION = "metrics:node-load-samples";
|
|
76839
77490
|
var DEFAULT_MAX_ROWS = 5e5;
|
|
76840
77491
|
var LOAD_SERIES_COLUMNS = [
|
|
@@ -77545,6 +78196,20 @@ var require_native_metrics_addon = __commonJS({
|
|
|
77545
78196
|
* per sample, to reach that very same table.
|
|
77546
78197
|
*/
|
|
77547
78198
|
loadStore = null;
|
|
78199
|
+
/**
|
|
78200
|
+
* The container's OWN memory, sampled on the process-snapshot tick.
|
|
78201
|
+
*
|
|
78202
|
+
* It rides that tick rather than a timer of its own so a memory reading and
|
|
78203
|
+
* the process rows it must be compared against carry the SAME timestamp —
|
|
78204
|
+
* the whole question is a subtraction, and two clocks make it an estimate.
|
|
78205
|
+
* Constructed in `onInitialize`, where the logger exists; it resolves the
|
|
78206
|
+
* cgroup once and latches.
|
|
78207
|
+
*/
|
|
78208
|
+
memoryProbe = null;
|
|
78209
|
+
/** Hot tier for the container reading. Bounds in `container-memory-series.ts`. */
|
|
78210
|
+
memoryRing = new ContainerMemoryRing();
|
|
78211
|
+
/** Cold tier, HUB only — same reasoning as `loadStore`. */
|
|
78212
|
+
memoryStore = null;
|
|
77548
78213
|
/** The resolved knobs. Re-resolved on every settings write. */
|
|
77549
78214
|
loadConfig = {
|
|
77550
78215
|
cadenceSec: 10,
|
|
@@ -77617,13 +78282,20 @@ var require_native_metrics_addon = __commonJS({
|
|
|
77617
78282
|
dumpHeapSnapshot: (params) => this.dumpHeapSnapshot(params)
|
|
77618
78283
|
};
|
|
77619
78284
|
this.applyLoadSeriesConfig();
|
|
77620
|
-
if (this.isHub)
|
|
77621
|
-
|
|
77622
|
-
|
|
77623
|
-
|
|
78285
|
+
if (this.isHub) {
|
|
78286
|
+
this.loadStore = new LoadSeriesStore({
|
|
78287
|
+
store: this.ctx.api.settingsStore,
|
|
78288
|
+
logger: this.ctx.logger.child("LoadSeries")
|
|
78289
|
+
});
|
|
78290
|
+
this.memoryStore = new ContainerMemoryStore({
|
|
78291
|
+
store: this.ctx.api.settingsStore,
|
|
78292
|
+
logger: this.ctx.logger.child("ContainerMemory")
|
|
78293
|
+
});
|
|
78294
|
+
}
|
|
78295
|
+
this.memoryProbe = new ContainerMemoryProbe({ logger: this.ctx.logger.child("ContainerMemory") });
|
|
77624
78296
|
this.snapshotTimer = setInterval(() => this.emitResourcesSnapshot(), METRICS_SNAPSHOT_INTERVAL_MS);
|
|
77625
78297
|
this.startProcessSnapshotTimer();
|
|
77626
|
-
this.ctx.addDisposer(this.ctx.eventBus.subscribe({ category: require_dist10.EventCategory.MetricsNodeProcessesSnapshot }, (event) => this.retainSnapshot(event.data.nodeId, event.data.timestamp, event.data.processes)));
|
|
78298
|
+
this.ctx.addDisposer(this.ctx.eventBus.subscribe({ category: require_dist10.EventCategory.MetricsNodeProcessesSnapshot }, (event) => this.retainSnapshot(event.data.nodeId, event.data.timestamp, event.data.processes, event.data.containerMemory)));
|
|
77627
78299
|
return [{
|
|
77628
78300
|
capability: require_dist10.metricsProviderCapability,
|
|
77629
78301
|
provider: composed
|
|
@@ -77641,19 +78313,31 @@ var require_native_metrics_addon = __commonJS({
|
|
|
77641
78313
|
* The durable append is fire-and-forget: a storage stall must cost a gap in
|
|
77642
78314
|
* the cold window, never a blocked event-bus handler. Every failure logs.
|
|
77643
78315
|
*/
|
|
77644
|
-
retainSnapshot(nodeId, atMs, processes) {
|
|
78316
|
+
retainSnapshot(nodeId, atMs, processes, containerMemory) {
|
|
77645
78317
|
const retained = processes.map((p) => NativeMetricsAddon2.toRetained(p));
|
|
77646
78318
|
if (!this.loadRing.record(nodeId, atMs, retained)) return;
|
|
77647
78319
|
this.observedRowsByNode.set(nodeId, retained.length);
|
|
78320
|
+
if (containerMemory !== null) this.memoryRing.record(nodeId, atMs, containerMemory);
|
|
77648
78321
|
const store = this.loadStore;
|
|
77649
78322
|
if (store === null) return;
|
|
77650
|
-
store.append(nodeId, atMs, retained).then(() => store.prune([...this.observedRowsByNode.keys()], this.loadConfig)).
|
|
78323
|
+
store.append(nodeId, atMs, retained).then(() => store.prune([...this.observedRowsByNode.keys()], this.loadConfig)).then(async (outcome) => {
|
|
78324
|
+
if (outcome === null) return;
|
|
78325
|
+
await this.memoryStore?.prune([...this.observedRowsByNode.keys()], this.loadConfig);
|
|
78326
|
+
}).catch((err) => {
|
|
77651
78327
|
this.ctx.logger.warn("durable load series write failed", { meta: {
|
|
77652
78328
|
nodeId,
|
|
77653
78329
|
atMs,
|
|
77654
78330
|
error: err instanceof Error ? err.message : String(err)
|
|
77655
78331
|
} });
|
|
77656
78332
|
});
|
|
78333
|
+
if (containerMemory === null) return;
|
|
78334
|
+
this.memoryStore?.append(nodeId, atMs, containerMemory).catch((err) => {
|
|
78335
|
+
this.ctx.logger.warn("durable container memory write failed", { meta: {
|
|
78336
|
+
nodeId,
|
|
78337
|
+
atMs,
|
|
78338
|
+
error: err instanceof Error ? err.message : String(err)
|
|
78339
|
+
} });
|
|
78340
|
+
});
|
|
77657
78341
|
}
|
|
77658
78342
|
/**
|
|
77659
78343
|
* The ONE reader, over both tiers.
|
|
@@ -77682,6 +78366,14 @@ var require_native_metrics_addon = __commonJS({
|
|
|
77682
78366
|
return {
|
|
77683
78367
|
nodeId: params.forNodeId,
|
|
77684
78368
|
series: merged.series,
|
|
78369
|
+
containerMemory: await this.readContainerMemory({
|
|
78370
|
+
forNodeId: params.forNodeId,
|
|
78371
|
+
sinceMs,
|
|
78372
|
+
...params.sinceMs !== void 0 ? { exclusiveSinceMs: params.sinceMs } : {},
|
|
78373
|
+
bucketMs: merged.bucketMs,
|
|
78374
|
+
cadenceMs,
|
|
78375
|
+
origin: merged.oldestAtMs
|
|
78376
|
+
}),
|
|
77685
78377
|
bucketMs: merged.bucketMs,
|
|
77686
78378
|
retainedSamples: merged.retainedSamples,
|
|
77687
78379
|
oldestAtMs: merged.oldestAtMs,
|
|
@@ -77690,6 +78382,24 @@ var require_native_metrics_addon = __commonJS({
|
|
|
77690
78382
|
};
|
|
77691
78383
|
}
|
|
77692
78384
|
/**
|
|
78385
|
+
* The container's memory over the same window, on the same x-axis.
|
|
78386
|
+
*
|
|
78387
|
+
* Both tiers, merged and deduped on `atMs` like the process series, then
|
|
78388
|
+
* reduced against the SAME `bucketMs` and the SAME origin — otherwise the
|
|
78389
|
+
* two series in one answer would sit on two different axes and the
|
|
78390
|
+
* subtraction they exist for would be an eyeball.
|
|
78391
|
+
*
|
|
78392
|
+
* An EMPTY answer means the node has no cgroup, or nothing has been retained
|
|
78393
|
+
* for it yet. It never means zero.
|
|
78394
|
+
*/
|
|
78395
|
+
async readContainerMemory(params) {
|
|
78396
|
+
const hot = this.memoryRing.read(params.forNodeId, params.exclusiveSinceMs);
|
|
78397
|
+
const store = this.memoryStore;
|
|
78398
|
+
const merged = mergeContainerMemory(store === null ? [] : await store.read(params.forNodeId, params.sinceMs, CONTAINER_MEMORY_MAX_ROWS), hot);
|
|
78399
|
+
if (params.bucketMs <= params.cadenceMs) return merged;
|
|
78400
|
+
return reduceContainerMemory(merged, params.bucketMs, params.origin ?? 0);
|
|
78401
|
+
}
|
|
78402
|
+
/**
|
|
77693
78403
|
* Re-resolve the knobs and restate the fixed cadence.
|
|
77694
78404
|
*
|
|
77695
78405
|
* A REFUSED value (out of 5-60 s, or out of 1-72 h) leaves the previous
|
|
@@ -77806,6 +78516,7 @@ var require_native_metrics_addon = __commonJS({
|
|
|
77806
78516
|
const timestamp = Date.now();
|
|
77807
78517
|
try {
|
|
77808
78518
|
const processes = await this.listNodeProcesses();
|
|
78519
|
+
const containerMemory = this.memoryProbe?.sample() ?? null;
|
|
77809
78520
|
eventBus.emit(require_dist10.createEvent(require_dist10.EventCategory.MetricsNodeProcessesSnapshot, {
|
|
77810
78521
|
type: "node",
|
|
77811
78522
|
id: nodeId,
|
|
@@ -77813,7 +78524,8 @@ var require_native_metrics_addon = __commonJS({
|
|
|
77813
78524
|
}, {
|
|
77814
78525
|
nodeId,
|
|
77815
78526
|
processes,
|
|
77816
|
-
timestamp
|
|
78527
|
+
timestamp,
|
|
78528
|
+
containerMemory
|
|
77817
78529
|
}));
|
|
77818
78530
|
} catch (err) {
|
|
77819
78531
|
this.ctx.logger.warn("process snapshot skipped \u2014 this interval will be missing", { meta: {
|
|
@@ -78079,14 +78791,14 @@ var require_filesystem_storage_addon = __commonJS({
|
|
|
78079
78791
|
[Symbol.toStringTag]: { value: "Module" }
|
|
78080
78792
|
});
|
|
78081
78793
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
78082
|
-
var require_dist10 =
|
|
78794
|
+
var require_dist10 = require_dist_C7uZ_fOb();
|
|
78083
78795
|
var node_crypto = __require("crypto");
|
|
78084
78796
|
var node_fs_promises = __require("fs/promises");
|
|
78085
78797
|
var node_path = __require("path");
|
|
78086
78798
|
node_path = require_chunk.__toESM(node_path);
|
|
78087
|
-
var node_os = __require("os");
|
|
78088
78799
|
var node_fs = __require("fs");
|
|
78089
78800
|
node_fs = require_chunk.__toESM(node_fs);
|
|
78801
|
+
var node_os = __require("os");
|
|
78090
78802
|
function isWithinAllowedRoots(candidate, allowedRoots) {
|
|
78091
78803
|
const norm = (0, node_path.resolve)(candidate);
|
|
78092
78804
|
return allowedRoots.some((root) => {
|
|
@@ -79195,8 +79907,8 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
79195
79907
|
[Symbol.toStringTag]: { value: "Module" }
|
|
79196
79908
|
});
|
|
79197
79909
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
79198
|
-
var require_dist10 =
|
|
79199
|
-
var require_retired_settings_keys =
|
|
79910
|
+
var require_dist10 = require_dist_C7uZ_fOb();
|
|
79911
|
+
var require_retired_settings_keys = require_retired_settings_keys_CBU4_TJO();
|
|
79200
79912
|
var node_crypto = __require("crypto");
|
|
79201
79913
|
var node_fs = __require("fs");
|
|
79202
79914
|
var node_module = __require("module");
|
|
@@ -81475,7 +82187,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
81475
82187
|
[Symbol.toStringTag]: { value: "Module" }
|
|
81476
82188
|
});
|
|
81477
82189
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
81478
|
-
var require_dist10 =
|
|
82190
|
+
var require_dist10 = require_dist_C7uZ_fOb();
|
|
81479
82191
|
var node_crypto = __require("crypto");
|
|
81480
82192
|
var node_fs_promises = __require("fs/promises");
|
|
81481
82193
|
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
@@ -83356,7 +84068,7 @@ var require_system_config_addon = __commonJS({
|
|
|
83356
84068
|
[Symbol.toStringTag]: { value: "Module" }
|
|
83357
84069
|
});
|
|
83358
84070
|
require_chunk_Cek0wNdY();
|
|
83359
|
-
var require_dist10 =
|
|
84071
|
+
var require_dist10 = require_dist_C7uZ_fOb();
|
|
83360
84072
|
var SECTION_TITLES = {
|
|
83361
84073
|
server: "Server",
|
|
83362
84074
|
auth: "Authentication"
|
|
@@ -101417,7 +102129,7 @@ var require_winston_logging = __commonJS({
|
|
|
101417
102129
|
[Symbol.toStringTag]: { value: "Module" }
|
|
101418
102130
|
});
|
|
101419
102131
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
101420
|
-
var require_dist10 =
|
|
102132
|
+
var require_dist10 = require_dist_C7uZ_fOb();
|
|
101421
102133
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
101422
102134
|
var node_path = __require("path");
|
|
101423
102135
|
node_path = require_chunk.__toESM(node_path);
|
|
@@ -102447,9 +103159,9 @@ var require_file_data_plane_DO8KbxCe = __commonJS({
|
|
|
102447
103159
|
}
|
|
102448
103160
|
});
|
|
102449
103161
|
|
|
102450
|
-
// ../system/dist/tls-
|
|
102451
|
-
var
|
|
102452
|
-
"../system/dist/tls-
|
|
103162
|
+
// ../system/dist/tls-BxQlomxd.js
|
|
103163
|
+
var require_tls_BxQlomxd = __commonJS({
|
|
103164
|
+
"../system/dist/tls-BxQlomxd.js"(exports) {
|
|
102453
103165
|
"use strict";
|
|
102454
103166
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
102455
103167
|
var node_crypto = __require("crypto");
|
|
@@ -102457,9 +103169,9 @@ var require_tls_u8QCJCFE = __commonJS({
|
|
|
102457
103169
|
var node_path = __require("path");
|
|
102458
103170
|
var node_child_process = __require("child_process");
|
|
102459
103171
|
var node_util = __require("util");
|
|
103172
|
+
var node_fs = __require("fs");
|
|
102460
103173
|
var node_os = __require("os");
|
|
102461
103174
|
node_os = require_chunk.__toESM(node_os);
|
|
102462
|
-
var node_fs = __require("fs");
|
|
102463
103175
|
var node_http = __require("http");
|
|
102464
103176
|
var node_net = __require("net");
|
|
102465
103177
|
var DEFAULT_HTTP_PORT = 4480;
|
|
@@ -113905,12 +114617,12 @@ var require_dist2 = __commonJS({
|
|
|
113905
114617
|
}
|
|
113906
114618
|
});
|
|
113907
114619
|
|
|
113908
|
-
// ../system/dist/manifest-python-deps-
|
|
113909
|
-
var
|
|
113910
|
-
"../system/dist/manifest-python-deps-
|
|
114620
|
+
// ../system/dist/manifest-python-deps-CRTx_j4k.js
|
|
114621
|
+
var require_manifest_python_deps_CRTx_j4k = __commonJS({
|
|
114622
|
+
"../system/dist/manifest-python-deps-CRTx_j4k.js"(exports) {
|
|
113911
114623
|
"use strict";
|
|
113912
114624
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
113913
|
-
|
|
114625
|
+
require_dist_C7uZ_fOb();
|
|
113914
114626
|
var node_crypto = __require("crypto");
|
|
113915
114627
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
113916
114628
|
var _camstack_types_node = require_node();
|
|
@@ -113919,19 +114631,166 @@ var require_manifest_python_deps_BqWrDjSN = __commonJS({
|
|
|
113919
114631
|
node_path = require_chunk.__toESM(node_path);
|
|
113920
114632
|
var node_child_process = __require("child_process");
|
|
113921
114633
|
var node_util = __require("util");
|
|
113922
|
-
var node_os = __require("os");
|
|
113923
|
-
node_os = require_chunk.__toESM(node_os);
|
|
113924
114634
|
var node_fs = __require("fs");
|
|
113925
114635
|
node_fs = require_chunk.__toESM(node_fs);
|
|
114636
|
+
var node_os = __require("os");
|
|
114637
|
+
node_os = require_chunk.__toESM(node_os);
|
|
113926
114638
|
var node_http = __require("http");
|
|
113927
|
-
var node_perf_hooks = __require("perf_hooks");
|
|
113928
114639
|
var node_v8 = __require("v8");
|
|
113929
114640
|
node_v8 = require_chunk.__toESM(node_v8);
|
|
114641
|
+
var node_perf_hooks = __require("perf_hooks");
|
|
113930
114642
|
var node_vm = __require("vm");
|
|
113931
114643
|
node_vm = require_chunk.__toESM(node_vm);
|
|
113932
114644
|
var _camstack_types_addon = require_addon();
|
|
113933
114645
|
var node_net = __require("net");
|
|
113934
114646
|
var _trpc_client = require_dist2();
|
|
114647
|
+
function createEventPlaneReader(sources) {
|
|
114648
|
+
return () => {
|
|
114649
|
+
try {
|
|
114650
|
+
const registry = sources.registry();
|
|
114651
|
+
if (registry === null) return void 0;
|
|
114652
|
+
const children = [];
|
|
114653
|
+
const listed = registry.listChildren();
|
|
114654
|
+
for (const child of listed) {
|
|
114655
|
+
const stats = registry.getChildEventStats(child.childId);
|
|
114656
|
+
if (stats === null) continue;
|
|
114657
|
+
children.push({
|
|
114658
|
+
childId: child.childId,
|
|
114659
|
+
sent: stats.sent,
|
|
114660
|
+
suppressed: stats.suppressed
|
|
114661
|
+
});
|
|
114662
|
+
}
|
|
114663
|
+
const crossNode = sources.crossNodeStats();
|
|
114664
|
+
return {
|
|
114665
|
+
udsMode: registry.eventFanoutMode,
|
|
114666
|
+
crossNodeMode: sources.crossNodeMode(),
|
|
114667
|
+
children,
|
|
114668
|
+
childrenConnected: listed.length,
|
|
114669
|
+
childrenUndeclared: registry.undeclaredChildCount(),
|
|
114670
|
+
crossNodeDelivered: crossNode?.delivered ?? 0,
|
|
114671
|
+
crossNodeSuppressed: crossNode?.suppressed ?? 0
|
|
114672
|
+
};
|
|
114673
|
+
} catch {
|
|
114674
|
+
return;
|
|
114675
|
+
}
|
|
114676
|
+
};
|
|
114677
|
+
}
|
|
114678
|
+
var EVENT_PLANE_TOP_N = 5;
|
|
114679
|
+
var EMPTY_EVENT_PLANE_BASELINE = {
|
|
114680
|
+
children: /* @__PURE__ */ new Map(),
|
|
114681
|
+
crossNodeDelivered: 0,
|
|
114682
|
+
crossNodeSuppressed: 0
|
|
114683
|
+
};
|
|
114684
|
+
function diffEventPlane(baseline, current, topN = 5) {
|
|
114685
|
+
const deltas = [];
|
|
114686
|
+
let fanoutSent = 0;
|
|
114687
|
+
let fanoutSuppressed = 0;
|
|
114688
|
+
for (const sample of current.children) {
|
|
114689
|
+
const before = baseline.children.get(sample.childId);
|
|
114690
|
+
const sent = Math.max(0, sample.sent - (before?.sent ?? 0));
|
|
114691
|
+
const suppressed = Math.max(0, sample.suppressed - (before?.suppressed ?? 0));
|
|
114692
|
+
fanoutSent += sent;
|
|
114693
|
+
fanoutSuppressed += suppressed;
|
|
114694
|
+
if (sent > 0 || suppressed > 0) deltas.push({
|
|
114695
|
+
childId: sample.childId,
|
|
114696
|
+
sent,
|
|
114697
|
+
suppressed
|
|
114698
|
+
});
|
|
114699
|
+
}
|
|
114700
|
+
return {
|
|
114701
|
+
udsMode: current.udsMode,
|
|
114702
|
+
crossNodeMode: current.crossNodeMode,
|
|
114703
|
+
childrenConnected: current.childrenConnected,
|
|
114704
|
+
childrenUndeclared: current.childrenUndeclared,
|
|
114705
|
+
fanoutSent,
|
|
114706
|
+
fanoutSuppressed,
|
|
114707
|
+
crossNodeDelivered: Math.max(0, current.crossNodeDelivered - baseline.crossNodeDelivered),
|
|
114708
|
+
crossNodeSuppressed: Math.max(0, current.crossNodeSuppressed - baseline.crossNodeSuppressed),
|
|
114709
|
+
top: deltas.toSorted((a, b) => b.sent - a.sent || a.childId.localeCompare(b.childId)).slice(0, topN)
|
|
114710
|
+
};
|
|
114711
|
+
}
|
|
114712
|
+
function createEventPlaneMeter(reader, topN = 5) {
|
|
114713
|
+
let baseline = EMPTY_EVENT_PLANE_BASELINE;
|
|
114714
|
+
return { read: () => {
|
|
114715
|
+
const current = reader();
|
|
114716
|
+
if (current === void 0) return void 0;
|
|
114717
|
+
const window2 = diffEventPlane(baseline, current, topN);
|
|
114718
|
+
baseline = {
|
|
114719
|
+
children: new Map(current.children.map((s) => [s.childId, s])),
|
|
114720
|
+
crossNodeDelivered: current.crossNodeDelivered,
|
|
114721
|
+
crossNodeSuppressed: current.crossNodeSuppressed
|
|
114722
|
+
};
|
|
114723
|
+
return window2;
|
|
114724
|
+
} };
|
|
114725
|
+
}
|
|
114726
|
+
function formatEventPlane(window2) {
|
|
114727
|
+
if (window2 === void 0) return "";
|
|
114728
|
+
const top = window2.top.map((d) => `${d.childId}:${d.sent}/${d.suppressed}`).join(",");
|
|
114729
|
+
return ` fanoutMode=uds:${window2.udsMode}/cross-node:${window2.crossNodeMode} children=${window2.childrenConnected} childrenUndeclared=${window2.childrenUndeclared} fanoutSent=${window2.fanoutSent} fanoutSuppressed=${window2.fanoutSuppressed} crossNodeDelivered=${window2.crossNodeDelivered} crossNodeSuppressed=${window2.crossNodeSuppressed}` + (top.length === 0 ? "" : ` fanoutTop=${top}`);
|
|
114730
|
+
}
|
|
114731
|
+
var DECISIVE_HEAP_SPACES = ["old_space", "large_object_space"];
|
|
114732
|
+
var HEAP_SPACE_REPORT_MIN_MB = 32;
|
|
114733
|
+
var BYTES_PER_MB = 1048576;
|
|
114734
|
+
function mb(bytes) {
|
|
114735
|
+
return Math.round(bytes / BYTES_PER_MB);
|
|
114736
|
+
}
|
|
114737
|
+
function tenthsMb(bytes) {
|
|
114738
|
+
return Math.round(bytes / BYTES_PER_MB * 10) / 10;
|
|
114739
|
+
}
|
|
114740
|
+
function readHeapSpaces() {
|
|
114741
|
+
try {
|
|
114742
|
+
return node_v8.getHeapSpaceStatistics().map((space) => ({
|
|
114743
|
+
name: space.space_name,
|
|
114744
|
+
usedBytes: space.space_used_size
|
|
114745
|
+
}));
|
|
114746
|
+
} catch {
|
|
114747
|
+
return [];
|
|
114748
|
+
}
|
|
114749
|
+
}
|
|
114750
|
+
function heapSpaceField(v8Name) {
|
|
114751
|
+
return v8Name.replace(/_([a-z])/g, (_match, letter) => letter.toUpperCase());
|
|
114752
|
+
}
|
|
114753
|
+
function selectReportedSpaces(spaces, minMb = 32) {
|
|
114754
|
+
const decisive = DECISIVE_HEAP_SPACES.map((name) => spaces.find((space) => space.name === name)).filter((space) => space !== void 0);
|
|
114755
|
+
const rest = spaces.filter((space) => !DECISIVE_HEAP_SPACES.includes(space.name)).filter((space) => mb(space.usedBytes) >= minMb).toSorted((a, b) => b.usedBytes - a.usedBytes || a.name.localeCompare(b.name));
|
|
114756
|
+
return [...decisive, ...rest];
|
|
114757
|
+
}
|
|
114758
|
+
function formatHeapSpaces(spaces, minMb = 32) {
|
|
114759
|
+
const selected = selectReportedSpaces(spaces, minMb);
|
|
114760
|
+
if (selected.length === 0) return "";
|
|
114761
|
+
return ` ${selected.map((s) => `${heapSpaceField(s.name)}=${mb(s.usedBytes)}MB`).join(" ")}`;
|
|
114762
|
+
}
|
|
114763
|
+
var RUNNER_HEAP_SNAPSHOT_ENV = "CAMSTACK_RUNNER_HEAP_SNAPSHOT";
|
|
114764
|
+
function heapSnapshotAuthorised(env = process.env) {
|
|
114765
|
+
return env[RUNNER_HEAP_SNAPSHOT_ENV] === "on";
|
|
114766
|
+
}
|
|
114767
|
+
var defaultDeps = {
|
|
114768
|
+
readMemory: () => process.memoryUsage(),
|
|
114769
|
+
readSpaces: readHeapSpaces,
|
|
114770
|
+
writeSnapshot: (path) => {
|
|
114771
|
+
node_v8.writeHeapSnapshot(path);
|
|
114772
|
+
},
|
|
114773
|
+
env: process.env
|
|
114774
|
+
};
|
|
114775
|
+
function emitHeapDiagnosticReport(request, deps = defaultDeps) {
|
|
114776
|
+
try {
|
|
114777
|
+
const mu = deps.readMemory();
|
|
114778
|
+
const spaces = deps.readSpaces().filter((space) => space.usedBytes > 0).map((space) => `${space.name}=${tenthsMb(space.usedBytes)}`).join(" ");
|
|
114779
|
+
request.sink.info(`[mem] node="${request.label}" addons=[${request.addons.join(",")}] rss=${tenthsMb(mu.rss)} heapUsed=${tenthsMb(mu.heapUsed)} heapTotal=${tenthsMb(mu.heapTotal)} external=${tenthsMb(mu.external)} arrayBuffers=${tenthsMb(mu.arrayBuffers)} | ${spaces}`);
|
|
114780
|
+
} catch (error) {
|
|
114781
|
+
request.sink.warn(`[mem] node="${request.label}" space report failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
114782
|
+
}
|
|
114783
|
+
if (!heapSnapshotAuthorised(deps.env)) {
|
|
114784
|
+
request.sink.info(`[mem] node="${request.label}" heap snapshot NOT taken \u2014 it is an admin mutation (a multi-GB write and a stop-the-world walk of the heap). The per-space breakdown above is the free half and needs no authorisation. Set ${RUNNER_HEAP_SNAPSHOT_ENV}=on for this runner and signal again to take one.`);
|
|
114785
|
+
return;
|
|
114786
|
+
}
|
|
114787
|
+
try {
|
|
114788
|
+
deps.writeSnapshot(request.snapshotPath);
|
|
114789
|
+
request.sink.info(`[mem] node="${request.label}" heap snapshot written -> ${request.snapshotPath}`);
|
|
114790
|
+
} catch (error) {
|
|
114791
|
+
request.sink.warn(`[mem] node="${request.label}" snapshot failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
114792
|
+
}
|
|
114793
|
+
}
|
|
113935
114794
|
var HUB_MAIN_HEAP_WATCH_LABEL = "hub-main";
|
|
113936
114795
|
var HEAP_WATCH_INTERVAL_MS = 6e4;
|
|
113937
114796
|
var HEAP_WATCH_WARN_RATIO = 0.8;
|
|
@@ -113943,6 +114802,10 @@ var require_manifest_python_deps_BqWrDjSN = __commonJS({
|
|
|
113943
114802
|
}
|
|
113944
114803
|
var HEAP_RECLAIM_TRIGGER_MB = 1024;
|
|
113945
114804
|
var HEAP_RECLAIM_MIN_INTERVAL_MS = 12e4;
|
|
114805
|
+
var HEAP_RECLAIM_STEADY_STATE_INTERVAL_MS = 6e5;
|
|
114806
|
+
function reclaimIntervalMs(passesAtFloor, minIntervalMs = HEAP_RECLAIM_MIN_INTERVAL_MS, steadyStateIntervalMs = HEAP_RECLAIM_STEADY_STATE_INTERVAL_MS, steadyStatePasses = 6) {
|
|
114807
|
+
return passesAtFloor >= steadyStatePasses ? Math.max(minIntervalMs, steadyStateIntervalMs) : minIntervalMs;
|
|
114808
|
+
}
|
|
113946
114809
|
var ZERO_LOOP_DELAY = {
|
|
113947
114810
|
p50Ms: 0,
|
|
113948
114811
|
p99Ms: 0,
|
|
@@ -113952,14 +114815,15 @@ var require_manifest_python_deps_BqWrDjSN = __commonJS({
|
|
|
113952
114815
|
try {
|
|
113953
114816
|
const histogram = (0, node_perf_hooks.monitorEventLoopDelay)({ resolution: resolutionMs });
|
|
113954
114817
|
histogram.enable();
|
|
114818
|
+
const delay2 = (nanoseconds) => Math.max(0, Math.round(nanoseconds / 1e6) - resolutionMs);
|
|
113955
114819
|
return {
|
|
113956
114820
|
read: () => {
|
|
113957
114821
|
try {
|
|
113958
114822
|
if (histogram.count === 0) return ZERO_LOOP_DELAY;
|
|
113959
114823
|
const sample = {
|
|
113960
|
-
p50Ms:
|
|
113961
|
-
p99Ms:
|
|
113962
|
-
maxMs:
|
|
114824
|
+
p50Ms: delay2(histogram.percentile(50)),
|
|
114825
|
+
p99Ms: delay2(histogram.percentile(99)),
|
|
114826
|
+
maxMs: delay2(histogram.max)
|
|
113963
114827
|
};
|
|
113964
114828
|
histogram.reset();
|
|
113965
114829
|
return sample;
|
|
@@ -114069,16 +114933,19 @@ var require_manifest_python_deps_BqWrDjSN = __commonJS({
|
|
|
114069
114933
|
function formatOverBudget(label, b, source) {
|
|
114070
114934
|
return `[mem] ${label} OVER RSS BUDGET rss=${b.rssMb}MB budget=${b.budgetMb}MB over=+${b.overMb}MB shape=${b.shape} heapUsed=${b.heapUsedMb}MB(${share(b.heapUsedMb, b.rssMb)}%) external=${b.externalMb}MB(${share(b.externalMb, b.rssMb)}%) nativeResidue=${b.nativeResidueMb}MB(${share(b.nativeResidueMb, b.rssMb)}%) arrayBuffers=${b.arrayBuffersMb}MB budgetFrom="${source}" \u2014 ${SHAPE_ADVICE[b.shape]}`;
|
|
114071
114935
|
}
|
|
114072
|
-
function format2(label, s, loop, budgetMb) {
|
|
114936
|
+
function format2(label, s, loop, budgetMb, suffix) {
|
|
114073
114937
|
const line = `[mem] ${label} rss=${s.rssMb}MB heapUsed=${s.heapUsedMb}MB heapTotal=${s.heapTotalMb}MB heapLimit=${s.heapLimitMb}MB used=${Math.round(s.usedRatio * 100)}% external=${s.externalMb}MB arrayBuffers=${s.arrayBuffersMb}MB` + (budgetMb === void 0 ? "" : ` rssBudget=${budgetMb}MB`);
|
|
114074
|
-
if (loop === void 0) return line
|
|
114075
|
-
return `${line} loopP50=${loop.p50Ms}ms loopP99=${loop.p99Ms}ms loopMax=${loop.maxMs}ms`;
|
|
114938
|
+
if (loop === void 0) return `${line}${suffix}`;
|
|
114939
|
+
return `${line} loopP50=${loop.p50Ms}ms loopP99=${loop.p99Ms}ms loopMax=${loop.maxMs}ms${suffix}`;
|
|
114076
114940
|
}
|
|
114077
|
-
function startHeapWatch(label = HUB_MAIN_HEAP_WATCH_LABEL, sink = consoleSink, intervalMs = HEAP_WATCH_INTERVAL_MS, reclaimOptions, loopDelay = createLoopDelayMeter(), execArgv = process.execArgv, announceCeilingOrigin = true, rssBudget) {
|
|
114941
|
+
function startHeapWatch(label = HUB_MAIN_HEAP_WATCH_LABEL, sink = consoleSink, intervalMs = HEAP_WATCH_INTERVAL_MS, reclaimOptions, loopDelay = createLoopDelayMeter(), execArgv = process.execArgv, announceCeilingOrigin = true, rssBudget, probes) {
|
|
114942
|
+
const readSpaces = probes?.readSpaces ?? readHeapSpaces;
|
|
114943
|
+
const eventPlane = probes?.eventPlane === void 0 ? void 0 : createEventPlaneMeter(probes.eventPlane);
|
|
114078
114944
|
const readMemory = reclaimOptions?.readMemory ?? (() => process.memoryUsage());
|
|
114079
114945
|
const now = reclaimOptions?.now ?? (() => Date.now());
|
|
114080
114946
|
const triggerMb = reclaimOptions?.triggerMb ?? 1024;
|
|
114081
114947
|
const minIntervalMs = reclaimOptions?.minIntervalMs ?? 12e4;
|
|
114948
|
+
const steadyStateIntervalMs = reclaimOptions?.steadyStateIntervalMs ?? 6e5;
|
|
114082
114949
|
const fastIntervalMs = reclaimOptions?.fastIntervalMs ?? 2e3;
|
|
114083
114950
|
const escalateRatio = reclaimOptions?.escalateRatio ?? 0.7;
|
|
114084
114951
|
const deescalateRatio = reclaimOptions?.deescalateRatio ?? 0.6;
|
|
@@ -114096,9 +114963,10 @@ var require_manifest_python_deps_BqWrDjSN = __commonJS({
|
|
|
114096
114963
|
steadyStateAnnounced = false;
|
|
114097
114964
|
return;
|
|
114098
114965
|
}
|
|
114966
|
+
const floorMs = reclaimIntervalMs(passesAtFloor, minIntervalMs, steadyStateIntervalMs);
|
|
114099
114967
|
const sinceLast = now() - lastReclaimAt;
|
|
114100
|
-
if (sinceLast <
|
|
114101
|
-
passesAtFloor = sinceLast <=
|
|
114968
|
+
if (sinceLast < floorMs) return;
|
|
114969
|
+
passesAtFloor = sinceLast <= floorMs * 2 ? passesAtFloor + 1 : 1;
|
|
114102
114970
|
lastReclaimAt = now();
|
|
114103
114971
|
const startedAt = now();
|
|
114104
114972
|
try {
|
|
@@ -114111,7 +114979,8 @@ var require_manifest_python_deps_BqWrDjSN = __commonJS({
|
|
|
114111
114979
|
sink.info(`[mem] reclaim ${label} stranded=${strandedMb(sample)}MB rss=${sample.rssMb}MB\u2192${after.rssMb}MB freed=${sample.rssMb - after.rssMb}MB arrayBuffers=${sample.arrayBuffersMb}MB\u2192${after.arrayBuffersMb}MB took=${now() - startedAt}ms`);
|
|
114112
114980
|
if (passesAtFloor >= 6 && !steadyStateAnnounced) {
|
|
114113
114981
|
steadyStateAnnounced = true;
|
|
114114
|
-
|
|
114982
|
+
const nextFloorMs = reclaimIntervalMs(passesAtFloor, minIntervalMs, steadyStateIntervalMs);
|
|
114983
|
+
sink.warn(`[mem] reclaim ${label} has run at the floor for ${passesAtFloor} consecutive passes (every ${minIntervalMs}ms) \u2014 the stop-the-world is now STEADY STATE, not a rescue: stranded never fell back under ${triggerMb}MB between passes, so the trigger is not discriminating on this process and what is left deciding is the timer. BACKING OFF to every ${nextFloorMs}ms \u2014 the pass keeps running (it is still the only measurement of this process's live ArrayBuffer set) at a cost the router can pay. The allocation source is what needs the fix; this pass only bounds its peak.`);
|
|
114115
114984
|
}
|
|
114116
114985
|
};
|
|
114117
114986
|
let mode = "steady";
|
|
@@ -114149,7 +115018,7 @@ var require_manifest_python_deps_BqWrDjSN = __commonJS({
|
|
|
114149
115018
|
const due = at - lastLoggedAt >= intervalMs;
|
|
114150
115019
|
if (mode === "escalated" || due) {
|
|
114151
115020
|
lastLoggedAt = at;
|
|
114152
|
-
const line = format2(label, sample, loopDelay?.read(), budgetMb);
|
|
115021
|
+
const line = format2(label, sample, loopDelay?.read(), budgetMb, `${formatHeapSpaces(readSpaces())}${formatEventPlane(eventPlane?.read())}`);
|
|
114153
115022
|
if (sample.nearLimit) sink.warn(`${line} \u2014 APPROACHING HEAP LIMIT`);
|
|
114154
115023
|
else if (mode === "escalated") sink.warn(`${line} \u2014 heap elevated, sampling every ${probeIntervalMs}ms`);
|
|
114155
115024
|
else sink.info(line);
|
|
@@ -118254,6 +119123,34 @@ var require_manifest_python_deps_BqWrDjSN = __commonJS({
|
|
|
118254
119123
|
};
|
|
118255
119124
|
}
|
|
118256
119125
|
/**
|
|
119126
|
+
* The regime the counters above were produced under, read once from
|
|
119127
|
+
* `CAMSTACK_UDS_EVENT_FANOUT` at construction.
|
|
119128
|
+
*
|
|
119129
|
+
* A suppressed count means "nothing WAS dropped" under `filter` and "nothing
|
|
119130
|
+
* WOULD have been dropped" under `shadow`. Those are different claims, and
|
|
119131
|
+
* until this getter existed the mode was invisible at runtime — the counters
|
|
119132
|
+
* were readable and the regime that produced them was not.
|
|
119133
|
+
*/
|
|
119134
|
+
get eventFanoutMode() {
|
|
119135
|
+
return this.fanoutMode;
|
|
119136
|
+
}
|
|
119137
|
+
/**
|
|
119138
|
+
* Connected children that never declared a subscription pattern set.
|
|
119139
|
+
*
|
|
119140
|
+
* Each one is a fail-open on BOTH planes: `childWantsEvent` returns true for
|
|
119141
|
+
* an undeclared child ({@link ChildEntry.eventPatterns} `=== null`), and
|
|
119142
|
+
* `aggregateEventInterest` returns `null` — accept everything — if ANY
|
|
119143
|
+
* connected child is undeclared, which disables the node's inbound cross-node
|
|
119144
|
+
* gate as well. **One legacy runner silently turns off the filtering for the
|
|
119145
|
+
* whole node**, and nothing reported it, so a zero here is as load-bearing as
|
|
119146
|
+
* a non-zero one.
|
|
119147
|
+
*/
|
|
119148
|
+
undeclaredChildCount() {
|
|
119149
|
+
let count = 0;
|
|
119150
|
+
for (const entry of this.children.values()) if (entry.eventPatterns === null) count += 1;
|
|
119151
|
+
return count;
|
|
119152
|
+
}
|
|
119153
|
+
/**
|
|
118257
119154
|
* Does `entry` want to receive an event in `category`? Honours the fan-out
|
|
118258
119155
|
* mode: `broadcast` → always; undeclared patterns (`null`) → always
|
|
118259
119156
|
* (fail-open); else the child's declared set must match via `matchesPattern`
|
|
@@ -120709,12 +121606,24 @@ var require_manifest_python_deps_BqWrDjSN = __commonJS({
|
|
|
120709
121606
|
return CapabilityUnavailableError;
|
|
120710
121607
|
}
|
|
120711
121608
|
});
|
|
121609
|
+
Object.defineProperty(exports, "DECISIVE_HEAP_SPACES", {
|
|
121610
|
+
enumerable: true,
|
|
121611
|
+
get: function() {
|
|
121612
|
+
return DECISIVE_HEAP_SPACES;
|
|
121613
|
+
}
|
|
121614
|
+
});
|
|
120712
121615
|
Object.defineProperty(exports, "DeviceRegistry", {
|
|
120713
121616
|
enumerable: true,
|
|
120714
121617
|
get: function() {
|
|
120715
121618
|
return DeviceRegistry;
|
|
120716
121619
|
}
|
|
120717
121620
|
});
|
|
121621
|
+
Object.defineProperty(exports, "EVENT_PLANE_TOP_N", {
|
|
121622
|
+
enumerable: true,
|
|
121623
|
+
get: function() {
|
|
121624
|
+
return EVENT_PLANE_TOP_N;
|
|
121625
|
+
}
|
|
121626
|
+
});
|
|
120718
121627
|
Object.defineProperty(exports, "EVENT_TOPIC_PREFIX", {
|
|
120719
121628
|
enumerable: true,
|
|
120720
121629
|
get: function() {
|
|
@@ -120733,12 +121642,24 @@ var require_manifest_python_deps_BqWrDjSN = __commonJS({
|
|
|
120733
121642
|
return HEAP_RECLAIM_MIN_INTERVAL_MS;
|
|
120734
121643
|
}
|
|
120735
121644
|
});
|
|
121645
|
+
Object.defineProperty(exports, "HEAP_RECLAIM_STEADY_STATE_INTERVAL_MS", {
|
|
121646
|
+
enumerable: true,
|
|
121647
|
+
get: function() {
|
|
121648
|
+
return HEAP_RECLAIM_STEADY_STATE_INTERVAL_MS;
|
|
121649
|
+
}
|
|
121650
|
+
});
|
|
120736
121651
|
Object.defineProperty(exports, "HEAP_RECLAIM_TRIGGER_MB", {
|
|
120737
121652
|
enumerable: true,
|
|
120738
121653
|
get: function() {
|
|
120739
121654
|
return HEAP_RECLAIM_TRIGGER_MB;
|
|
120740
121655
|
}
|
|
120741
121656
|
});
|
|
121657
|
+
Object.defineProperty(exports, "HEAP_SPACE_REPORT_MIN_MB", {
|
|
121658
|
+
enumerable: true,
|
|
121659
|
+
get: function() {
|
|
121660
|
+
return HEAP_SPACE_REPORT_MIN_MB;
|
|
121661
|
+
}
|
|
121662
|
+
});
|
|
120742
121663
|
Object.defineProperty(exports, "HEAP_WATCH_INTERVAL_MS", {
|
|
120743
121664
|
enumerable: true,
|
|
120744
121665
|
get: function() {
|
|
@@ -120811,6 +121732,12 @@ var require_manifest_python_deps_BqWrDjSN = __commonJS({
|
|
|
120811
121732
|
return RSS_BUDGET_RELEASE_RATIO;
|
|
120812
121733
|
}
|
|
120813
121734
|
});
|
|
121735
|
+
Object.defineProperty(exports, "RUNNER_HEAP_SNAPSHOT_ENV", {
|
|
121736
|
+
enumerable: true,
|
|
121737
|
+
get: function() {
|
|
121738
|
+
return RUNNER_HEAP_SNAPSHOT_ENV;
|
|
121739
|
+
}
|
|
121740
|
+
});
|
|
120814
121741
|
Object.defineProperty(exports, "RUNNER_HEAP_WATCH_INTERVAL_MS", {
|
|
120815
121742
|
enumerable: true,
|
|
120816
121743
|
get: function() {
|
|
@@ -120847,6 +121774,12 @@ var require_manifest_python_deps_BqWrDjSN = __commonJS({
|
|
|
120847
121774
|
return UdsLocalTransportServer;
|
|
120848
121775
|
}
|
|
120849
121776
|
});
|
|
121777
|
+
Object.defineProperty(exports, "ZERO_LOOP_DELAY", {
|
|
121778
|
+
enumerable: true,
|
|
121779
|
+
get: function() {
|
|
121780
|
+
return ZERO_LOOP_DELAY;
|
|
121781
|
+
}
|
|
121782
|
+
});
|
|
120850
121783
|
Object.defineProperty(exports, "__resetCapUsageRegistryForTests", {
|
|
120851
121784
|
enumerable: true,
|
|
120852
121785
|
get: function() {
|
|
@@ -120973,6 +121906,18 @@ var require_manifest_python_deps_BqWrDjSN = __commonJS({
|
|
|
120973
121906
|
return createDeferredHeapWatchSink;
|
|
120974
121907
|
}
|
|
120975
121908
|
});
|
|
121909
|
+
Object.defineProperty(exports, "createEventPlaneMeter", {
|
|
121910
|
+
enumerable: true,
|
|
121911
|
+
get: function() {
|
|
121912
|
+
return createEventPlaneMeter;
|
|
121913
|
+
}
|
|
121914
|
+
});
|
|
121915
|
+
Object.defineProperty(exports, "createEventPlaneReader", {
|
|
121916
|
+
enumerable: true,
|
|
121917
|
+
get: function() {
|
|
121918
|
+
return createEventPlaneReader;
|
|
121919
|
+
}
|
|
121920
|
+
});
|
|
120976
121921
|
Object.defineProperty(exports, "createHubCapForwardService", {
|
|
120977
121922
|
enumerable: true,
|
|
120978
121923
|
get: function() {
|
|
@@ -120991,6 +121936,12 @@ var require_manifest_python_deps_BqWrDjSN = __commonJS({
|
|
|
120991
121936
|
return createLocalTransport;
|
|
120992
121937
|
}
|
|
120993
121938
|
});
|
|
121939
|
+
Object.defineProperty(exports, "createLoopDelayMeter", {
|
|
121940
|
+
enumerable: true,
|
|
121941
|
+
get: function() {
|
|
121942
|
+
return createLoopDelayMeter;
|
|
121943
|
+
}
|
|
121944
|
+
});
|
|
120994
121945
|
Object.defineProperty(exports, "createParentUnownedCallHandler", {
|
|
120995
121946
|
enumerable: true,
|
|
120996
121947
|
get: function() {
|
|
@@ -121045,12 +121996,36 @@ var require_manifest_python_deps_BqWrDjSN = __commonJS({
|
|
|
121045
121996
|
return deserializeTypedArrays;
|
|
121046
121997
|
}
|
|
121047
121998
|
});
|
|
121999
|
+
Object.defineProperty(exports, "diffEventPlane", {
|
|
122000
|
+
enumerable: true,
|
|
122001
|
+
get: function() {
|
|
122002
|
+
return diffEventPlane;
|
|
122003
|
+
}
|
|
122004
|
+
});
|
|
122005
|
+
Object.defineProperty(exports, "emitHeapDiagnosticReport", {
|
|
122006
|
+
enumerable: true,
|
|
122007
|
+
get: function() {
|
|
122008
|
+
return emitHeapDiagnosticReport;
|
|
122009
|
+
}
|
|
122010
|
+
});
|
|
121048
122011
|
Object.defineProperty(exports, "encodeFrame", {
|
|
121049
122012
|
enumerable: true,
|
|
121050
122013
|
get: function() {
|
|
121051
122014
|
return encodeFrame;
|
|
121052
122015
|
}
|
|
121053
122016
|
});
|
|
122017
|
+
Object.defineProperty(exports, "formatEventPlane", {
|
|
122018
|
+
enumerable: true,
|
|
122019
|
+
get: function() {
|
|
122020
|
+
return formatEventPlane;
|
|
122021
|
+
}
|
|
122022
|
+
});
|
|
122023
|
+
Object.defineProperty(exports, "formatHeapSpaces", {
|
|
122024
|
+
enumerable: true,
|
|
122025
|
+
get: function() {
|
|
122026
|
+
return formatHeapSpaces;
|
|
122027
|
+
}
|
|
122028
|
+
});
|
|
121054
122029
|
Object.defineProperty(exports, "getBrokerEventBus", {
|
|
121055
122030
|
enumerable: true,
|
|
121056
122031
|
get: function() {
|
|
@@ -121099,6 +122074,18 @@ var require_manifest_python_deps_BqWrDjSN = __commonJS({
|
|
|
121099
122074
|
return getWorkerNativeCapSnapshot;
|
|
121100
122075
|
}
|
|
121101
122076
|
});
|
|
122077
|
+
Object.defineProperty(exports, "heapSnapshotAuthorised", {
|
|
122078
|
+
enumerable: true,
|
|
122079
|
+
get: function() {
|
|
122080
|
+
return heapSnapshotAuthorised;
|
|
122081
|
+
}
|
|
122082
|
+
});
|
|
122083
|
+
Object.defineProperty(exports, "heapSpaceField", {
|
|
122084
|
+
enumerable: true,
|
|
122085
|
+
get: function() {
|
|
122086
|
+
return heapSpaceField;
|
|
122087
|
+
}
|
|
122088
|
+
});
|
|
121102
122089
|
Object.defineProperty(exports, "hubMainRssBudget", {
|
|
121103
122090
|
enumerable: true,
|
|
121104
122091
|
get: function() {
|
|
@@ -121159,6 +122146,24 @@ var require_manifest_python_deps_BqWrDjSN = __commonJS({
|
|
|
121159
122146
|
return parseRssBudgetMb;
|
|
121160
122147
|
}
|
|
121161
122148
|
});
|
|
122149
|
+
Object.defineProperty(exports, "readHeapSpaces", {
|
|
122150
|
+
enumerable: true,
|
|
122151
|
+
get: function() {
|
|
122152
|
+
return readHeapSpaces;
|
|
122153
|
+
}
|
|
122154
|
+
});
|
|
122155
|
+
Object.defineProperty(exports, "readMoleculerFanoutMode", {
|
|
122156
|
+
enumerable: true,
|
|
122157
|
+
get: function() {
|
|
122158
|
+
return readMoleculerFanoutMode;
|
|
122159
|
+
}
|
|
122160
|
+
});
|
|
122161
|
+
Object.defineProperty(exports, "reclaimIntervalMs", {
|
|
122162
|
+
enumerable: true,
|
|
122163
|
+
get: function() {
|
|
122164
|
+
return reclaimIntervalMs;
|
|
122165
|
+
}
|
|
122166
|
+
});
|
|
121162
122167
|
Object.defineProperty(exports, "registerEventBusService", {
|
|
121163
122168
|
enumerable: true,
|
|
121164
122169
|
get: function() {
|
|
@@ -121189,6 +122194,12 @@ var require_manifest_python_deps_BqWrDjSN = __commonJS({
|
|
|
121189
122194
|
return runNpm;
|
|
121190
122195
|
}
|
|
121191
122196
|
});
|
|
122197
|
+
Object.defineProperty(exports, "selectReportedSpaces", {
|
|
122198
|
+
enumerable: true,
|
|
122199
|
+
get: function() {
|
|
122200
|
+
return selectReportedSpaces;
|
|
122201
|
+
}
|
|
122202
|
+
});
|
|
121192
122203
|
Object.defineProperty(exports, "serializeTypedArrays", {
|
|
121193
122204
|
enumerable: true,
|
|
121194
122205
|
get: function() {
|
|
@@ -125057,7 +126068,7 @@ var require_dist3 = __commonJS({
|
|
|
125057
126068
|
"use strict";
|
|
125058
126069
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
125059
126070
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
125060
|
-
var require_dist10 =
|
|
126071
|
+
var require_dist10 = require_dist_C7uZ_fOb();
|
|
125061
126072
|
var require_builtins_alerts_alerts_addon = require_alerts_addon();
|
|
125062
126073
|
require_alerts();
|
|
125063
126074
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
@@ -125082,8 +126093,8 @@ var require_dist3 = __commonJS({
|
|
|
125082
126093
|
require_system_config();
|
|
125083
126094
|
var require_builtins_winston_logging_index = require_winston_logging();
|
|
125084
126095
|
var require_file_data_plane = require_file_data_plane_DO8KbxCe();
|
|
125085
|
-
var require_tls$1 =
|
|
125086
|
-
var require_manifest_python_deps =
|
|
126096
|
+
var require_tls$1 = require_tls_BxQlomxd();
|
|
126097
|
+
var require_manifest_python_deps = require_manifest_python_deps_CRTx_j4k();
|
|
125087
126098
|
var require_resource_monitor = require_resource_monitor_CdnzxBLP();
|
|
125088
126099
|
var require_custom_action_registry = require_custom_action_registry_jY0NOZK8();
|
|
125089
126100
|
var zod = require_zod();
|
|
@@ -125095,11 +126106,11 @@ var require_dist3 = __commonJS({
|
|
|
125095
126106
|
var node_child_process = __require("child_process");
|
|
125096
126107
|
var node_util = __require("util");
|
|
125097
126108
|
node_util = require_chunk.__toESM(node_util);
|
|
125098
|
-
var node_os = __require("os");
|
|
125099
|
-
node_os = require_chunk.__toESM(node_os);
|
|
125100
126109
|
var node_fs = __require("fs");
|
|
125101
126110
|
var node_fs$1 = require_chunk.__toESM(node_fs, 1);
|
|
125102
126111
|
node_fs = require_chunk.__toESM(node_fs);
|
|
126112
|
+
var node_os = __require("os");
|
|
126113
|
+
node_os = require_chunk.__toESM(node_os);
|
|
125103
126114
|
var node_http = __require("http");
|
|
125104
126115
|
var node_vm = __require("vm");
|
|
125105
126116
|
node_vm = require_chunk.__toESM(node_vm);
|
|
@@ -205454,6 +206465,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
205454
206465
|
exports.ConsoleLoggingAddon = require_builtins_console_logging_index.ConsoleLoggingAddon$1;
|
|
205455
206466
|
exports.CoreBlocksAddon = require_builtins_core_blocks_core_blocks_addon.CoreBlocksAddon;
|
|
205456
206467
|
exports.CustomActionRegistry = require_custom_action_registry.CustomActionRegistry;
|
|
206468
|
+
exports.DECISIVE_HEAP_SPACES = require_manifest_python_deps.DECISIVE_HEAP_SPACES;
|
|
205457
206469
|
exports.DEFAULT_DATA_PATH = DEFAULT_DATA_PATH;
|
|
205458
206470
|
exports.DEFAULT_LAN_HTTP_PORT = require_tls$1.DEFAULT_LAN_HTTP_PORT;
|
|
205459
206471
|
exports.DEFAULT_LOG_LEVEL = DEFAULT_LOG_LEVEL;
|
|
@@ -205463,6 +206475,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
205463
206475
|
exports.DeviceManagerAddon = require_builtins_device_manager_device_manager_addon.DeviceManagerAddon;
|
|
205464
206476
|
exports.DeviceRegistry = require_manifest_python_deps.DeviceRegistry;
|
|
205465
206477
|
exports.DeviceStore = require_builtins_sqlite_storage_index.DeviceStore$1;
|
|
206478
|
+
exports.EVENT_PLANE_TOP_N = require_manifest_python_deps.EVENT_PLANE_TOP_N;
|
|
205466
206479
|
exports.EVENT_TOPIC_PREFIX = require_manifest_python_deps.EVENT_TOPIC_PREFIX;
|
|
205467
206480
|
exports.EngineManagerResolver = EngineManagerResolver;
|
|
205468
206481
|
exports.EventBus = EventBus;
|
|
@@ -205475,7 +206488,9 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
205475
206488
|
exports.HEALTH_MONITOR_RETRY_INTERVALS_MS = HEALTH_MONITOR_RETRY_INTERVALS_MS;
|
|
205476
206489
|
exports.HEALTH_MONITOR_TICK_MS = HEALTH_MONITOR_TICK_MS;
|
|
205477
206490
|
exports.HEAP_RECLAIM_MIN_INTERVAL_MS = require_manifest_python_deps.HEAP_RECLAIM_MIN_INTERVAL_MS;
|
|
206491
|
+
exports.HEAP_RECLAIM_STEADY_STATE_INTERVAL_MS = require_manifest_python_deps.HEAP_RECLAIM_STEADY_STATE_INTERVAL_MS;
|
|
205478
206492
|
exports.HEAP_RECLAIM_TRIGGER_MB = require_manifest_python_deps.HEAP_RECLAIM_TRIGGER_MB;
|
|
206493
|
+
exports.HEAP_SPACE_REPORT_MIN_MB = require_manifest_python_deps.HEAP_SPACE_REPORT_MIN_MB;
|
|
205479
206494
|
exports.HEAP_WATCH_INTERVAL_MS = require_manifest_python_deps.HEAP_WATCH_INTERVAL_MS;
|
|
205480
206495
|
exports.HEAP_WATCH_WARN_RATIO = require_manifest_python_deps.HEAP_WATCH_WARN_RATIO;
|
|
205481
206496
|
exports.HUB_CAP_FWD_ACTION = require_manifest_python_deps.HUB_CAP_FWD_ACTION;
|
|
@@ -205524,6 +206539,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
205524
206539
|
exports.RESTART_MARKER_FILE = RESTART_MARKER_FILE;
|
|
205525
206540
|
exports.RSS_BUDGET_REANNOUNCE_MIN_MS = require_manifest_python_deps.RSS_BUDGET_REANNOUNCE_MIN_MS;
|
|
205526
206541
|
exports.RSS_BUDGET_RELEASE_RATIO = require_manifest_python_deps.RSS_BUDGET_RELEASE_RATIO;
|
|
206542
|
+
exports.RUNNER_HEAP_SNAPSHOT_ENV = require_manifest_python_deps.RUNNER_HEAP_SNAPSHOT_ENV;
|
|
205527
206543
|
exports.RUNNER_HEAP_WATCH_INTERVAL_MS = require_manifest_python_deps.RUNNER_HEAP_WATCH_INTERVAL_MS;
|
|
205528
206544
|
exports.RUNNER_RSS_BUDGET_ENV = require_manifest_python_deps.RUNNER_RSS_BUDGET_ENV;
|
|
205529
206545
|
exports.RUNTIME_DEFAULTS = require_dist10.RUNTIME_DEFAULTS;
|
|
@@ -205552,6 +206568,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
205552
206568
|
exports.UserManager = require_builtins_local_auth_local_auth_addon.UserManager;
|
|
205553
206569
|
exports.WinstonDestination = require_builtins_winston_logging_index.WinstonDestination$1;
|
|
205554
206570
|
exports.WinstonLoggingAddon = require_builtins_winston_logging_index.WinstonLoggingAddon$1;
|
|
206571
|
+
exports.ZERO_LOOP_DELAY = require_manifest_python_deps.ZERO_LOOP_DELAY;
|
|
205555
206572
|
exports.__resetCapUsageRegistryForTests = require_manifest_python_deps.__resetCapUsageRegistryForTests;
|
|
205556
206573
|
exports.__resetLoggingGateForTests = __resetLoggingGateForTests;
|
|
205557
206574
|
exports.adaptBrokerToCluster = require_manifest_python_deps.adaptBrokerToCluster;
|
|
@@ -205603,11 +206620,14 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
205603
206620
|
exports.createCoreCapService = createCoreCapService;
|
|
205604
206621
|
exports.createDeferredHeapWatchSink = require_manifest_python_deps.createDeferredHeapWatchSink;
|
|
205605
206622
|
exports.createDoorSettingsView = createDoorSettingsView;
|
|
206623
|
+
exports.createEventPlaneMeter = require_manifest_python_deps.createEventPlaneMeter;
|
|
206624
|
+
exports.createEventPlaneReader = require_manifest_python_deps.createEventPlaneReader;
|
|
205606
206625
|
exports.createFileDataPlaneHandler = require_file_data_plane.createFileDataPlaneHandler;
|
|
205607
206626
|
exports.createHubCapForwardService = require_manifest_python_deps.createHubCapForwardService;
|
|
205608
206627
|
exports.createHubService = createHubService;
|
|
205609
206628
|
exports.createKernelHwAccel = require_manifest_python_deps.createKernelHwAccel;
|
|
205610
206629
|
exports.createLocalTransport = require_manifest_python_deps.createLocalTransport;
|
|
206630
|
+
exports.createLoopDelayMeter = require_manifest_python_deps.createLoopDelayMeter;
|
|
205611
206631
|
exports.createParentUnownedCallHandler = require_manifest_python_deps.createParentUnownedCallHandler;
|
|
205612
206632
|
exports.createProcessService = createProcessService;
|
|
205613
206633
|
exports.createReadinessService = createReadinessService;
|
|
@@ -205625,6 +206645,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
205625
206645
|
exports.describeProviderKindDrift = describeProviderKindDrift;
|
|
205626
206646
|
exports.describeRss = require_manifest_python_deps.describeRss;
|
|
205627
206647
|
exports.detectWorkspacePackagesDir = detectWorkspacePackagesDir;
|
|
206648
|
+
exports.diffEventPlane = require_manifest_python_deps.diffEventPlane;
|
|
205628
206649
|
Object.defineProperty(exports, "downloadBinary", {
|
|
205629
206650
|
enumerable: true,
|
|
205630
206651
|
get: function() {
|
|
@@ -205634,6 +206655,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
205634
206655
|
exports.downloadFile = require_file_data_plane.downloadFile;
|
|
205635
206656
|
exports.downloadModel = require_file_data_plane.downloadModel;
|
|
205636
206657
|
exports.emitDownForOwnedCaps = require_dist10.emitDownForOwnedCaps;
|
|
206658
|
+
exports.emitHeapDiagnosticReport = require_manifest_python_deps.emitHeapDiagnosticReport;
|
|
205637
206659
|
exports.encodeFrame = require_manifest_python_deps.encodeFrame;
|
|
205638
206660
|
exports.ensureAddonNativePrebuilds = ensureAddonNativePrebuilds;
|
|
205639
206661
|
Object.defineProperty(exports, "ensureBinary", {
|
|
@@ -205668,6 +206690,8 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
205668
206690
|
return _camstack_types_node.findInPath;
|
|
205669
206691
|
}
|
|
205670
206692
|
});
|
|
206693
|
+
exports.formatEventPlane = require_manifest_python_deps.formatEventPlane;
|
|
206694
|
+
exports.formatHeapSpaces = require_manifest_python_deps.formatHeapSpaces;
|
|
205671
206695
|
exports.formatLogLine = require_formatter.formatLogLine;
|
|
205672
206696
|
exports.getBrokerEventBus = require_manifest_python_deps.getBrokerEventBus;
|
|
205673
206697
|
exports.getCapUsageRegistry = require_manifest_python_deps.getCapUsageRegistry;
|
|
@@ -205700,6 +206724,8 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
205700
206724
|
exports.getWorkerDeviceRegistry = require_manifest_python_deps.getWorkerDeviceRegistry;
|
|
205701
206725
|
exports.hasDotNode = hasDotNode;
|
|
205702
206726
|
exports.hashClusterSecret = hashClusterSecret;
|
|
206727
|
+
exports.heapSnapshotAuthorised = require_manifest_python_deps.heapSnapshotAuthorised;
|
|
206728
|
+
exports.heapSpaceField = require_manifest_python_deps.heapSpaceField;
|
|
205703
206729
|
exports.hubMainRssBudget = require_manifest_python_deps.hubMainRssBudget;
|
|
205704
206730
|
exports.installManifestNativeDeps = require_manifest_python_deps.installManifestNativeDeps;
|
|
205705
206731
|
exports.installManifestPythonDeps = require_manifest_python_deps.installManifestPythonDeps;
|
|
@@ -205738,11 +206764,14 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
205738
206764
|
exports.proxyToUpstream = proxyToUpstream;
|
|
205739
206765
|
exports.quarantineAddonResidue = quarantineAddonResidue;
|
|
205740
206766
|
exports.readExtraSans = require_tls$1.readExtraSans;
|
|
206767
|
+
exports.readHeapSpaces = require_manifest_python_deps.readHeapSpaces;
|
|
205741
206768
|
exports.readLanHttpState = require_tls$1.readLanHttpState;
|
|
206769
|
+
exports.readMoleculerFanoutMode = require_manifest_python_deps.readMoleculerFanoutMode;
|
|
205742
206770
|
exports.readPendingRestart = readPendingRestart;
|
|
205743
206771
|
exports.readTlsAccessStatus = require_tls$1.readTlsAccessStatus;
|
|
205744
206772
|
exports.readTlsMode = require_tls$1.readTlsMode;
|
|
205745
206773
|
exports.readinessKey = require_dist10.readinessKey;
|
|
206774
|
+
exports.reclaimIntervalMs = require_manifest_python_deps.reclaimIntervalMs;
|
|
205746
206775
|
exports.registerEventBusService = require_manifest_python_deps.registerEventBusService;
|
|
205747
206776
|
exports.registerLanHttpHandler = require_tls$1.registerLanHttpHandler;
|
|
205748
206777
|
exports.reissueTlsLeaf = require_tls$1.reissueTlsLeaf;
|
|
@@ -205756,6 +206785,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
|
|
|
205756
206785
|
exports.scopesAllowAddon = require_dist10.scopesAllowAddon;
|
|
205757
206786
|
exports.scopesAllowDeviceCap = require_dist10.scopesAllowDeviceCap;
|
|
205758
206787
|
exports.selectAddonResidue = selectAddonResidue;
|
|
206788
|
+
exports.selectReportedSpaces = require_manifest_python_deps.selectReportedSpaces;
|
|
205759
206789
|
exports.serializeTypedArrays = require_manifest_python_deps.serializeTypedArrays;
|
|
205760
206790
|
exports.setHubConnected = require_manifest_python_deps.setHubConnected;
|
|
205761
206791
|
exports.setNodeEventInterest = require_manifest_python_deps.setNodeEventInterest;
|
|
@@ -214762,6 +215792,38 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
214762
215792
|
/** Wall-clock uptime (seconds). Parsed from `ps etime`. */
|
|
214763
215793
|
uptimeSec: zod.z.number()
|
|
214764
215794
|
});
|
|
215795
|
+
var ContainerMemoryPointSchema = zod.z.object({
|
|
215796
|
+
/** Which hierarchy answered, so a reading is never ambiguous. */
|
|
215797
|
+
source: zod.z.enum(["cgroup-v2", "cgroup-v1"]),
|
|
215798
|
+
/** `memory.current` (v2) / `memory.usage_in_bytes` (v1). Always known. */
|
|
215799
|
+
currentBytes: zod.z.number(),
|
|
215800
|
+
/** The cgroup's ceiling. `null` = NO LIMIT — never a sentinel, never zero. */
|
|
215801
|
+
limitBytes: zod.z.number().nullable(),
|
|
215802
|
+
/** Anonymous pages: the closest thing to "what the processes allocated". */
|
|
215803
|
+
anonBytes: zod.z.number().nullable(),
|
|
215804
|
+
/** Page cache. Charged to the cgroup, owned by no process. */
|
|
215805
|
+
fileBytes: zod.z.number().nullable(),
|
|
215806
|
+
/**
|
|
215807
|
+
* Shared memory — and the field that explained the largest single surprise.
|
|
215808
|
+
* The i915 driver backs GPU buffers with shmem, so an inference pool or a
|
|
215809
|
+
* hardware-decode session holding DRM objects is charged HERE and appears
|
|
215810
|
+
* nowhere in a `ps` scan.
|
|
215811
|
+
*/
|
|
215812
|
+
shmemBytes: zod.z.number().nullable(),
|
|
215813
|
+
/** Kernel slab charged to this cgroup. `null` on v1, which never publishes it. */
|
|
215814
|
+
slabBytes: zod.z.number().nullable(),
|
|
215815
|
+
/**
|
|
215816
|
+
* Shrinkable i915 GEM object bytes, from debugfs.
|
|
215817
|
+
*
|
|
215818
|
+
* **Host-wide across every DRM client, NOT cgroup-scoped.** It is not a
|
|
215819
|
+
* component of `currentBytes` and must not be subtracted from it; it says
|
|
215820
|
+
* what put the shmem there, where `shmemBytes` only says how much.
|
|
215821
|
+
*
|
|
215822
|
+
* `null` wherever debugfs is not mounted — which is inside every camstack
|
|
215823
|
+
* container today — and on any node with no Intel GPU.
|
|
215824
|
+
*/
|
|
215825
|
+
gpuShmemBytes: zod.z.number().nullable()
|
|
215826
|
+
}).extend({ atMs: zod.z.number() });
|
|
214765
215827
|
var DumpHeapSnapshotInputSchema = zod.z.object({
|
|
214766
215828
|
/** The addon whose runner should dump a heap snapshot. */
|
|
214767
215829
|
addonId: zod.z.string()
|
|
@@ -214811,6 +215873,21 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
214811
215873
|
/** One entry per function seen in the window, heaviest-first. */
|
|
214812
215874
|
series: zod.z.array(LoadFunctionSeriesSchema).readonly(),
|
|
214813
215875
|
/**
|
|
215876
|
+
* The CONTAINER's memory over the same window, oldest-first.
|
|
215877
|
+
*
|
|
215878
|
+
* Sits next to `series` rather than in a method of its own because the whole
|
|
215879
|
+
* question is a subtraction: the per-process rows in `series` sum to one
|
|
215880
|
+
* number and this one is another, and an operator who has to issue two calls
|
|
215881
|
+
* to compare them will compare two different instants. Same reader, same
|
|
215882
|
+
* `sinceMs`, same `bucketMs`, same timestamps.
|
|
215883
|
+
*
|
|
215884
|
+
* **EMPTY means ABSENT, never zero.** A node with no cgroup — a developer
|
|
215885
|
+
* Mac, a bare-metal host, a container with the hierarchy hidden — reports no
|
|
215886
|
+
* points at all. A zero here would be indistinguishable from a healthy
|
|
215887
|
+
* container and is precisely the lie this field exists to avoid.
|
|
215888
|
+
*/
|
|
215889
|
+
containerMemory: zod.z.array(ContainerMemoryPointSchema).readonly(),
|
|
215890
|
+
/**
|
|
214814
215891
|
* Width of one returned bucket, in ms. Equals the sampling cadence when no
|
|
214815
215892
|
* reduction was needed — so a caller can always say what one point covers
|
|
214816
215893
|
* without having to know whether it was reduced.
|
|
@@ -420662,7 +421739,17 @@ var require_main4 = __commonJS({
|
|
|
420662
421739
|
const heapReclaimer = (0, system_1.createV8Reclaimer)();
|
|
420663
421740
|
const heapReclaim = heapReclaimer === void 0 ? void 0 : { reclaim: heapReclaimer };
|
|
420664
421741
|
const heapWatchSink = (0, system_1.createDeferredHeapWatchSink)(system_1.HUB_MAIN_HEAP_WATCH_LABEL);
|
|
420665
|
-
|
|
421742
|
+
let moleculerForEventPlane = null;
|
|
421743
|
+
(0, system_1.startHeapWatch)(system_1.HUB_MAIN_HEAP_WATCH_LABEL, heapWatchSink.sink, void 0, heapReclaim, void 0, void 0, true, (0, system_1.hubMainRssBudget)(), {
|
|
421744
|
+
eventPlane: (0, system_1.createEventPlaneReader)({
|
|
421745
|
+
registry: () => moleculerForEventPlane?.childRegistry ?? null,
|
|
421746
|
+
crossNodeStats: () => {
|
|
421747
|
+
const broker = moleculerForEventPlane?.broker;
|
|
421748
|
+
return broker === void 0 ? null : (0, system_1.getMoleculerEventStats)(broker);
|
|
421749
|
+
},
|
|
421750
|
+
crossNodeMode: () => (0, system_1.readMoleculerFanoutMode)()
|
|
421751
|
+
})
|
|
421752
|
+
});
|
|
420666
421753
|
cleanupOrphanProcesses();
|
|
420667
421754
|
let spaIndexHtml = null;
|
|
420668
421755
|
const configPath = process.env.CONFIG_PATH ?? path.join(process.env.CAMSTACK_DATA ?? path.join(process.cwd(), "camstack-data"), "config.yaml");
|
|
@@ -420782,6 +421869,7 @@ var require_main4 = __commonJS({
|
|
|
420782
421869
|
console.log("[bootstrap] app.init() complete \u2014 all onModuleInit hooks have run");
|
|
420783
421870
|
capabilityRegistry.ready();
|
|
420784
421871
|
const moleculer = app.get(moleculer_service_1.MoleculerService);
|
|
421872
|
+
moleculerForEventPlane = moleculer;
|
|
420785
421873
|
moleculer.registerLogReceiver();
|
|
420786
421874
|
capabilityRegistry.registerProvider("model-distributor", "$hub", (0, model_distributor_js_1.buildModelDistributorProvider)(moleculer, loggingService));
|
|
420787
421875
|
try {
|