Merge pull request #1089 from pikasTech/issue1087-otel-search

fix(otel): compact observability search full output
This commit is contained in:
Lyon
2026-06-27 09:37:07 +08:00
committed by GitHub
@@ -118,7 +118,13 @@ export async function search(config: UniDeskConfig, options: SearchOptions): Pro
}
const exposedResult = parsed === null
? compactCapture(result, { full: true })
: redactSensitiveUnknown(parsed);
: options.raw
? redactSensitiveUnknown(parsed)
: {
...compactSearchFullResult(parsed),
outputMode: "bounded-compact-json",
rawDisclosure: "Use --raw only for Tempo/API envelope or parser debugging.",
};
return {
ok,
action: "platform-infra-observability-search",
@@ -129,6 +135,63 @@ export async function search(config: UniDeskConfig, options: SearchOptions): Pro
};
}
function compactSearchFullResult(value: unknown): Record<string, unknown> {
const source = asPlainRecord(value) ?? {};
return {
ok: source.ok === true,
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,
traces: asArray(source.traces).slice(0, 5).map(compactSearchFullTrace),
omittedTraceCount: Math.max(0, asArray(source.traces).length - 5),
truncated: source.truncated ?? null,
next: source.next ?? null,
searchStderrTail: source.searchStderrTail ?? null,
disclosure: {
defaultView: "bounded search full summary; span arrays and raw Tempo bodies are omitted",
expand: "query one trace with platform-infra observability trace --trace-id <traceId> --grep <text> --full; use --raw for parser/debug only",
},
};
}
function compactSearchFullTrace(value: unknown): Record<string, unknown> {
const trace = asPlainRecord(value) ?? {};
const meta = asPlainRecord(trace.meta);
return {
traceId: trace.traceId ?? null,
startAt: trace.startAt ?? isoFromUnixNano(meta?.startTimeUnixNano),
durationMs: trace.durationMs ?? meta?.durationMs ?? null,
queryOk: trace.queryOk ?? null,
parseOk: trace.parseOk ?? null,
rawMatched: trace.rawMatched ?? null,
bodyBytes: trace.bodyBytes ?? null,
spanCount: trace.spanCount ?? null,
serviceCount: trace.serviceCount ?? null,
services: asArray(trace.services).slice(0, 4),
businessTraceIds: asArray(trace.businessTraceIds).slice(0, 4),
errorSpanCount: trace.errorSpanCount ?? null,
matchedSpanCount: trace.matchedSpanCount ?? null,
spanNameCounts: asArray(trace.spanNameCounts).slice(0, 4).map(compactNameCount),
matchedSpanNames: [...new Set(asArray(trace.matchedSpans).map((span) => textValue(asPlainRecord(span)?.name)).filter((name) => name !== "-"))].slice(0, 4),
};
}
function compactNameCount(value: unknown): Record<string, unknown> {
const item = asPlainRecord(value) ?? {};
return {
name: item.name ?? null,
count: item.count ?? null,
};
}
export function inferSearchTempoQuery(options: SearchOptions): string | null {
const filters: string[] = [];
if (options.path !== null) filters.push(`.http.route = ${JSON.stringify(options.path)}`);