stream_coverage i status-API.

This commit is contained in:
larssand
2026-06-29 18:36:50 +02:00
parent c95634f976
commit 0b31e6c55e
5 changed files with 78 additions and 1 deletions

View File

@@ -51,6 +51,47 @@ def _range_seconds(value: object) -> int:
return 3600
def _stream_coverage(runtime_values: dict[str, object], stream_profiles: dict[str, object], stream_status: dict[str, object], profile_readiness: list[dict[str, object]], stream_titles: dict[str, str]) -> list[dict[str, object]]:
configured = [
item for item in runtime_values.get("graylog_streams", [])
if isinstance(item, dict) and item.get("id")
]
status_by_id = {
str(item.get("stream_id", "")): item
for item in stream_status.get("streams", [])
if isinstance(item, dict) and item.get("stream_id")
}
readiness_by_stream: dict[str, list[dict[str, object]]] = {}
for item in profile_readiness:
readiness_by_stream.setdefault(str(item.get("stream_id", "")), []).append(item)
ids = list(dict.fromkeys([str(item.get("id", "")) for item in configured] + list(stream_profiles) + list(status_by_id)))
rows = []
for stream_id in ids:
profile = stream_profiles.get(stream_id)
readiness = readiness_by_stream.get(stream_id, [])
ready_fields = sum(1 for item in readiness if item.get("ready"))
total_fields = len(readiness)
status = status_by_id.get(stream_id, {})
enabled = next((bool(item.get("enabled")) for item in configured if str(item.get("id", "")) == stream_id), False)
rows.append({
"stream_id": stream_id,
"stream_name": _stream_name(stream_id, stream_titles, profile),
"enabled": enabled,
"profile": _profile_name(stream_id, stream_titles, profile) if profile else "",
"profile_ready": bool(profile),
"entity_field": str(getattr(profile, "entity_field", "")) if profile else "",
"tracked_fields": len(getattr(profile, "categorical_fields", ())) + len(getattr(profile, "numeric_fields", ())) if profile else 0,
"ready_fields": ready_fields,
"total_fields": total_fields,
"readiness": f"{ready_fields}/{total_fields}" if total_fields else "0/0",
"events_fetched": int(status.get("events_fetched", 0) or 0),
"latest_event_time": str(status.get("latest_event_time", "")),
"truncated": bool(status.get("truncated")),
"health": "not_enabled" if not enabled else "missing_profile" if not profile else "no_events" if int(status.get("events_fetched", 0) or 0) == 0 else "learning" if total_fields and ready_fields < total_fields else "ready" if total_fields else "profile_needs_fields",
})
return rows
def build_status(
log_path: str,
*,
@@ -146,6 +187,7 @@ def build_status(
}
for item in profile_readiness
]
stream_coverage = _stream_coverage(runtime_values, stream_profiles, mcp_status, profile_readiness, stream_titles)
intel_ips = sorted(
{
ip
@@ -184,6 +226,7 @@ def build_status(
"capabilities": {"threat_intel": threat_intel_status, "graylog_mcp": mcp_status},
"configuration": runtime_config,
"stream_profiles": [{"stream_id": item.stream_id, "name": _profile_name(item.stream_id, stream_titles, item), "stream_name": _stream_name(item.stream_id, stream_titles, item), "entity_field": item.entity_field, "timestamp_field": item.timestamp_field, "categorical_fields": list(item.categorical_fields), "numeric_fields": list(item.numeric_fields), "detectors": item.detectors, "field_weights": item.field_weights} for item in stream_profiles.values()],
"stream_coverage": stream_coverage,
"profile_readiness": profile_readiness,
"diagnostics": {
"top_source_ips": top_field_values(events, "srcip", limit=10),