From 75a41234808e92238c5ecfd4fde940bb94659120 Mon Sep 17 00:00:00 2001 From: Codex Date: Sun, 21 Jun 2026 15:28:36 +0000 Subject: [PATCH] fix: compact observability search defaults --- scripts/src/platform-infra-observability.ts | 213 +++++++++++++++++++- 1 file changed, 211 insertions(+), 2 deletions(-) diff --git a/scripts/src/platform-infra-observability.ts b/scripts/src/platform-infra-observability.ts index 7e4beaee..d0b60354 100644 --- a/scripts/src/platform-infra-observability.ts +++ b/scripts/src/platform-infra-observability.ts @@ -675,6 +675,11 @@ async function search(config: UniDeskConfig, options: SearchOptions): Promise { + const source = asPlainRecord(value) ?? {}; + const traces = asArray(source.traces).map(compactSearchTrace); + return { + ok: source.ok === true, + searchPath: source.searchPath ?? null, + grep: source.grep ?? null, + tempoQuery: source.tempoQuery ?? null, + pathFilter: source.pathFilter ?? null, + statusFilter: source.statusFilter ?? null, + limit: source.limit ?? null, + candidateLimit: source.candidateLimit ?? null, + searchParseOk: source.searchParseOk ?? null, + candidateTraceCount: source.candidateTraceCount ?? null, + scannedTraceCount: source.scannedTraceCount ?? null, + matchedTraceCount: source.matchedTraceCount ?? null, + scanStopped: source.scanStopped ?? null, + matchingActive: source.matchingActive ?? null, + traces, + truncated: source.truncated ?? null, + next: source.next ?? null, + searchStderrTail: source.searchStderrTail ?? null, + disclosure: { + defaultView: "compact trace rows only; span arrays are omitted to keep stdout below config/unidesk-cli.yaml output.maxStdoutBytes", + expand: "rerun with --full or query a specific trace id with platform-infra observability trace", + }, + }; +} + +function compactSearchTrace(value: unknown): Record { + const trace = asPlainRecord(value) ?? {}; + return { + traceId: trace.traceId ?? null, + traceCommand: trace.traceCommand ?? null, + grepCommand: trace.grepCommand ?? null, + meta: compactMetaRecord(trace.meta), + queryOk: trace.queryOk ?? null, + parseOk: trace.parseOk ?? null, + rawMatched: trace.rawMatched ?? null, + matchingActive: trace.matchingActive ?? null, + bodyBytes: trace.bodyBytes ?? null, + spanCount: trace.spanCount ?? null, + serviceCount: trace.serviceCount ?? null, + services: trace.services ?? null, + businessTraceIds: trace.businessTraceIds ?? null, + errorSpanCount: trace.errorSpanCount ?? null, + matchedSpanCount: trace.matchedSpanCount ?? null, + spanNameCounts: compactNameCounts(trace.spanNameCounts, 6), + errorSpanNames: compactSpanNames(trace.errorSpans, 5), + matchedSpanNames: compactSpanNames(trace.matchedSpans, 8), + stderrTail: trace.stderrTail ?? null, + }; +} + +function compactDiagnoseCodeAgentResult(value: unknown): Record { + const source = asPlainRecord(value) ?? {}; + const mapping = asPlainRecord(source.mapping); + const evidence = asPlainRecord(source.evidence); + return { + ok: source.ok === true, + mapping: mapping === null ? null : { + mode: mapping.mode ?? null, + businessTraceId: mapping.businessTraceId ?? null, + otelTraceId: mapping.otelTraceId ?? null, + searchOk: mapping.searchOk ?? null, + searchParseOk: mapping.searchParseOk ?? null, + candidateTraceCount: mapping.candidateTraceCount ?? null, + scannedCandidateCount: mapping.scannedCandidateCount ?? null, + candidateSelectionMode: mapping.candidateSelectionMode ?? null, + selectedScore: mapping.selectedScore ?? null, + selectedQuality: mapping.selectedQuality ?? null, + selectedLowConfidence: mapping.selectedLowConfidence ?? null, + selectedRejectedReason: mapping.selectedRejectedReason ?? null, + selectedReasons: limitArray(mapping.selectedReasons, 8), + selectedMeta: compactMetaRecord(mapping.selectedMeta), + candidatePreview: asArray(mapping.candidatePreview).slice(0, 3).map(compactDiagnoseCandidate), + searchStderrTail: mapping.searchStderrTail ?? null, + }, + tracePath: source.tracePath ?? null, + bodyBytes: source.bodyBytes ?? null, + traceParseOk: source.traceParseOk ?? null, + spanCount: source.spanCount ?? null, + services: source.services ?? null, + servicePath: source.servicePath ?? null, + businessTraceIds: source.businessTraceIds ?? null, + identity: source.identity ?? null, + agentrun: compactRecord(source.agentrun, ["terminalStatus", "latestSeq", "terminalEventType", "runnerProviderClassification"]), + hwlabReadModel: source.hwlabReadModel ?? null, + http: source.http ?? null, + projectionLag: source.projectionLag ?? null, + summary: source.summary ?? null, + rootCauseCandidates: asArray(source.rootCauseCandidates).slice(0, 5).map(compactRootCauseCandidate), + spanNameCounts: compactNameCounts(source.spanNameCounts, 10), + evidence: evidence === null ? null : { + httpProblemSpanCount: evidence.httpProblemSpanCount ?? null, + terminalSpanCount: evidence.terminalSpanCount ?? null, + turnStatusReadSpanCount: evidence.turnStatusReadSpanCount ?? null, + projectionSpanCount: evidence.projectionSpanCount ?? null, + errorSpanCount: evidence.errorSpanCount ?? null, + errorSpanSampleNames: evidence.errorSpanSampleNames ?? null, + idleWarningSpanCount: evidence.idleWarningSpanCount ?? null, + idleWarningSpanTail: compactSpanList(evidence.idleWarningSpanTail, 3), + }, + next: source.next ?? null, + stderrTail: source.stderrTail ?? null, + disclosure: { + defaultView: "compact diagnosis only; detailed span evidence is omitted to keep stdout below config/unidesk-cli.yaml output.maxStdoutBytes", + expand: "rerun diagnose-code-agent with --full, or query a specific trace id with platform-infra observability trace --grep ", + }, + }; +} + +function compactDiagnoseCandidate(value: unknown): Record { + const candidate = asPlainRecord(value) ?? {}; + return { + traceId: candidate.traceId ?? null, + score: candidate.score ?? null, + reasons: limitArray(candidate.reasons, 6), + parseOk: candidate.parseOk ?? null, + queryOk: candidate.queryOk ?? null, + spanCount: candidate.spanCount ?? null, + services: candidate.services ?? null, + servicePath: candidate.servicePath ?? null, + identity: candidate.identity ?? null, + terminalStatus: candidate.terminalStatus ?? null, + errorSpanCount: candidate.errorSpanCount ?? null, + candidateQuality: candidate.candidateQuality ?? null, + lowConfidence: candidate.lowConfidence ?? null, + rootTraceName: candidate.rootTraceName ?? null, + rootServiceName: candidate.rootServiceName ?? null, + spanNamePreview: limitArray(candidate.spanNamePreview, 8), + traceCommand: candidate.traceCommand ?? null, + }; +} + +function compactRootCauseCandidate(value: unknown): Record { + const candidate = asPlainRecord(value) ?? {}; + return { + code: candidate.code ?? null, + label: candidate.label ?? null, + confidence: candidate.confidence ?? null, + summary: candidate.summary ?? null, + evidenceCount: Array.isArray(candidate.evidence) ? candidate.evidence.length : candidate.evidence === undefined || candidate.evidence === null ? 0 : 1, + }; +} + +function compactSpanList(value: unknown, limit: number): unknown[] { + return asArray(value).slice(0, limit).map((item) => { + const span = asPlainRecord(item) ?? {}; + const attrs = asPlainRecord(span.attributes) ?? {}; + return { + name: span.name ?? null, + service: span.service ?? null, + attributes: compactRecord(attrs, ["failureKind", "terminalStatus", "status", "eventType", "idleMs", "waitingFor", "lastEventLabel", "http.route", "http.status_code", "http.response.status_code"]), + }; + }); +} + +function compactSpanNames(value: unknown, limit: number): string[] { + return asArray(value).slice(0, limit).map((item) => { + const span = asPlainRecord(item); + return String(span?.name ?? ""); + }); +} + +function compactNameCounts(value: unknown, limit: number): unknown[] { + return asArray(value).slice(0, limit).map((item) => { + const record = asPlainRecord(item) ?? {}; + return { name: record.name ?? null, count: record.count ?? null }; + }); +} + +function compactMetaRecord(value: unknown): Record | null { + return compactRecord(value, ["traceID", "traceId", "rootServiceName", "rootTraceName", "startTimeUnixNano", "durationMs"]); +} + +function compactRecord(value: unknown, keys: string[]): Record | null { + const source = asPlainRecord(value); + if (source === null) return null; + const result: Record = {}; + for (const key of keys) { + if (Object.prototype.hasOwnProperty.call(source, key)) result[key] = source[key]; + } + return result; +} + +function asPlainRecord(value: unknown): Record | null { + if (typeof value !== "object" || value === null || Array.isArray(value)) return null; + return value as Record; +} + +function asArray(value: unknown): unknown[] { + return Array.isArray(value) ? value : []; +} + +function limitArray(value: unknown, limit: number): unknown[] { + return asArray(value).slice(0, limit); +} + function renderManifest(observability: ObservabilityConfig, target: ObservabilityTarget): string { const collectorImage = imageReference(observability.images.collector); const tempoImage = imageReference(observability.images.tempo);