rigscope 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +2 -2
- package/.next/build-manifest.json +2 -2
- package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +3 -3
- package/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +3 -3
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/administration/page_client-reference-manifest.js +1 -1
- package/.next/server/app/administration.html +1 -1
- package/.next/server/app/administration.rsc +3 -3
- package/.next/server/app/administration.segments/_full.segment.rsc +3 -3
- package/.next/server/app/administration.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/administration.segments/administration/__PAGE__.segment.rsc +3 -3
- package/.next/server/app/alerts/page_client-reference-manifest.js +1 -1
- package/.next/server/app/alerts.html +1 -1
- package/.next/server/app/alerts.rsc +3 -3
- package/.next/server/app/alerts.segments/_full.segment.rsc +3 -3
- package/.next/server/app/alerts.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/alerts.segments/alerts/__PAGE__.segment.rsc +3 -3
- package/.next/server/app/connections/page_client-reference-manifest.js +1 -1
- package/.next/server/app/connections.html +1 -1
- package/.next/server/app/connections.rsc +3 -3
- package/.next/server/app/connections.segments/_full.segment.rsc +3 -3
- package/.next/server/app/connections.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/connections.segments/connections/__PAGE__.segment.rsc +3 -3
- package/.next/server/app/history/page.js +2 -2
- package/.next/server/app/history/page_client-reference-manifest.js +1 -1
- package/.next/server/app/history.html +1 -1
- package/.next/server/app/history.rsc +6 -6
- package/.next/server/app/history.segments/_full.segment.rsc +6 -6
- package/.next/server/app/history.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/history.segments/history/__PAGE__.segment.rsc +6 -6
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +3 -3
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +3 -3
- package/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login.html +1 -1
- package/.next/server/app/login.rsc +3 -3
- package/.next/server/app/login.segments/_full.segment.rsc +3 -3
- package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +3 -3
- package/.next/server/app/machines/[machineId]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/processes/page.js +1 -1
- package/.next/server/app/processes/page_client-reference-manifest.js +1 -1
- package/.next/server/app/processes.html +1 -1
- package/.next/server/app/processes.rsc +4 -4
- package/.next/server/app/processes.segments/_full.segment.rsc +4 -4
- package/.next/server/app/processes.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/processes.segments/processes/__PAGE__.segment.rsc +4 -4
- package/.next/server/app-paths-manifest.json +2 -2
- package/.next/server/chunks/161.js +1 -1
- package/.next/server/chunks/168.js +1 -1
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/route-cache/APP_PAGE/16d1ab46157a868f438fa01e04bf53e805c71cddec593ea1535905c59625cd42/$/login.html +1 -0
- package/.next/server/route-cache/APP_PAGE/16d1ab46157a868f438fa01e04bf53e805c71cddec593ea1535905c59625cd42/$/login.meta +1 -0
- package/.next/server/route-cache/APP_PAGE/16d1ab46157a868f438fa01e04bf53e805c71cddec593ea1535905c59625cd42/$/login.rsc +26 -0
- package/.next/server/route-cache/APP_PAGE/16d1ab46157a868f438fa01e04bf53e805c71cddec593ea1535905c59625cd42/$/login.segments/_full.segment.rsc +26 -0
- package/.next/server/route-cache/APP_PAGE/16d1ab46157a868f438fa01e04bf53e805c71cddec593ea1535905c59625cd42/$/login.segments/_tree.segment.rsc +4 -0
- package/.next/server/route-cache/APP_PAGE/16d1ab46157a868f438fa01e04bf53e805c71cddec593ea1535905c59625cd42/$/login.segments/login/__PAGE__.segment.rsc +32 -0
- package/.next/server/route-cache/APP_PAGE/41da0ef926a63354a29f601d8e8d0a5951196c45ebcd28b7d4708fb7f56f3bf1/$/_not-found.html +1 -0
- package/.next/server/route-cache/APP_PAGE/41da0ef926a63354a29f601d8e8d0a5951196c45ebcd28b7d4708fb7f56f3bf1/$/_not-found.meta +1 -0
- package/.next/server/route-cache/APP_PAGE/41da0ef926a63354a29f601d8e8d0a5951196c45ebcd28b7d4708fb7f56f3bf1/$/_not-found.rsc +24 -0
- package/.next/server/route-cache/APP_PAGE/41da0ef926a63354a29f601d8e8d0a5951196c45ebcd28b7d4708fb7f56f3bf1/$/_not-found.segments/_full.segment.rsc +24 -0
- package/.next/server/route-cache/APP_PAGE/41da0ef926a63354a29f601d8e8d0a5951196c45ebcd28b7d4708fb7f56f3bf1/$/_not-found.segments/_not-found/__PAGE__.segment.rsc +30 -0
- package/.next/server/route-cache/APP_PAGE/41da0ef926a63354a29f601d8e8d0a5951196c45ebcd28b7d4708fb7f56f3bf1/$/_not-found.segments/_tree.segment.rsc +4 -0
- package/.next/server/route-cache/APP_PAGE/c6377dd9ce6a1c2cd100eb4344e843eb4639b9ed26f84643f77680e9eb454c4b/$/index.html +1 -0
- package/.next/server/route-cache/APP_PAGE/c6377dd9ce6a1c2cd100eb4344e843eb4639b9ed26f84643f77680e9eb454c4b/$/index.meta +1 -0
- package/.next/server/route-cache/APP_PAGE/c6377dd9ce6a1c2cd100eb4344e843eb4639b9ed26f84643f77680e9eb454c4b/$/index.rsc +26 -0
- package/.next/server/route-cache/APP_PAGE/c6377dd9ce6a1c2cd100eb4344e843eb4639b9ed26f84643f77680e9eb454c4b/$/index.segments/__PAGE__.segment.rsc +31 -0
- package/.next/server/route-cache/APP_PAGE/c6377dd9ce6a1c2cd100eb4344e843eb4639b9ed26f84643f77680e9eb454c4b/$/index.segments/_full.segment.rsc +26 -0
- package/.next/server/route-cache/APP_PAGE/c6377dd9ce6a1c2cd100eb4344e843eb4639b9ed26f84643f77680e9eb454c4b/$/index.segments/_tree.segment.rsc +3 -0
- package/.next/static/chunks/408-4fe7147e38981ee1.js +1 -0
- package/.next/static/chunks/939-514e554087419c71.js +1 -0
- package/.next/static/chunks/app/history/page-69ea64476ee5db85.js +3 -0
- package/.next/static/chunks/app/processes/{page-e471ed23a1d5632f.js → page-0e98a4a64e829c5f.js} +1 -1
- package/.next/static/css/3fbf75e4c471c6a8.css +1 -0
- package/ARCHITECTURE.md +30 -4
- package/CHANGELOG.md +47 -2
- package/dist/cli.cjs +1627 -1042
- package/dist/collector.cjs +138 -226
- package/dist/hub.cjs +7 -20
- package/dist/ops.cjs +160 -33
- package/dist/system.cjs +869 -450
- package/docs/bottlenecks.md +4 -6
- package/docs/configuration.md +2 -0
- package/docs/installation.md +42 -7
- package/docs/operations.md +32 -16
- package/docs/releasing.md +21 -17
- package/docs/system-installation.md +11 -2
- package/package.json +1 -2
- package/.next/static/chunks/408-dc6158e0bb450ef6.js +0 -1
- package/.next/static/chunks/939-2600d7c8e583d5ef.js +0 -1
- package/.next/static/chunks/app/history/page-1475454737279ee0.js +0 -3
- package/.next/static/css/e45c0c7ef5ba0336.css +0 -1
- /package/.next/static/{NE6PGEiJxUnKRceuzUWPc → xjSDCOO8Gpm5iPO9tyRG5}/_buildManifest.js +0 -0
- /package/.next/static/{NE6PGEiJxUnKRceuzUWPc → xjSDCOO8Gpm5iPO9tyRG5}/_ssgManifest.js +0 -0
package/dist/collector.cjs
CHANGED
|
@@ -128,7 +128,6 @@ var ConfigError = class extends Error {
|
|
|
128
128
|
var DEFAULT_COLLECTOR_ID = "mock-collector";
|
|
129
129
|
var MOCK_HOSTNAME = "mock-machine";
|
|
130
130
|
var CONNECT_PATH = "/api/collector/connect";
|
|
131
|
-
var PREVIOUS_CONNECT_PATH = "/api/collector/v1/connect";
|
|
132
131
|
var MAX_DESTINATIONS = 8;
|
|
133
132
|
var DEFAULT_INTERVAL_MS = 1e3;
|
|
134
133
|
var MIN_INTERVAL_MS = 100;
|
|
@@ -205,7 +204,6 @@ function validateHubUrl(raw, label, issues) {
|
|
|
205
204
|
issues.push(`${label}: URL must include a host`);
|
|
206
205
|
return null;
|
|
207
206
|
}
|
|
208
|
-
if (parsed.pathname === PREVIOUS_CONNECT_PATH) parsed.pathname = CONNECT_PATH;
|
|
209
207
|
if (parsed.pathname !== CONNECT_PATH) {
|
|
210
208
|
issues.push(`${label}: path must be exactly ${CONNECT_PATH}`);
|
|
211
209
|
return null;
|
|
@@ -520,18 +518,26 @@ function defaultStatePath() {
|
|
|
520
518
|
function readState(path2) {
|
|
521
519
|
const stat = (0, import_node_fs2.lstatSync)(path2);
|
|
522
520
|
if (!stat.isFile() || stat.size > 64 * 1024 || (stat.mode & 63) !== 0) throw new Error("collector state must be a private regular file");
|
|
523
|
-
const
|
|
524
|
-
if (
|
|
521
|
+
const parsed = JSON.parse((0, import_node_fs2.readFileSync)(path2, "utf8"));
|
|
522
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("invalid collector state");
|
|
523
|
+
const raw = parsed;
|
|
524
|
+
if (Object.hasOwn(raw, "version") || Object.hasOwn(raw, "formatVersion")) {
|
|
525
|
+
throw new Error("collector state uses an older versioned shape; run rigscope install or upgrade to reset it");
|
|
526
|
+
}
|
|
527
|
+
if (typeof raw.collectorId !== "string" || !/^[\x21-\x7e]{1,128}$/.test(raw.collectorId) || !Array.isArray(raw.destinations)) throw new Error("invalid collector state");
|
|
525
528
|
const destinations = raw.destinations.length === 0 ? [] : [...parseCollectorConfig({ COLLECTOR_HUBS: JSON.stringify(raw.destinations) }).destinations];
|
|
526
|
-
|
|
527
|
-
|
|
529
|
+
const pending = raw.pendingEnrollments;
|
|
530
|
+
if (pending !== void 0 && (!Array.isArray(pending) || pending.length > 8 || pending.some((p) => !p || typeof p !== "object" || typeof p.url !== "string" || typeof p.requestId !== "string" || !/^[\x21-\x7e]{1,128}$/.test(p.requestId) || typeof p.recoverySecret !== "string" || !/^[A-Za-z0-9_-]{32,128}$/.test(p.recoverySecret)))) {
|
|
531
|
+
throw new Error("invalid pending enrollment recovery state");
|
|
532
|
+
}
|
|
533
|
+
const pendingEnrollments = pending?.map((value) => {
|
|
534
|
+
const pendingEnrollment = value;
|
|
528
535
|
const issues = [];
|
|
529
|
-
const url = validateHubUrl(
|
|
536
|
+
const url = validateHubUrl(pendingEnrollment.url, "pending enrollment", issues);
|
|
530
537
|
if (!url || issues.length) throw new ConfigError(issues);
|
|
531
|
-
return { ...
|
|
538
|
+
return { ...pendingEnrollment, url: url.href };
|
|
532
539
|
});
|
|
533
540
|
return {
|
|
534
|
-
version: 1,
|
|
535
541
|
collectorId: raw.collectorId,
|
|
536
542
|
destinations,
|
|
537
543
|
...pendingEnrollments === void 0 ? {} : { pendingEnrollments }
|
|
@@ -564,9 +570,14 @@ function updateInstallation(path2, change = (s) => s) {
|
|
|
564
570
|
state = readState(path2);
|
|
565
571
|
} catch (error) {
|
|
566
572
|
if (error.code !== "ENOENT") throw error;
|
|
567
|
-
state = {
|
|
573
|
+
state = { collectorId: (0, import_node_crypto2.randomUUID)(), destinations: [] };
|
|
568
574
|
}
|
|
569
|
-
const
|
|
575
|
+
const changed = change(state);
|
|
576
|
+
const next = {
|
|
577
|
+
collectorId: changed.collectorId,
|
|
578
|
+
destinations: changed.destinations,
|
|
579
|
+
...changed.pendingEnrollments === void 0 ? {} : { pendingEnrollments: changed.pendingEnrollments }
|
|
580
|
+
};
|
|
570
581
|
temporary = `${path2}.${(0, import_node_crypto2.randomUUID)()}.tmp`;
|
|
571
582
|
const out = (0, import_node_fs2.openSync)(temporary, "wx", 384);
|
|
572
583
|
try {
|
|
@@ -687,154 +698,6 @@ var import_node_os2 = require("node:os");
|
|
|
687
698
|
var import_node_fs5 = require("node:fs");
|
|
688
699
|
var import_ws = require("ws");
|
|
689
700
|
|
|
690
|
-
// src/contracts/telemetry.ts
|
|
691
|
-
var MAX_MESSAGE_BYTES = 262144;
|
|
692
|
-
var MAX_DETAIL_BYTES = 1048576;
|
|
693
|
-
var MAX_BATCH_RECORDS = 32;
|
|
694
|
-
var MAX_CORES = 1024;
|
|
695
|
-
var MAX_GPUS = 16;
|
|
696
|
-
var MAX_FILESYSTEMS = 64;
|
|
697
|
-
var MAX_DISKS = 64;
|
|
698
|
-
var MAX_INTERFACES = 64;
|
|
699
|
-
var MAX_ADDRESSES_PER_INTERFACE = 32;
|
|
700
|
-
var MAX_PROCESS_ROWS = 6e3;
|
|
701
|
-
var MAX_COLLECTION_FAILURES = 32;
|
|
702
|
-
var MIN_DETAIL_INTERVAL_MS = 1e3;
|
|
703
|
-
var MAX_DETAIL_INTERVAL_MS = 6e4;
|
|
704
|
-
var MIN_DETAIL_LEASE_MS = 5e3;
|
|
705
|
-
var MAX_DETAIL_LEASE_MS = 12e4;
|
|
706
|
-
var MAX_ID = 128;
|
|
707
|
-
var MAX_TEXT = 256;
|
|
708
|
-
var MIN_EPOCH = Date.parse("2000-01-01T00:00:00Z");
|
|
709
|
-
var MAX_EPOCH = Date.parse("2200-01-01T00:00:00Z");
|
|
710
|
-
var CAPABILITY_NAMES = ["metrics", "inventory", "processes"];
|
|
711
|
-
var METRIC_EXTENSION_NAMES = ["bottleneck-v1"];
|
|
712
|
-
var COLLECTOR_PROTOCOL_VERSION = "0.3.0";
|
|
713
|
-
function parseHubMessage(value) {
|
|
714
|
-
const o = obj(value, "hub message");
|
|
715
|
-
switch (o.type) {
|
|
716
|
-
case "welcome": {
|
|
717
|
-
keys(o, ["type", "hubRunId", "machineId", "delivery", "maxInFlightBatches"], "welcome", ["metricExtensions"]);
|
|
718
|
-
if (o.delivery !== "durable") throw new Error(`invalid welcome: unexpected delivery ${desc(o.delivery)}`);
|
|
719
|
-
const welcome = { type: "welcome", hubRunId: id(o.hubRunId, "hubRunId"), machineId: id(o.machineId, "machineId"), delivery: "durable", maxInFlightBatches: int(o.maxInFlightBatches, "maxInFlightBatches", 1, 64) };
|
|
720
|
-
if (hasOwn(o, "metricExtensions")) {
|
|
721
|
-
const extensions = arr(o.metricExtensions, "welcome.metricExtensions", 1, METRIC_EXTENSION_NAMES.length).map((extension) => oneOf(extension, METRIC_EXTENSION_NAMES, "welcome.metricExtensions"));
|
|
722
|
-
if (new Set(extensions).size !== extensions.length) throw new Error("invalid welcome: metricExtensions must be unique");
|
|
723
|
-
welcome.metricExtensions = extensions;
|
|
724
|
-
}
|
|
725
|
-
return welcome;
|
|
726
|
-
}
|
|
727
|
-
case "ack": {
|
|
728
|
-
keys(o, ["type", "accepted", "rejected"], "ack", ["retryAfterMs"]);
|
|
729
|
-
const accepted = arr(o.accepted, "ack.accepted", 0, MAX_BATCH_RECORDS * 64).map((r) => parseRef(r, []));
|
|
730
|
-
const rejected = arr(o.rejected, "ack.rejected", 0, MAX_BATCH_RECORDS * 64).map((r) => {
|
|
731
|
-
const ref = parseRef(r, ["reason"]);
|
|
732
|
-
return { ...ref, reason: text(r.reason, "reason", 0, MAX_TEXT) };
|
|
733
|
-
});
|
|
734
|
-
const out = { type: "ack", accepted, rejected };
|
|
735
|
-
if (hasOwn(o, "retryAfterMs")) out.retryAfterMs = int(o.retryAfterMs, "retryAfterMs", 0, 6e5);
|
|
736
|
-
return out;
|
|
737
|
-
}
|
|
738
|
-
case "detail.subscribe":
|
|
739
|
-
keys(o, ["type", "subscriptionId", "kind", "intervalMs", "leaseMs"], "detail.subscribe");
|
|
740
|
-
if (o.kind !== "processes") throw new Error("invalid detail.subscribe: unsupported kind");
|
|
741
|
-
return {
|
|
742
|
-
type: "detail.subscribe",
|
|
743
|
-
subscriptionId: id(o.subscriptionId, "subscriptionId"),
|
|
744
|
-
kind: "processes",
|
|
745
|
-
intervalMs: int(o.intervalMs, "intervalMs", MIN_DETAIL_INTERVAL_MS, MAX_DETAIL_INTERVAL_MS),
|
|
746
|
-
leaseMs: int(o.leaseMs, "leaseMs", MIN_DETAIL_LEASE_MS, MAX_DETAIL_LEASE_MS)
|
|
747
|
-
};
|
|
748
|
-
case "detail.cancel":
|
|
749
|
-
keys(o, ["type", "subscriptionId"], "detail.cancel");
|
|
750
|
-
return { type: "detail.cancel", subscriptionId: id(o.subscriptionId, "subscriptionId") };
|
|
751
|
-
default:
|
|
752
|
-
throw new Error(`invalid hub message: unsupported type ${desc(o.type)}`);
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
function projectTelemetryRecordForWire(record, extensions) {
|
|
756
|
-
if (extensions.includes("bottleneck-v1") || record.kind !== "metrics") return record;
|
|
757
|
-
return { ...record, payload: projectMetricsPayloadToBaseWire(record.payload) };
|
|
758
|
-
}
|
|
759
|
-
function projectMetricsPayloadToBaseWire(payload) {
|
|
760
|
-
return {
|
|
761
|
-
cpu: projectCpuToBaseWire(payload.cpu),
|
|
762
|
-
memory: projectMemoryToBaseWire(payload.memory),
|
|
763
|
-
swap: payload.swap,
|
|
764
|
-
gpus: payload.gpus,
|
|
765
|
-
disks: projectDisksToBaseWire(payload.disks),
|
|
766
|
-
network: payload.network
|
|
767
|
-
};
|
|
768
|
-
}
|
|
769
|
-
function projectCpuToBaseWire(cpu) {
|
|
770
|
-
if (cpu.status !== "ok") return cpu;
|
|
771
|
-
return { status: "ok", usagePercent: cpu.usagePercent, perCore: [...cpu.perCore] };
|
|
772
|
-
}
|
|
773
|
-
function projectMemoryToBaseWire(memory) {
|
|
774
|
-
if (memory.status !== "ok") return memory;
|
|
775
|
-
return { status: "ok", usedBytes: memory.usedBytes, totalBytes: memory.totalBytes };
|
|
776
|
-
}
|
|
777
|
-
function projectDisksToBaseWire(disks) {
|
|
778
|
-
if (disks.status !== "ok") return disks;
|
|
779
|
-
return {
|
|
780
|
-
status: "ok",
|
|
781
|
-
filesystems: disks.filesystems.map((filesystem) => filesystem.status === "ok" ? { id: filesystem.id, status: "ok", usedBytes: filesystem.usedBytes, totalBytes: filesystem.totalBytes } : filesystem),
|
|
782
|
-
devices: disks.devices.map((device) => device.status === "ok" ? { id: device.id, status: "ok", readBytesPerSec: device.readBytesPerSec, writeBytesPerSec: device.writeBytesPerSec } : device)
|
|
783
|
-
};
|
|
784
|
-
}
|
|
785
|
-
function parseRef(value, extra) {
|
|
786
|
-
const o = obj(value, "record ref");
|
|
787
|
-
keys(o, ["runId", "sequence", ...extra], "record ref");
|
|
788
|
-
return { runId: id(o.runId, "runId"), sequence: int(o.sequence, "sequence", 0, Number.MAX_SAFE_INTEGER) };
|
|
789
|
-
}
|
|
790
|
-
function obj(value, what) {
|
|
791
|
-
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error(`invalid ${what}: expected object, got ${desc(value)}`);
|
|
792
|
-
return value;
|
|
793
|
-
}
|
|
794
|
-
function keys(o, required, what, optional = []) {
|
|
795
|
-
const allowed = /* @__PURE__ */ new Set([...required, ...optional]);
|
|
796
|
-
for (const k of Object.keys(o)) if (!allowed.has(k)) throw new Error(`invalid ${what}: unexpected field "${k}"`);
|
|
797
|
-
for (const k of required) if (o[k] === void 0) throw new Error(`invalid ${what}: missing field "${k}"`);
|
|
798
|
-
for (const k of optional) if (hasOwn(o, k) && o[k] === void 0) throw new Error(`invalid ${what}: ${k} must not be undefined`);
|
|
799
|
-
}
|
|
800
|
-
function hasOwn(o, k) {
|
|
801
|
-
return Object.prototype.hasOwnProperty.call(o, k);
|
|
802
|
-
}
|
|
803
|
-
function arr(v, what, min, max) {
|
|
804
|
-
if (!Array.isArray(v)) throw new Error(`invalid ${what}: expected array`);
|
|
805
|
-
if (v.length < min || v.length > max) throw new Error(`invalid ${what}: length ${v.length} outside ${min}..${max}`);
|
|
806
|
-
return v;
|
|
807
|
-
}
|
|
808
|
-
function oneOf(v, options, what) {
|
|
809
|
-
if (typeof v !== "string" || !options.includes(v)) throw new Error(`invalid ${what}: unexpected value ${desc(v)}`);
|
|
810
|
-
return v;
|
|
811
|
-
}
|
|
812
|
-
function text(v, field, min, max) {
|
|
813
|
-
if (typeof v !== "string") throw new Error(`invalid ${field}: expected string, got ${desc(v)}`);
|
|
814
|
-
if (v.length < min || v.length > max) throw new Error(`invalid ${field}: length ${v.length} outside ${min}..${max}`);
|
|
815
|
-
return v;
|
|
816
|
-
}
|
|
817
|
-
function id(v, field) {
|
|
818
|
-
return text(v, field, 1, MAX_ID);
|
|
819
|
-
}
|
|
820
|
-
function int(v, field, min, max) {
|
|
821
|
-
if (typeof v !== "number" || !Number.isSafeInteger(v)) throw new Error(`invalid ${field}: expected safe integer, got ${desc(v)}`);
|
|
822
|
-
if (v < min || v > max) throw new Error(`invalid ${field}: ${v} outside ${min}..${max}`);
|
|
823
|
-
return v;
|
|
824
|
-
}
|
|
825
|
-
function desc(v) {
|
|
826
|
-
try {
|
|
827
|
-
const s = JSON.stringify(v);
|
|
828
|
-
if (typeof s === "string") return s.length <= 80 ? s : `${s.slice(0, 77)}...`;
|
|
829
|
-
} catch {
|
|
830
|
-
}
|
|
831
|
-
return String(v);
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
// src/contracts/index.ts
|
|
835
|
-
var MIN_TIMESTAMP_EPOCH = Date.parse("2000-01-01T00:00:00Z");
|
|
836
|
-
var MAX_TIMESTAMP_EPOCH = Date.parse("2200-01-01T00:00:00Z");
|
|
837
|
-
|
|
838
701
|
// collector/destinations/budget.ts
|
|
839
702
|
var DEFAULT_MAX_TOTAL_OUTBOX_BYTES = 256 * 1024 * 1024;
|
|
840
703
|
var DEFAULT_MAX_TOTAL_OUTBOX_DISK_BYTES = 640 * 1024 * 1024;
|
|
@@ -959,9 +822,7 @@ function serializeRecord(record) {
|
|
|
959
822
|
return { json, bytes: Buffer.byteLength(json, "utf8") };
|
|
960
823
|
}
|
|
961
824
|
function parseStoredRecord(json) {
|
|
962
|
-
|
|
963
|
-
if (record.protocolVersion === 2) delete record.protocolVersion;
|
|
964
|
-
return record;
|
|
825
|
+
return JSON.parse(json);
|
|
965
826
|
}
|
|
966
827
|
function fileBytes(file) {
|
|
967
828
|
try {
|
|
@@ -1025,10 +886,6 @@ var DestinationOutbox = class _DestinationOutbox {
|
|
|
1025
886
|
static open(opts) {
|
|
1026
887
|
const limits = { ...DEFAULT_OUTBOX_LIMITS, ...opts.limits };
|
|
1027
888
|
validateDiskLimit(limits.maxDiskBytes);
|
|
1028
|
-
if (opts.previousDir && opts.previousDir !== opts.dir && !fs.existsSync(opts.dir) && fs.existsSync(path.join(opts.previousDir, "outbox.sqlite"))) {
|
|
1029
|
-
fs.mkdirSync(path.dirname(opts.dir), { recursive: true, mode: 448 });
|
|
1030
|
-
fs.renameSync(opts.previousDir, opts.dir);
|
|
1031
|
-
}
|
|
1032
889
|
fs.mkdirSync(opts.dir, { recursive: true, mode: 448 });
|
|
1033
890
|
try {
|
|
1034
891
|
fs.chmodSync(opts.dir, 448);
|
|
@@ -1062,45 +919,15 @@ var DestinationOutbox = class _DestinationOutbox {
|
|
|
1062
919
|
db.exec(SCHEMA);
|
|
1063
920
|
const columns = db.prepare("PRAGMA table_info(outbox_records)").all();
|
|
1064
921
|
if (!columns.some((column) => column.name === "offered")) {
|
|
1065
|
-
|
|
1066
|
-
db.exec("UPDATE outbox_records SET offered = 1 WHERE kind = 'gap'");
|
|
922
|
+
throw new Error("outbox must use the canonical schema; reset or reinstall the unfinished installation");
|
|
1067
923
|
}
|
|
1068
924
|
db.prepare("UPDATE outbox_records SET state = 'pending' WHERE state = 'inflight'").run();
|
|
1069
925
|
const outbox = new _DestinationOutbox(opts, db, limits);
|
|
1070
926
|
outbox.configurePhysicalLimit();
|
|
1071
927
|
outbox.totalBytes = outbox.readTotalBytes();
|
|
1072
|
-
if (opts.previousDir && opts.previousDir !== opts.dir) outbox.importPrevious(opts.previousDir);
|
|
1073
928
|
opts.budget?.register(outbox);
|
|
1074
929
|
return outbox;
|
|
1075
930
|
}
|
|
1076
|
-
/** A partially upgraded installation may already have both URL-based queues. */
|
|
1077
|
-
importPrevious(dir) {
|
|
1078
|
-
const file = path.join(dir, "outbox.sqlite");
|
|
1079
|
-
if (!fs.existsSync(file)) return;
|
|
1080
|
-
const previous = new import_node_sqlite.DatabaseSync(file, { readOnly: true, timeout: BUSY_TIMEOUT_MS });
|
|
1081
|
-
try {
|
|
1082
|
-
const columns = previous.prepare("PRAGMA table_info(outbox_records)").all();
|
|
1083
|
-
const offered = columns.some((column) => column.name === "offered") ? "offered" : "CASE WHEN kind = 'gap' THEN 1 ELSE 0 END AS offered";
|
|
1084
|
-
const rows = previous.prepare(`SELECT json, ${offered} FROM outbox_records ORDER BY id`);
|
|
1085
|
-
const existing = this.db.prepare("SELECT id FROM outbox_records WHERE run_id = ? AND sequence = ?");
|
|
1086
|
-
const markOffered = this.db.prepare("UPDATE outbox_records SET offered = 1 WHERE run_id = ? AND sequence = ?");
|
|
1087
|
-
this.db.exec("BEGIN IMMEDIATE");
|
|
1088
|
-
try {
|
|
1089
|
-
for (const row of rows.iterate()) {
|
|
1090
|
-
const record = parseStoredRecord(row.json);
|
|
1091
|
-
if (!existing.get(record.runId, record.sequence)) this.insertRecord(record);
|
|
1092
|
-
if (row.offered) markOffered.run(record.runId, record.sequence);
|
|
1093
|
-
}
|
|
1094
|
-
this.db.exec("COMMIT");
|
|
1095
|
-
} catch (error) {
|
|
1096
|
-
this.db.exec("ROLLBACK");
|
|
1097
|
-
throw error;
|
|
1098
|
-
}
|
|
1099
|
-
} finally {
|
|
1100
|
-
previous.close();
|
|
1101
|
-
}
|
|
1102
|
-
fs.rmSync(dir, { recursive: true });
|
|
1103
|
-
}
|
|
1104
931
|
// -------------------------------------------------------------------------
|
|
1105
932
|
// Writes
|
|
1106
933
|
// -------------------------------------------------------------------------
|
|
@@ -1719,6 +1546,112 @@ var DestinationOutbox = class _DestinationOutbox {
|
|
|
1719
1546
|
}
|
|
1720
1547
|
};
|
|
1721
1548
|
|
|
1549
|
+
// src/contracts/telemetry.ts
|
|
1550
|
+
var MAX_MESSAGE_BYTES = 262144;
|
|
1551
|
+
var MAX_DETAIL_BYTES = 1048576;
|
|
1552
|
+
var MAX_BATCH_RECORDS = 32;
|
|
1553
|
+
var MAX_CORES = 1024;
|
|
1554
|
+
var MAX_GPUS = 16;
|
|
1555
|
+
var MAX_FILESYSTEMS = 64;
|
|
1556
|
+
var MAX_DISKS = 64;
|
|
1557
|
+
var MAX_INTERFACES = 64;
|
|
1558
|
+
var MAX_ADDRESSES_PER_INTERFACE = 32;
|
|
1559
|
+
var MAX_PROCESS_ROWS = 6e3;
|
|
1560
|
+
var MAX_COLLECTION_FAILURES = 32;
|
|
1561
|
+
var MIN_DETAIL_INTERVAL_MS = 1e3;
|
|
1562
|
+
var MAX_DETAIL_INTERVAL_MS = 6e4;
|
|
1563
|
+
var MIN_DETAIL_LEASE_MS = 5e3;
|
|
1564
|
+
var MAX_DETAIL_LEASE_MS = 12e4;
|
|
1565
|
+
var MAX_ID = 128;
|
|
1566
|
+
var MAX_TEXT = 256;
|
|
1567
|
+
var MIN_EPOCH = Date.parse("2000-01-01T00:00:00Z");
|
|
1568
|
+
var MAX_EPOCH = Date.parse("2200-01-01T00:00:00Z");
|
|
1569
|
+
var CAPABILITY_NAMES = ["metrics", "inventory", "processes"];
|
|
1570
|
+
function parseHubMessage(value) {
|
|
1571
|
+
const o = obj(value, "hub message");
|
|
1572
|
+
switch (o.type) {
|
|
1573
|
+
case "welcome": {
|
|
1574
|
+
keys(o, ["type", "hubRunId", "machineId", "delivery", "maxInFlightBatches"], "welcome");
|
|
1575
|
+
if (o.delivery !== "durable") throw new Error(`invalid welcome: unexpected delivery ${desc(o.delivery)}`);
|
|
1576
|
+
return { type: "welcome", hubRunId: id(o.hubRunId, "hubRunId"), machineId: id(o.machineId, "machineId"), delivery: "durable", maxInFlightBatches: int(o.maxInFlightBatches, "maxInFlightBatches", 1, 64) };
|
|
1577
|
+
}
|
|
1578
|
+
case "ack": {
|
|
1579
|
+
keys(o, ["type", "accepted", "rejected"], "ack", ["retryAfterMs"]);
|
|
1580
|
+
const accepted = arr(o.accepted, "ack.accepted", 0, MAX_BATCH_RECORDS * 64).map((r) => parseRef(r, []));
|
|
1581
|
+
const rejected = arr(o.rejected, "ack.rejected", 0, MAX_BATCH_RECORDS * 64).map((r) => {
|
|
1582
|
+
const ref = parseRef(r, ["reason"]);
|
|
1583
|
+
return { ...ref, reason: text(r.reason, "reason", 0, MAX_TEXT) };
|
|
1584
|
+
});
|
|
1585
|
+
const out = { type: "ack", accepted, rejected };
|
|
1586
|
+
if (hasOwn(o, "retryAfterMs")) out.retryAfterMs = int(o.retryAfterMs, "retryAfterMs", 0, 6e5);
|
|
1587
|
+
return out;
|
|
1588
|
+
}
|
|
1589
|
+
case "detail.subscribe":
|
|
1590
|
+
keys(o, ["type", "subscriptionId", "kind", "intervalMs", "leaseMs"], "detail.subscribe");
|
|
1591
|
+
if (o.kind !== "processes") throw new Error("invalid detail.subscribe: unsupported kind");
|
|
1592
|
+
return {
|
|
1593
|
+
type: "detail.subscribe",
|
|
1594
|
+
subscriptionId: id(o.subscriptionId, "subscriptionId"),
|
|
1595
|
+
kind: "processes",
|
|
1596
|
+
intervalMs: int(o.intervalMs, "intervalMs", MIN_DETAIL_INTERVAL_MS, MAX_DETAIL_INTERVAL_MS),
|
|
1597
|
+
leaseMs: int(o.leaseMs, "leaseMs", MIN_DETAIL_LEASE_MS, MAX_DETAIL_LEASE_MS)
|
|
1598
|
+
};
|
|
1599
|
+
case "detail.cancel":
|
|
1600
|
+
keys(o, ["type", "subscriptionId"], "detail.cancel");
|
|
1601
|
+
return { type: "detail.cancel", subscriptionId: id(o.subscriptionId, "subscriptionId") };
|
|
1602
|
+
default:
|
|
1603
|
+
throw new Error(`invalid hub message: unsupported type ${desc(o.type)}`);
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1606
|
+
function parseRef(value, extra) {
|
|
1607
|
+
const o = obj(value, "record ref");
|
|
1608
|
+
keys(o, ["runId", "sequence", ...extra], "record ref");
|
|
1609
|
+
return { runId: id(o.runId, "runId"), sequence: int(o.sequence, "sequence", 0, Number.MAX_SAFE_INTEGER) };
|
|
1610
|
+
}
|
|
1611
|
+
function obj(value, what) {
|
|
1612
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error(`invalid ${what}: expected object, got ${desc(value)}`);
|
|
1613
|
+
return value;
|
|
1614
|
+
}
|
|
1615
|
+
function keys(o, required, what, optional = []) {
|
|
1616
|
+
const allowed = /* @__PURE__ */ new Set([...required, ...optional]);
|
|
1617
|
+
for (const k of Object.keys(o)) if (!allowed.has(k)) throw new Error(`invalid ${what}: unexpected field "${k}"`);
|
|
1618
|
+
for (const k of required) if (o[k] === void 0) throw new Error(`invalid ${what}: missing field "${k}"`);
|
|
1619
|
+
for (const k of optional) if (hasOwn(o, k) && o[k] === void 0) throw new Error(`invalid ${what}: ${k} must not be undefined`);
|
|
1620
|
+
}
|
|
1621
|
+
function hasOwn(o, k) {
|
|
1622
|
+
return Object.prototype.hasOwnProperty.call(o, k);
|
|
1623
|
+
}
|
|
1624
|
+
function arr(v, what, min, max) {
|
|
1625
|
+
if (!Array.isArray(v)) throw new Error(`invalid ${what}: expected array`);
|
|
1626
|
+
if (v.length < min || v.length > max) throw new Error(`invalid ${what}: length ${v.length} outside ${min}..${max}`);
|
|
1627
|
+
return v;
|
|
1628
|
+
}
|
|
1629
|
+
function text(v, field, min, max) {
|
|
1630
|
+
if (typeof v !== "string") throw new Error(`invalid ${field}: expected string, got ${desc(v)}`);
|
|
1631
|
+
if (v.length < min || v.length > max) throw new Error(`invalid ${field}: length ${v.length} outside ${min}..${max}`);
|
|
1632
|
+
return v;
|
|
1633
|
+
}
|
|
1634
|
+
function id(v, field) {
|
|
1635
|
+
return text(v, field, 1, MAX_ID);
|
|
1636
|
+
}
|
|
1637
|
+
function int(v, field, min, max) {
|
|
1638
|
+
if (typeof v !== "number" || !Number.isSafeInteger(v)) throw new Error(`invalid ${field}: expected safe integer, got ${desc(v)}`);
|
|
1639
|
+
if (v < min || v > max) throw new Error(`invalid ${field}: ${v} outside ${min}..${max}`);
|
|
1640
|
+
return v;
|
|
1641
|
+
}
|
|
1642
|
+
function desc(v) {
|
|
1643
|
+
try {
|
|
1644
|
+
const s = JSON.stringify(v);
|
|
1645
|
+
if (typeof s === "string") return s.length <= 80 ? s : `${s.slice(0, 77)}...`;
|
|
1646
|
+
} catch {
|
|
1647
|
+
}
|
|
1648
|
+
return String(v);
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
// src/contracts/index.ts
|
|
1652
|
+
var MIN_TIMESTAMP_EPOCH = Date.parse("2000-01-01T00:00:00Z");
|
|
1653
|
+
var MAX_TIMESTAMP_EPOCH = Date.parse("2200-01-01T00:00:00Z");
|
|
1654
|
+
|
|
1722
1655
|
// collector/destinations/backoff.ts
|
|
1723
1656
|
var DEFAULT_BASE_MS = 1e3;
|
|
1724
1657
|
var DEFAULT_MAX_MS = 3e4;
|
|
@@ -1796,9 +1729,6 @@ var DestinationSession = class {
|
|
|
1796
1729
|
outbox;
|
|
1797
1730
|
expectedIntervalMs;
|
|
1798
1731
|
capabilities;
|
|
1799
|
-
collectorVersion;
|
|
1800
|
-
/** Extensions negotiated for the current socket; empty means base wire shape. */
|
|
1801
|
-
metricExtensions = [];
|
|
1802
1732
|
socketFactory;
|
|
1803
1733
|
welcomeTimeoutMs;
|
|
1804
1734
|
idleTimeoutMs;
|
|
@@ -1841,9 +1771,6 @@ var DestinationSession = class {
|
|
|
1841
1771
|
constructor(options) {
|
|
1842
1772
|
assertExpectedIntervalMs(options.expectedIntervalMs);
|
|
1843
1773
|
assertCapabilities(options.capabilities);
|
|
1844
|
-
if (options.collectorVersion.length < 1 || options.collectorVersion.length > 64) {
|
|
1845
|
-
throw new Error("collectorVersion must be 1..64 characters");
|
|
1846
|
-
}
|
|
1847
1774
|
const maxBatchBytes = options.maxBatchBytes ?? DEFAULT_MAX_BATCH_BYTES;
|
|
1848
1775
|
if (!Number.isSafeInteger(maxBatchBytes) || maxBatchBytes < 1 || maxBatchBytes >= MAX_MESSAGE_BYTES) {
|
|
1849
1776
|
throw new Error(`maxBatchBytes must be a safe integer below ${MAX_MESSAGE_BYTES}, got ${String(maxBatchBytes)}`);
|
|
@@ -1867,7 +1794,6 @@ var DestinationSession = class {
|
|
|
1867
1794
|
this.outbox = options.outbox;
|
|
1868
1795
|
this.expectedIntervalMs = options.expectedIntervalMs;
|
|
1869
1796
|
this.capabilities = [...options.capabilities];
|
|
1870
|
-
this.collectorVersion = options.collectorVersion;
|
|
1871
1797
|
this.socketFactory = options.socketFactory;
|
|
1872
1798
|
this.welcomeTimeoutMs = options.welcomeTimeoutMs ?? DEFAULT_WELCOME_TIMEOUT_MS;
|
|
1873
1799
|
this.idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
|
|
@@ -1996,7 +1922,6 @@ var DestinationSession = class {
|
|
|
1996
1922
|
openSocket() {
|
|
1997
1923
|
if (this.stopping) return;
|
|
1998
1924
|
const epoch = ++this.epoch;
|
|
1999
|
-
this.metricExtensions = [];
|
|
2000
1925
|
this.failedEpoch = -1;
|
|
2001
1926
|
this.status = "connecting";
|
|
2002
1927
|
let socket;
|
|
@@ -2052,8 +1977,7 @@ var DestinationSession = class {
|
|
|
2052
1977
|
bootId: this.identity.bootId,
|
|
2053
1978
|
hostname: this.identity.hostname,
|
|
2054
1979
|
capabilities: [...this.capabilities],
|
|
2055
|
-
expectedIntervalMs: this.expectedIntervalMs
|
|
2056
|
-
collectorVersion: this.collectorVersion
|
|
1980
|
+
expectedIntervalMs: this.expectedIntervalMs
|
|
2057
1981
|
};
|
|
2058
1982
|
}
|
|
2059
1983
|
handleMessage(epoch, data) {
|
|
@@ -2129,7 +2053,6 @@ var DestinationSession = class {
|
|
|
2129
2053
|
}
|
|
2130
2054
|
this.status = "welcomed";
|
|
2131
2055
|
this.welcomedAtMs = this.now();
|
|
2132
|
-
this.metricExtensions = [...welcome.metricExtensions ?? []];
|
|
2133
2056
|
this.inFlightWindow = Math.max(1, Math.min(welcome.maxInFlightBatches, this.maxLocalInFlightBatches));
|
|
2134
2057
|
this.replayTokens = 1;
|
|
2135
2058
|
this.lastTokenRefillMs = this.now();
|
|
@@ -2327,10 +2250,7 @@ var DestinationSession = class {
|
|
|
2327
2250
|
return true;
|
|
2328
2251
|
}
|
|
2329
2252
|
buildSamplesMessage(mode, records) {
|
|
2330
|
-
|
|
2331
|
-
(record) => projectTelemetryRecordForWire(record, this.metricExtensions)
|
|
2332
|
-
);
|
|
2333
|
-
return JSON.stringify({ type: "samples", mode, records: wireRecords });
|
|
2253
|
+
return JSON.stringify({ type: "samples", mode, records });
|
|
2334
2254
|
}
|
|
2335
2255
|
handleAckTimeout(batchId) {
|
|
2336
2256
|
const batch = this.inFlight.get(batchId);
|
|
@@ -2447,7 +2367,6 @@ var HubConnection = class _HubConnection {
|
|
|
2447
2367
|
outbox,
|
|
2448
2368
|
expectedIntervalMs: effectiveIntervalMs(options.baseIntervalMs, options.endpoint.intervalMs),
|
|
2449
2369
|
capabilities,
|
|
2450
|
-
collectorVersion: options.collectorVersion,
|
|
2451
2370
|
socketFactory: options.socketFactory,
|
|
2452
2371
|
backoff: options.backoff,
|
|
2453
2372
|
rand: options.rand,
|
|
@@ -2460,19 +2379,14 @@ var HubConnection = class _HubConnection {
|
|
|
2460
2379
|
});
|
|
2461
2380
|
}
|
|
2462
2381
|
/**
|
|
2463
|
-
* Opens this connection's durable outbox under its
|
|
2464
|
-
*
|
|
2465
|
-
*
|
|
2466
|
-
*
|
|
2467
|
-
* samples were already cadence-selected when they were captured.
|
|
2382
|
+
* Opens this connection's durable outbox under its canonical endpoint URL
|
|
2383
|
+
* and re-applies the privacy policy to recovered pending records so none of
|
|
2384
|
+
* them can leave with forbidden fields. Sanitation never cadence-filters:
|
|
2385
|
+
* retained samples were already cadence-selected when they were captured.
|
|
2468
2386
|
*/
|
|
2469
2387
|
static open(options) {
|
|
2470
|
-
const dir = outboxDirFor(options.stateDir, options.endpoint.url);
|
|
2471
|
-
const previousUrl = new URL(options.endpoint.url);
|
|
2472
|
-
previousUrl.pathname = PREVIOUS_CONNECT_PATH;
|
|
2473
2388
|
const outbox = DestinationOutbox.open({
|
|
2474
|
-
dir,
|
|
2475
|
-
previousDir: outboxDirFor(options.stateDir, previousUrl.href),
|
|
2389
|
+
dir: outboxDirFor(options.stateDir, options.endpoint.url),
|
|
2476
2390
|
budget: options.budget,
|
|
2477
2391
|
allocateSequence: options.allocateSequence,
|
|
2478
2392
|
identity: {
|
|
@@ -5292,8 +5206,7 @@ function budget(value, fallback) {
|
|
|
5292
5206
|
// package.json
|
|
5293
5207
|
var package_default = {
|
|
5294
5208
|
name: "rigscope",
|
|
5295
|
-
version: "0.1.
|
|
5296
|
-
rigscopeConfigVersion: 2,
|
|
5209
|
+
version: "0.1.3",
|
|
5297
5210
|
private: false,
|
|
5298
5211
|
engines: {
|
|
5299
5212
|
node: ">=26.0.0"
|
|
@@ -5520,7 +5433,6 @@ async function runDurableCollector(config, identity, statePath, mock) {
|
|
|
5520
5433
|
budget: budget2,
|
|
5521
5434
|
allocateSequence: () => sequence.next(),
|
|
5522
5435
|
sampler,
|
|
5523
|
-
collectorVersion: COLLECTOR_PROTOCOL_VERSION,
|
|
5524
5436
|
socketFactory: (url, options) => new import_ws.WebSocket(url, {
|
|
5525
5437
|
headers: options.headers,
|
|
5526
5438
|
handshakeTimeout: options.handshakeTimeoutMs,
|
package/dist/hub.cjs
CHANGED
|
@@ -1741,8 +1741,7 @@ function describeError(error) {
|
|
|
1741
1741
|
// package.json
|
|
1742
1742
|
var package_default = {
|
|
1743
1743
|
name: "rigscope",
|
|
1744
|
-
version: "0.1.
|
|
1745
|
-
rigscopeConfigVersion: 2,
|
|
1744
|
+
version: "0.1.3",
|
|
1746
1745
|
private: false,
|
|
1747
1746
|
engines: {
|
|
1748
1747
|
node: ">=26.0.0"
|
|
@@ -3109,18 +3108,12 @@ var MIN_EPOCH = Date.parse("2000-01-01T00:00:00Z");
|
|
|
3109
3108
|
var MAX_EPOCH = Date.parse("2200-01-01T00:00:00Z");
|
|
3110
3109
|
var CAPABILITY_NAMES = ["metrics", "inventory", "processes"];
|
|
3111
3110
|
var METRIC_FAMILIES = ["cpu", "memory", "swap", "gpus", "disks", "network"];
|
|
3112
|
-
var METRIC_EXTENSION_NAMES = ["bottleneck-v1"];
|
|
3113
|
-
var COLLECTOR_PROTOCOL_VERSION = "0.3.0";
|
|
3114
|
-
var METRIC_EXTENSION_PROTOCOL_VERSIONS = [COLLECTOR_PROTOCOL_VERSION];
|
|
3115
|
-
function collectorSupportsMetricExtensions(collectorVersion) {
|
|
3116
|
-
return METRIC_EXTENSION_PROTOCOL_VERSIONS.includes(collectorVersion);
|
|
3117
|
-
}
|
|
3118
3111
|
var GAP_REASONS = ["outbox-age", "outbox-bytes", "disk-budget", "write-failure", "rejected"];
|
|
3119
3112
|
function parseCollectorMessage(value) {
|
|
3120
3113
|
const o = obj(value, "collector message");
|
|
3121
3114
|
switch (o.type) {
|
|
3122
3115
|
case "hello": {
|
|
3123
|
-
keys(o, ["type", "collectorId", "runId", "bootId", "hostname", "capabilities", "expectedIntervalMs"
|
|
3116
|
+
keys(o, ["type", "collectorId", "runId", "bootId", "hostname", "capabilities", "expectedIntervalMs"], "hello");
|
|
3124
3117
|
const caps = arr(o.capabilities, "hello.capabilities", 1, CAPABILITY_NAMES.length).map((c) => oneOf(c, CAPABILITY_NAMES, "hello.capabilities"));
|
|
3125
3118
|
if (new Set(caps).size !== caps.length || !caps.includes("metrics")) throw new Error("invalid hello: capabilities must be unique and include metrics");
|
|
3126
3119
|
return {
|
|
@@ -3130,8 +3123,7 @@ function parseCollectorMessage(value) {
|
|
|
3130
3123
|
bootId: text(o.bootId, "bootId", 0, MAX_ID),
|
|
3131
3124
|
hostname: text(o.hostname, "hostname", 0, MAX_HOSTNAME),
|
|
3132
3125
|
capabilities: caps,
|
|
3133
|
-
expectedIntervalMs: int(o.expectedIntervalMs, "expectedIntervalMs", MIN_EXPECTED_INTERVAL_MS, MAX_EXPECTED_INTERVAL_MS)
|
|
3134
|
-
collectorVersion: text(o.collectorVersion, "collectorVersion", 1, 64)
|
|
3126
|
+
expectedIntervalMs: int(o.expectedIntervalMs, "expectedIntervalMs", MIN_EXPECTED_INTERVAL_MS, MAX_EXPECTED_INTERVAL_MS)
|
|
3135
3127
|
};
|
|
3136
3128
|
}
|
|
3137
3129
|
case "samples": {
|
|
@@ -4245,8 +4237,8 @@ function readGaps(db, machineId, fromMs, toMs) {
|
|
|
4245
4237
|
"SELECT from_ms, to_ms, dropped, reason FROM gaps WHERE machine_id = ? AND to_ms >= ? AND from_ms <= ? ORDER BY from_ms LIMIT ?"
|
|
4246
4238
|
).all(machineId, fromMs, toMs, MAX_GAPS);
|
|
4247
4239
|
const missing = db.db.prepare(
|
|
4248
|
-
"WITH
|
|
4249
|
-
).all(machineId, fromMs, toMs, MAX_GAPS);
|
|
4240
|
+
"WITH before_window AS ( SELECT captured_at_ms, expected_interval_ms FROM sample_receipts WHERE machine_id = ? AND captured_at_ms < ? ORDER BY captured_at_ms DESC LIMIT 1 ), in_window AS ( SELECT captured_at_ms, expected_interval_ms FROM sample_receipts WHERE machine_id = ? AND captured_at_ms >= ? AND captured_at_ms <= ? ), ordered AS ( SELECT captured_at_ms, expected_interval_ms, LAG(captured_at_ms) OVER (ORDER BY captured_at_ms) AS prev_ms FROM (SELECT * FROM before_window UNION ALL SELECT * FROM in_window) ) SELECT MAX(prev_ms, ?) AS from_ms, captured_at_ms AS to_ms FROM ordered WHERE prev_ms IS NOT NULL AND captured_at_ms > ? AND captured_at_ms - prev_ms > MAX(15000, 3 * COALESCE(expected_interval_ms, 5000)) ORDER BY captured_at_ms LIMIT ?"
|
|
4241
|
+
).all(machineId, fromMs, machineId, fromMs, toMs, fromMs, fromMs, MAX_GAPS);
|
|
4250
4242
|
const gaps = [
|
|
4251
4243
|
...dropped.map((row) => ({
|
|
4252
4244
|
fromMs: Number(row.from_ms),
|
|
@@ -6991,9 +6983,6 @@ ${reason}`
|
|
|
6991
6983
|
delivery: "durable",
|
|
6992
6984
|
maxInFlightBatches: MAX_IN_FLIGHT_SAMPLE_BATCHES
|
|
6993
6985
|
};
|
|
6994
|
-
if (collectorSupportsMetricExtensions(hello.collectorVersion)) {
|
|
6995
|
-
welcome.metricExtensions = [...METRIC_EXTENSION_NAMES];
|
|
6996
|
-
}
|
|
6997
6986
|
this.send(connection, JSON.stringify(welcome));
|
|
6998
6987
|
}
|
|
6999
6988
|
onSessionMessage(connection, message) {
|
|
@@ -7286,7 +7275,6 @@ function filterSnapshot(snapshot, scope) {
|
|
|
7286
7275
|
var import_node_crypto15 = require("node:crypto");
|
|
7287
7276
|
var import_node_fs3 = require("node:fs");
|
|
7288
7277
|
var import_node_path4 = require("node:path");
|
|
7289
|
-
var STATE_VERSION = 1;
|
|
7290
7278
|
var MAX_COLLECTOR_ID_LENGTH2 = 128;
|
|
7291
7279
|
var MAX_MACHINE_ID_LENGTH2 = 128;
|
|
7292
7280
|
var MAX_TOKEN_LENGTH2 = 256;
|
|
@@ -7541,8 +7529,8 @@ var EnrollmentStore = class {
|
|
|
7541
7529
|
throw new EnrollmentStoreError("invalid-state", "state file must be a JSON object");
|
|
7542
7530
|
}
|
|
7543
7531
|
const state = parsed;
|
|
7544
|
-
if (state.
|
|
7545
|
-
throw new EnrollmentStoreError("invalid-state", "state file
|
|
7532
|
+
if (Object.keys(state).some((key) => key !== "enrollments" && key !== "consumed")) {
|
|
7533
|
+
throw new EnrollmentStoreError("invalid-state", "state file must use the canonical enrollment shape; reset or reinstall unfinished state");
|
|
7546
7534
|
}
|
|
7547
7535
|
if (!Array.isArray(state.enrollments) || !Array.isArray(state.consumed)) {
|
|
7548
7536
|
throw new EnrollmentStoreError("invalid-state", "state file must contain enrollments and consumed arrays");
|
|
@@ -7601,7 +7589,6 @@ var EnrollmentStore = class {
|
|
|
7601
7589
|
}
|
|
7602
7590
|
persistState(next) {
|
|
7603
7591
|
const state = {
|
|
7604
|
-
version: STATE_VERSION,
|
|
7605
7592
|
enrollments: next.enrollments,
|
|
7606
7593
|
consumed: next.consumed
|
|
7607
7594
|
};
|