feat: add node workbench observability ops

This commit is contained in:
Codex
2026-06-17 11:28:05 +00:00
parent dd41f04029
commit fd5e59cb48
3 changed files with 751 additions and 2 deletions
+64
View File
@@ -1,3 +1,5 @@
// SPEC: PJ2026-01060505 Workbench Performance draft-2026-06-17-p0.
// Responsibility: YAML source-of-truth parsing for HWLAB node/lane Workbench observability.
import { readFileSync } from "node:fs";
import { rootPath } from "./config";
@@ -83,6 +85,27 @@ export interface HwlabRuntimeBuildkitSpec {
export interface HwlabRuntimeObservabilitySpec {
readonly prometheusOperator: boolean;
readonly metricsEndpoint?: HwlabRuntimeObservabilityMetricsEndpointSpec;
readonly workbench?: HwlabRuntimeObservabilityWorkbenchSpec;
}
export interface HwlabRuntimeObservabilityMetricsEndpointSpec {
readonly serviceName: string;
readonly containerName: string;
readonly port: number;
readonly scheme: "http";
readonly path: string;
readonly scrapeMode: "pod-loopback";
readonly publicRawMetrics: "denied";
}
export interface HwlabRuntimeObservabilityWorkbenchSpec {
readonly enabled: boolean;
readonly summaryPath: string;
readonly metricPrefixes: readonly string[];
readonly requiredSeries: readonly string[];
readonly backendLabelDenylist: readonly string[];
readonly maxUnknownEventLines: number;
}
export interface HwlabRuntimeImageRewriteSpec {
@@ -266,6 +289,12 @@ function booleanField(obj: Record<string, unknown>, key: string, path: string):
return value;
}
function nonNegativeIntegerField(obj: Record<string, unknown>, key: string, path: string): number {
const value = obj[key];
if (typeof value !== "number" || !Number.isInteger(value) || value < 0) throw new Error(`${path}.${key} must be a non-negative integer`);
return value;
}
function sortedRecordEntries(value: unknown, path: string): Array<[string, Record<string, unknown>]> {
return Object.entries(asRecord(value, path)).map(([key, item]) => [key, asRecord(item, `${path}.${key}`)]);
}
@@ -557,6 +586,41 @@ function observabilityConfig(value: unknown, path: string): HwlabRuntimeObservab
const raw = asRecord(value, path);
return {
prometheusOperator: booleanField(raw, "prometheusOperator", path),
metricsEndpoint: observabilityMetricsEndpointConfig(raw.metricsEndpoint, `${path}.metricsEndpoint`),
workbench: observabilityWorkbenchConfig(raw.workbench, `${path}.workbench`),
};
}
function observabilityMetricsEndpointConfig(value: unknown, path: string): HwlabRuntimeObservabilityMetricsEndpointSpec | undefined {
if (value === undefined) return undefined;
const raw = asRecord(value, path);
const scheme = stringField(raw, "scheme", path);
if (scheme !== "http") throw new Error(`${path}.scheme must be http`);
const scrapeMode = stringField(raw, "scrapeMode", path);
if (scrapeMode !== "pod-loopback") throw new Error(`${path}.scrapeMode must be pod-loopback`);
const publicRawMetrics = stringField(raw, "publicRawMetrics", path);
if (publicRawMetrics !== "denied") throw new Error(`${path}.publicRawMetrics must be denied`);
return {
serviceName: stringField(raw, "serviceName", path),
containerName: stringField(raw, "containerName", path),
port: numberField(raw, "port", path),
scheme,
path: stringField(raw, "path", path),
scrapeMode,
publicRawMetrics,
};
}
function observabilityWorkbenchConfig(value: unknown, path: string): HwlabRuntimeObservabilityWorkbenchSpec | undefined {
if (value === undefined) return undefined;
const raw = asRecord(value, path);
return {
enabled: booleanField(raw, "enabled", path),
summaryPath: stringField(raw, "summaryPath", path),
metricPrefixes: stringArrayField(raw, "metricPrefixes", path),
requiredSeries: stringArrayField(raw, "requiredSeries", path),
backendLabelDenylist: stringArrayField(raw, "backendLabelDenylist", path),
maxUnknownEventLines: nonNegativeIntegerField(raw, "maxUnknownEventLines", path),
};
}