fix(hwlab): preserve trace explorer observability config

This commit is contained in:
Codex
2026-06-20 08:40:29 +00:00
parent ec3ce1c845
commit a5104aca5b
2 changed files with 21 additions and 0 deletions
+1
View File
@@ -161,6 +161,7 @@ lanes:
XDG_CONFIG_HOME: /tekton/home/.config
observability:
prometheusOperator: false
traceExplorerUrlTemplate: /v1/workbench/traces/{trace_id}/events
metricsEndpoint:
serviceName: hwlab-cloud-api
containerName: hwlab-cloud-api
+20
View File
@@ -93,6 +93,7 @@ export interface HwlabRuntimeBuildkitSpec {
export interface HwlabRuntimeObservabilitySpec {
readonly prometheusOperator: boolean;
readonly traceExplorerUrlTemplate?: string;
readonly metricsEndpoint?: HwlabRuntimeObservabilityMetricsEndpointSpec;
readonly workbench?: HwlabRuntimeObservabilityWorkbenchSpec;
readonly recordingRules: readonly HwlabRuntimeObservabilityRecordingRuleSpec[];
@@ -641,8 +642,11 @@ function observabilityConfig(value: unknown, path: string): HwlabRuntimeObservab
for (const alert of warningAlerts) {
if (!recordingRuleIds.has(alert.ruleId)) throw new Error(`${path}.warningAlerts.${alert.id}.ruleId must reference a recordingRules id`);
}
const traceExplorerUrlTemplate = optionalStringField(raw, "traceExplorerUrlTemplate", path);
if (traceExplorerUrlTemplate !== undefined) validateTraceExplorerUrlTemplate(traceExplorerUrlTemplate, `${path}.traceExplorerUrlTemplate`);
return {
prometheusOperator: booleanField(raw, "prometheusOperator", path),
traceExplorerUrlTemplate,
metricsEndpoint: observabilityMetricsEndpointConfig(raw.metricsEndpoint, `${path}.metricsEndpoint`),
workbench: observabilityWorkbenchConfig(raw.workbench, `${path}.workbench`),
recordingRules,
@@ -650,6 +654,22 @@ function observabilityConfig(value: unknown, path: string): HwlabRuntimeObservab
};
}
function validateTraceExplorerUrlTemplate(template: string, path: string): void {
if (!template.includes("{trace_id}")) throw new Error(`${path} must include {trace_id}`);
if (template.startsWith("//")) throw new Error(`${path} must not be protocol-relative`);
const placeholders = Array.from(template.matchAll(/\{([A-Za-z0-9_:-]+)\}/gu), (match) => match[0]);
if (placeholders.length === 0 || placeholders.some((placeholder) => placeholder !== "{trace_id}")) {
throw new Error(`${path} may only use the {trace_id} placeholder`);
}
try {
const url = new URL(template.replaceAll("{trace_id}", "trc_template_probe"), "https://hwlab.local");
if (url.protocol !== "http:" && url.protocol !== "https:") throw new Error("unsupported protocol");
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new Error(`${path} must be an http(s) or same-origin relative URL template: ${message}`);
}
}
function observabilityMetricsEndpointConfig(value: unknown, path: string): HwlabRuntimeObservabilityMetricsEndpointSpec | undefined {
if (value === undefined) return undefined;
const raw = asRecord(value, path);