fix: compact observability search defaults
This commit is contained in:
@@ -675,6 +675,11 @@ async function search(config: UniDeskConfig, options: SearchOptions): Promise<Re
|
||||
const searchPath = `/api/search?${params.toString()}`;
|
||||
const result = await capture(config, target.route, ["sh"], searchScript(observability, target, searchPath, options));
|
||||
const parsed = parseJsonOutput(result.stdout);
|
||||
const exposedResult = parsed === null
|
||||
? compactCapture(result, { full: true })
|
||||
: options.full || options.raw
|
||||
? redactSensitiveUnknown(parsed)
|
||||
: redactSensitiveUnknown(compactSearchResult(parsed));
|
||||
return {
|
||||
ok: result.exitCode === 0 && parsed?.ok === true,
|
||||
action: "platform-infra-observability-search",
|
||||
@@ -693,7 +698,7 @@ async function search(config: UniDeskConfig, options: SearchOptions): Promise<Re
|
||||
candidateLimit: options.candidateLimit,
|
||||
limit: options.limit,
|
||||
},
|
||||
result: redactSensitiveUnknown(parsed) ?? compactCapture(result, { full: true }),
|
||||
result: exposedResult,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -720,6 +725,11 @@ async function diagnoseCodeAgent(config: UniDeskConfig, options: DiagnoseCodeAge
|
||||
}
|
||||
const result = await capture(config, target.route, ["sh"], diagnoseCodeAgentScript(observability, target, searchPath, options));
|
||||
const parsed = parseJsonOutput(result.stdout);
|
||||
const exposedResult = parsed === null
|
||||
? compactCapture(result, { full: true })
|
||||
: options.full || options.raw
|
||||
? redactSensitiveUnknown(parsed)
|
||||
: redactSensitiveUnknown(compactDiagnoseCodeAgentResult(parsed));
|
||||
return {
|
||||
ok: result.exitCode === 0 && parsed?.ok === true,
|
||||
action: "platform-infra-observability-diagnose-code-agent",
|
||||
@@ -735,10 +745,209 @@ async function diagnoseCodeAgent(config: UniDeskConfig, options: DiagnoseCodeAge
|
||||
candidateLimit: options.candidateLimit,
|
||||
limit: options.limit,
|
||||
},
|
||||
result: redactSensitiveUnknown(parsed) ?? compactCapture(result, { full: true }),
|
||||
result: exposedResult,
|
||||
};
|
||||
}
|
||||
|
||||
function compactSearchResult(value: unknown): Record<string, unknown> {
|
||||
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<string, unknown> {
|
||||
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<string, unknown> {
|
||||
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 <span>",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function compactDiagnoseCandidate(value: unknown): Record<string, unknown> {
|
||||
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<string, unknown> {
|
||||
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 ?? "<unknown>");
|
||||
});
|
||||
}
|
||||
|
||||
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<string, unknown> | null {
|
||||
return compactRecord(value, ["traceID", "traceId", "rootServiceName", "rootTraceName", "startTimeUnixNano", "durationMs"]);
|
||||
}
|
||||
|
||||
function compactRecord(value: unknown, keys: string[]): Record<string, unknown> | null {
|
||||
const source = asPlainRecord(value);
|
||||
if (source === null) return null;
|
||||
const result: Record<string, unknown> = {};
|
||||
for (const key of keys) {
|
||||
if (Object.prototype.hasOwnProperty.call(source, key)) result[key] = source[key];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function asPlainRecord(value: unknown): Record<string, unknown> | null {
|
||||
if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
|
||||
return value as Record<string, unknown>;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user