fix: surface OTel and sentinel visibility gaps

This commit is contained in:
Codex
2026-06-30 06:44:10 +00:00
parent 5e2276a305
commit 9e3747d9ed
6 changed files with 116 additions and 7 deletions
@@ -120,6 +120,8 @@ export async function status(config: UniDeskConfig, options: CommonOptions): Pro
return renderStatusTable({
ok: result.exitCode === 0 && summary?.ready === true,
target,
backendEndpoint: `${observability.traceBackend.serviceName}.${target.namespace}.svc.cluster.local:${observability.traceBackend.httpPort}`,
collectorEndpoint: `${observability.collector.serviceName}.${target.namespace}.svc.cluster.local:${observability.collector.otlp.grpcPort}`,
summary,
remote: parsed === null ? compactCapture(result, { full: false }) : null,
});
@@ -143,6 +145,8 @@ export async function status(config: UniDeskConfig, options: CommonOptions): Pro
function renderStatusTable(input: {
ok: boolean;
target: ObservabilityTarget;
backendEndpoint: string;
collectorEndpoint: string;
summary: Record<string, unknown> | null;
remote: Record<string, unknown> | null;
}): RenderedCliResult {
@@ -167,6 +171,7 @@ function renderStatusTable(input: {
`platform-infra observability status (${input.ok ? "ok" : "not-ok"})`,
"",
`target=${input.target.id} namespace=${input.target.namespace} ready=${textValue(input.summary?.ready)} route=${input.target.route}`,
`tempo=${input.backendEndpoint} collector=${input.collectorEndpoint} deployments=${deployments.length} pods=${pods.length} probes=${probes.length}`,
"",
"Deployments:",
formatTable(["NAME", "READY", "AVAILABLE"], deployments.length > 0 ? deployments : [["-", "-", "-"]]),
@@ -87,6 +87,7 @@ export function compactDiagnoseCodeAgentResult(value: unknown): Record<string, u
spanCount: source.spanCount ?? null,
services: source.services ?? null,
servicePath: source.servicePath ?? null,
observabilityGap: source.observabilityGap ?? null,
businessTraceIds: source.businessTraceIds ?? null,
identity: compactDiagnoseIdentity(source.identity),
agentrun: compactDiagnoseAgentRun(source.agentrun),
@@ -1986,8 +1986,26 @@ service_path = {
service: ("reached" if service in services else "missing")
for service in expected_services
}
service_path["complete"] = all(service in services for service in expected_services)
missing_services = [service for service in expected_services if service not in services]
service_path["complete"] = len(missing_services) == 0
observability_gap = {
"status": "complete" if len(missing_services) == 0 else "missing-service-spans",
"expectedServices": expected_services,
"seenServices": sorted(services),
"missingServices": missing_services,
"complete": len(missing_services) == 0,
}
if missing_services and ("hwlab-cloud-api" in services or identity.get("runId") not in (None, "") or identity.get("commandId") not in (None, "")):
candidates.insert(0, {
"code": "observability_gap_missing_service_spans",
"label": "observability gap",
"confidence": 0.76,
"summary": "The business trace is correlated to Code Agent context but is missing expected service spans; do not interpret the missing manager/runner spans as proof that those services were not involved.",
"evidence": observability_gap,
})
facts = []
if missing_services:
facts.append("observability gap: missing service spans " + ",".join(missing_services))
if http_summary.get("actorForbidden"):
facts.append("actor forbidden")
terminal_status = agentrun.get("terminalStatus")
@@ -2014,6 +2032,7 @@ summary = {
"actorForbidden": http_summary.get("actorForbidden"),
"terminalStatus": terminal_status,
"failureKind": agentrun.get("failureKind"),
"observabilityGap": observability_gap.get("status"),
},
}
evidence = {
@@ -2041,6 +2060,7 @@ payload = {
"spanCount": len(spans),
"services": services,
"servicePath": service_path,
"observabilityGap": observability_gap,
"businessTraceIds": business_trace_ids[:20],
"identity": identity,
"agentrun": {
@@ -613,6 +613,8 @@ export function renderDiagnoseCodeAgentTable(input: {
const projectionLag = asPlainRecord(input.result.projectionLag);
const summary = asPlainRecord(input.result.summary);
const evidence = asPlainRecord(input.result.evidence);
const observabilityGap = asPlainRecord(input.result.observabilityGap);
const servicePath = asPlainRecord(input.result.servicePath);
const rootCauses = asArray(input.result.rootCauseCandidates).map((item) => asPlainRecord(item) ?? {});
const http = asPlainRecord(input.result.http);
const services = joinValues(input.result.services, 54);
@@ -633,6 +635,14 @@ export function renderDiagnoseCodeAgentTable(input: {
shortenEnd(textValue(candidate.summary ?? candidate.label), 80),
]);
const httpRows = httpTableRows(http);
const expectedServices = asArray(observabilityGap?.expectedServices).map((item) => textValue(item)).filter((item) => item !== "-");
const seenServices = new Set(asArray(observabilityGap?.seenServices).map((item) => textValue(item)).filter((item) => item !== "-"));
const missingServices = new Set(asArray(observabilityGap?.missingServices).map((item) => textValue(item)).filter((item) => item !== "-"));
const serviceRows = expectedServices.map((service) => [
service,
textValue(servicePath?.[service] ?? (missingServices.has(service) ? "missing" : seenServices.has(service) ? "reached" : "-")),
missingServices.has(service) ? "missing" : seenServices.has(service) ? "seen" : "-",
]);
const queryClauses = asArray(input.query.queryClauses).map((item) => textValue(item)).filter((item) => item !== "-");
const requestedRunId = textValue(input.query.runId);
const requestedCommandId = textValue(input.query.commandId);
@@ -658,6 +668,10 @@ export function renderDiagnoseCodeAgentTable(input: {
"Root causes:",
formatTable(["CODE", "CONF", "SUMMARY"], rootRows.length > 0 ? rootRows : [["-", "-", "-"]]),
"",
"Service trace coverage:",
formatTable(["SERVICE", "PATH", "SPAN"], serviceRows.length > 0 ? serviceRows : [["-", "-", "-"]]),
` observabilityGap=${textValue(observabilityGap?.status)} missing=${joinValues(observabilityGap?.missingServices, 60)} seen=${joinValues(observabilityGap?.seenServices, 80)}`,
"",
"HTTP:",
formatTable(["METHOD", "ROUTE", "STATUS", "COUNT"], httpRows.length > 0 ? httpRows : [["-", "-", "-", "-"]]),
"",