atlasbot: expose baseline deltas and pod issue summary
This commit is contained in:
parent
4ff7def3ff
commit
79f15eaa7a
@ -114,24 +114,34 @@ def _merge_cluster_summary(snapshot: dict[str, Any], summary: dict[str, Any]) ->
|
||||
cluster_summary = snapshot.get("summary") if isinstance(snapshot.get("summary"), dict) else {}
|
||||
if not cluster_summary:
|
||||
return
|
||||
signals = cluster_summary.get("signals")
|
||||
profiles = cluster_summary.get("profiles")
|
||||
inventory = cluster_summary.get("inventory")
|
||||
topology = cluster_summary.get("topology")
|
||||
lexicon = cluster_summary.get("lexicon")
|
||||
cross_stats = cluster_summary.get("cross_stats")
|
||||
if isinstance(signals, list):
|
||||
summary["signals"] = signals
|
||||
if isinstance(profiles, dict):
|
||||
summary["profiles"] = profiles
|
||||
if isinstance(inventory, dict):
|
||||
summary["inventory"] = inventory
|
||||
if isinstance(topology, dict):
|
||||
summary["topology"] = topology
|
||||
if isinstance(lexicon, dict):
|
||||
summary["lexicon"] = lexicon
|
||||
if isinstance(cross_stats, dict):
|
||||
summary["cross_stats"] = cross_stats
|
||||
_merge_cluster_fields(
|
||||
summary,
|
||||
cluster_summary,
|
||||
{
|
||||
"signals": list,
|
||||
"profiles": dict,
|
||||
"inventory": dict,
|
||||
"topology": dict,
|
||||
"lexicon": dict,
|
||||
"cross_stats": dict,
|
||||
"baseline_deltas": dict,
|
||||
"pod_issue_summary": dict,
|
||||
"trend_requests": dict,
|
||||
"pod_waiting_trends": dict,
|
||||
"pod_terminated_trends": dict,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def _merge_cluster_fields(
|
||||
summary: dict[str, Any],
|
||||
cluster_summary: dict[str, Any],
|
||||
field_types: dict[str, type],
|
||||
) -> None:
|
||||
for key, expected in field_types.items():
|
||||
value = cluster_summary.get(key)
|
||||
if isinstance(value, expected):
|
||||
summary[key] = value
|
||||
|
||||
|
||||
def _augment_lexicon(summary: dict[str, Any]) -> None:
|
||||
@ -1640,6 +1650,76 @@ def _append_cluster_watchlist(lines: list[str], summary: dict[str, Any]) -> None
|
||||
lines.append("cluster_watchlist: " + "; ".join(watchlist))
|
||||
|
||||
|
||||
def _append_baseline_deltas(lines: list[str], summary: dict[str, Any]) -> None:
|
||||
deltas = summary.get("baseline_deltas") if isinstance(summary.get("baseline_deltas"), dict) else {}
|
||||
nodes = deltas.get("nodes") if isinstance(deltas.get("nodes"), dict) else {}
|
||||
namespaces = deltas.get("namespaces") if isinstance(deltas.get("namespaces"), dict) else {}
|
||||
for scope, block in (("nodes", nodes), ("namespaces", namespaces)):
|
||||
if not isinstance(block, dict):
|
||||
continue
|
||||
for metric, entries in block.items():
|
||||
if not isinstance(entries, list) or not entries:
|
||||
continue
|
||||
parts: list[str] = []
|
||||
for entry in entries[:5]:
|
||||
if not isinstance(entry, dict):
|
||||
continue
|
||||
name = entry.get("node") if scope == "nodes" else entry.get("namespace")
|
||||
delta = entry.get("delta")
|
||||
severity = entry.get("severity")
|
||||
if not isinstance(name, str) or not name or not isinstance(delta, (int, float)):
|
||||
continue
|
||||
suffix = f" ({severity})" if isinstance(severity, str) and severity else ""
|
||||
parts.append(f"{name}={_format_float(delta)}%{suffix}")
|
||||
if parts:
|
||||
lines.append(f"{scope}_baseline_delta_{metric}: " + "; ".join(parts))
|
||||
|
||||
|
||||
def _append_pod_issue_summary(lines: list[str], summary: dict[str, Any]) -> None:
|
||||
issues = summary.get("pod_issue_summary") if isinstance(summary.get("pod_issue_summary"), dict) else {}
|
||||
waiting = issues.get("waiting_reasons_top") if isinstance(issues.get("waiting_reasons_top"), list) else []
|
||||
phases = issues.get("phase_reasons_top") if isinstance(issues.get("phase_reasons_top"), list) else []
|
||||
namespace_issue = issues.get("namespace_issue_top") if isinstance(issues.get("namespace_issue_top"), dict) else {}
|
||||
waiting_line = _reason_line(waiting, "pod_waiting_reasons_top")
|
||||
if waiting_line:
|
||||
lines.append(waiting_line)
|
||||
phase_line = _reason_line(phases, "pod_phase_reasons_top")
|
||||
if phase_line:
|
||||
lines.append(phase_line)
|
||||
if namespace_issue:
|
||||
_append_namespace_issue_lines(lines, namespace_issue)
|
||||
|
||||
|
||||
def _reason_line(entries: list[dict[str, Any]], label: str) -> str:
|
||||
parts = []
|
||||
for entry in entries[:5]:
|
||||
if not isinstance(entry, dict):
|
||||
continue
|
||||
reason = entry.get("reason")
|
||||
count = entry.get("count")
|
||||
if reason:
|
||||
parts.append(f"{reason}={count}")
|
||||
if parts:
|
||||
return f"{label}: " + "; ".join(parts)
|
||||
return ""
|
||||
|
||||
|
||||
def _append_namespace_issue_lines(lines: list[str], namespace_issue: dict[str, Any]) -> None:
|
||||
for key, entries in namespace_issue.items():
|
||||
if not isinstance(entries, list) or not entries:
|
||||
continue
|
||||
parts: list[str] = []
|
||||
for entry in entries[:5]:
|
||||
if not isinstance(entry, dict):
|
||||
continue
|
||||
ns = entry.get("namespace")
|
||||
value = entry.get("value")
|
||||
if ns:
|
||||
parts.append(f"{ns}={value}")
|
||||
if parts:
|
||||
lines.append(f"namespace_issue_top_{key}: " + "; ".join(parts))
|
||||
|
||||
|
||||
def _build_cluster_watchlist(summary: dict[str, Any]) -> dict[str, Any]:
|
||||
items: list[str] = []
|
||||
nodes_summary = summary.get("nodes_summary") if isinstance(summary.get("nodes_summary"), dict) else {}
|
||||
@ -1880,6 +1960,7 @@ def summary_text(snapshot: dict[str, Any] | None) -> str: # noqa: PLR0915
|
||||
_append_namespace_nodes(lines, summary)
|
||||
_append_node_pods(lines, summary)
|
||||
_append_pod_issues(lines, summary)
|
||||
_append_pod_issue_summary(lines, summary)
|
||||
_append_workload_health(lines, summary)
|
||||
_append_events(lines, summary)
|
||||
_append_node_usage_stats(lines, summary)
|
||||
@ -1895,6 +1976,7 @@ def summary_text(snapshot: dict[str, Any] | None) -> str: # noqa: PLR0915
|
||||
_append_pvc_usage(lines, summary)
|
||||
_append_root_disk_headroom(lines, summary)
|
||||
_append_namespace_capacity_summary(lines, summary)
|
||||
_append_baseline_deltas(lines, summary)
|
||||
_append_longhorn(lines, summary)
|
||||
_append_workloads(lines, summary)
|
||||
_append_topology(lines, summary)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user