Files

88 lines
2.6 KiB
Python
Raw Permalink Normal View History

"""Attach alert_logs to fleet metric sample windows (10min flush alignment)."""
from __future__ import annotations
from datetime import datetime, timedelta
from typing import Any
from server.utils.display_time import to_naive_utc
ALERT_TYPE_LABELS = {
"cpu": "CPU",
"mem": "内存",
"disk": "磁盘",
"time_drift": "时钟漂移",
"system": "系统",
}
def _parse_naive_utc(value: datetime | str | None) -> datetime | None:
if value is None:
return None
if isinstance(value, datetime):
return to_naive_utc(value)
raw = str(value).strip()
if not raw:
return None
normalized = raw.replace(" ", "T") if " " in raw and "T" not in raw else raw
if normalized.endswith("Z"):
normalized = normalized[:-1] + "+00:00"
try:
dt = datetime.fromisoformat(normalized)
except ValueError:
return None
return to_naive_utc(dt)
def _alert_to_dict(alert: Any) -> dict[str, Any]:
atype = str(getattr(alert, "alert_type", "") or "")
return {
"server_name": getattr(alert, "server_name", None) or "",
"server_id": getattr(alert, "server_id", None),
"alert_type": atype,
"alert_type_label": ALERT_TYPE_LABELS.get(atype, atype),
"value": getattr(alert, "value", None) or "",
"is_recovery": bool(getattr(alert, "is_recovery", False)),
"created_at": str(getattr(alert, "created_at", "") or ""),
}
def attach_alerts_to_fleet_points(
points: list[dict[str, Any]],
alerts: list[Any],
*,
interval_minutes: int = 10,
) -> list[dict[str, Any]]:
"""Map each sample to alerts in (previous_sample, current_sample] window."""
if not points:
return []
parsed: list[tuple[datetime | None, dict[str, Any]]] = []
for p in points:
parsed.append((_parse_naive_utc(p.get("recorded_at")), p))
alert_rows: list[tuple[datetime, dict[str, Any]]] = []
for a in alerts:
adt = _parse_naive_utc(getattr(a, "created_at", None))
if adt is not None:
alert_rows.append((adt, _alert_to_dict(a)))
window = timedelta(minutes=max(1, interval_minutes))
enriched: list[dict[str, Any]] = []
for i, (pt_dt, p) in enumerate(parsed):
if pt_dt is None:
enriched.append({**p, "alerts": [], "alert_count": 0})
continue
prev_dt = parsed[i - 1][0] if i > 0 else None
start = prev_dt if prev_dt is not None else pt_dt - window
bucket = [
item
for adt, item in alert_rows
if start < adt <= pt_dt
]
enriched.append({**p, "alerts": bucket, "alert_count": len(bucket)})
return enriched