// SPEC: PJ2026-01060505 Workbench Performance draft-2026-06-17-p0. // Responsibility: Prometheus/observability expression rendering for HWLAB node runtime. import type { HwlabRuntimeObservabilityRecordingRuleSpec, HwlabRuntimeObservabilitySpec, HwlabRuntimeObservabilityWarningAlertSpec } from "./hwlab-node-lanes"; export function nodeObservabilityRecordingRuleSummaries(observability: HwlabRuntimeObservabilitySpec): Array> { return observability.recordingRules.map((rule) => ({ ...rule, expression: nodeObservabilityRecordingRuleExpression(rule), sampleCountExpression: nodeObservabilitySampleCountExpression(rule, rule.matchLabels), lowSampleGuardExpression: `${nodeObservabilitySampleCountExpression(rule, rule.matchLabels)} >= ${rule.minSamples}`, })); } export function nodeObservabilityWarningAlertSummaries(observability: HwlabRuntimeObservabilitySpec): Array> { const recordingRules = new Map(observability.recordingRules.map((rule) => [rule.id, rule])); return observability.warningAlerts.map((alert) => { const rule = recordingRules.get(alert.ruleId); return { ...alert, expression: rule === undefined ? null : nodeObservabilityWarningAlertExpression(rule, alert), recordingRule: rule === undefined ? null : rule.metric, lowSampleGuardExpression: rule === undefined ? null : `${nodeObservabilitySampleCountExpression(rule, { ...rule.matchLabels, ...alert.matchLabels })} >= ${alert.minSamples}`, }; }); } export function nodeObservabilityRecordingRuleExpression(rule: HwlabRuntimeObservabilityRecordingRuleSpec): string { const bucketGroupBy = uniqueStrings([...rule.groupBy, "le"]); return `histogram_quantile(${formatPrometheusNumber(rule.quantile)}, sum by (${bucketGroupBy.join(", ")}) (rate(${prometheusMetricSelector(`${rule.sourceMetric}_bucket`, rule.matchLabels)}[${rule.window}])))`; } function nodeObservabilitySampleCountExpression(rule: HwlabRuntimeObservabilityRecordingRuleSpec, matchLabels: Record): string { const groupBy = uniqueStrings([...rule.groupBy]); return `sum by (${groupBy.join(", ")}) (increase(${prometheusMetricSelector(`${rule.sourceMetric}_count`, matchLabels)}[${rule.window}]))`; } export function nodeObservabilityWarningAlertExpression(rule: HwlabRuntimeObservabilityRecordingRuleSpec, alert: HwlabRuntimeObservabilityWarningAlertSpec): string { const sampleLabels = { ...rule.matchLabels, ...alert.matchLabels }; const sampleGuard = `${nodeObservabilitySampleCountExpression(rule, sampleLabels)} >= ${alert.minSamples}`; const vectorMatch = rule.groupBy.length === 0 ? "" : ` on (${uniqueStrings([...rule.groupBy]).join(", ")})`; return `(${prometheusMetricSelector(rule.metric, alert.matchLabels)} > ${formatPrometheusNumber(alert.thresholdSeconds)}) and${vectorMatch} (${sampleGuard})`; } function prometheusMetricSelector(metric: string, labels: Record): string { const selector = prometheusLabelSelector(labels); return selector.length === 0 ? metric : `${metric}${selector}`; } function prometheusLabelSelector(labels: Record): string { const entries = Object.entries(labels); if (entries.length === 0) return ""; return `{${entries.map(([key, value]) => `${key}${value.includes("|") ? "=~" : "="}"${escapePrometheusLabelValue(value)}"`).join(",")}}`; } function escapePrometheusLabelValue(value: string): string { return value.replace(/\\/gu, "\\\\").replace(/"/gu, "\\\""); } function formatPrometheusNumber(value: number): string { return Number.isInteger(value) ? String(value) : String(value); } function uniqueStrings(values: readonly string[]): string[] { return [...new Set(values)]; }