feat: add node workbench observability ops
This commit is contained in:
@@ -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),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user