Make incidents diff resilient and send sample if empty
This commit is contained in:
@@ -397,69 +397,91 @@ async def incidents_summary(msg: Message):
|
|||||||
async def incidents_diff(msg: Message):
|
async def incidents_diff(msg: Message):
|
||||||
if not is_admin_msg(msg):
|
if not is_admin_msg(msg):
|
||||||
return
|
return
|
||||||
parts = msg.text.split()
|
|
||||||
hours = 24
|
|
||||||
reset = False
|
|
||||||
if len(parts) >= 2:
|
|
||||||
if parts[1].lower() in {"reset", "clear"}:
|
|
||||||
reset = True
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
hours = max(1, int(parts[1]))
|
|
||||||
except ValueError:
|
|
||||||
hours = 24
|
|
||||||
if reset:
|
|
||||||
runtime_state.set_state("incidents_diff_last_ts", None)
|
|
||||||
await msg.answer("📣 Diff marker reset. Next run will show all within window.", reply_markup=system_logs_audit_kb)
|
|
||||||
return
|
|
||||||
last_iso = runtime_state.get("incidents_diff_last_ts")
|
|
||||||
last_dt = None
|
|
||||||
if isinstance(last_iso, str):
|
|
||||||
try:
|
|
||||||
last_dt = datetime.fromisoformat(last_iso)
|
|
||||||
except Exception:
|
|
||||||
last_dt = None
|
|
||||||
rows = read_raw(cfg, hours=hours, limit=5000, include_old=True)
|
|
||||||
|
|
||||||
def collect(from_dt):
|
|
||||||
fresh: list[tuple[datetime, str]] = []
|
|
||||||
for dt, line in rows:
|
|
||||||
if from_dt and dt <= from_dt:
|
|
||||||
continue
|
|
||||||
fresh.append((dt, line))
|
|
||||||
return fresh
|
|
||||||
|
|
||||||
fresh = collect(last_dt)
|
|
||||||
# auto-reset if marker is ahead of all rows
|
|
||||||
if not fresh and last_dt and rows and last_dt >= rows[-1][0]:
|
|
||||||
last_dt = None
|
|
||||||
runtime_state.set_state("incidents_diff_last_ts", None)
|
|
||||||
fresh = collect(None)
|
|
||||||
|
|
||||||
if not fresh:
|
|
||||||
note = f"since {last_dt.astimezone().strftime('%Y-%m-%d %H:%M')}" if last_dt else "for the period"
|
|
||||||
if rows:
|
|
||||||
sample = rows[-50:]
|
|
||||||
body = "\n".join(f"{dt.astimezone().strftime('%m-%d %H:%M')} {line}" for dt, line in sample)
|
|
||||||
await msg.answer(
|
|
||||||
f"📣 No new incidents {note} (window {hours}h).\nRecent sample:\n```\n{body}\n```",
|
|
||||||
reply_markup=system_logs_audit_kb,
|
|
||||||
parse_mode="Markdown",
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
await msg.answer(f"📣 No new incidents {note} (window {hours}h)", reply_markup=system_logs_audit_kb)
|
|
||||||
return
|
|
||||||
fresh.sort(key=lambda x: x[0])
|
|
||||||
body = "\n".join(f"{dt.astimezone().strftime('%m-%d %H:%M')} {line}" for dt, line in fresh[-200:])
|
|
||||||
await msg.answer(
|
|
||||||
f"📣 New incidents (since last mark, window {hours}h): {len(fresh)}\n```\n{body}\n```",
|
|
||||||
reply_markup=system_logs_audit_kb,
|
|
||||||
parse_mode="Markdown",
|
|
||||||
)
|
|
||||||
try:
|
try:
|
||||||
runtime_state.set_state("incidents_diff_last_ts", fresh[-1][0].isoformat())
|
parts = msg.text.split()
|
||||||
except Exception:
|
hours = 24
|
||||||
pass
|
reset = False
|
||||||
|
if len(parts) >= 2:
|
||||||
|
if parts[1].lower() in {"reset", "clear"}:
|
||||||
|
reset = True
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
hours = max(1, int(parts[1]))
|
||||||
|
except ValueError:
|
||||||
|
hours = 24
|
||||||
|
if reset:
|
||||||
|
runtime_state.set_state("incidents_diff_last_ts", None)
|
||||||
|
await msg.answer(
|
||||||
|
"📣 Diff marker reset. Next run will show all within window.",
|
||||||
|
reply_markup=system_logs_audit_kb,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
last_iso = runtime_state.get("incidents_diff_last_ts")
|
||||||
|
last_dt = None
|
||||||
|
if isinstance(last_iso, str):
|
||||||
|
try:
|
||||||
|
last_dt = datetime.fromisoformat(last_iso)
|
||||||
|
except Exception:
|
||||||
|
last_dt = None
|
||||||
|
rows = read_raw(cfg, hours=hours, limit=5000, include_old=True)
|
||||||
|
|
||||||
|
def collect(from_dt):
|
||||||
|
fresh: list[tuple[datetime, str]] = []
|
||||||
|
for dt, line in rows:
|
||||||
|
if from_dt and dt <= from_dt:
|
||||||
|
continue
|
||||||
|
fresh.append((dt, line))
|
||||||
|
return fresh
|
||||||
|
|
||||||
|
fresh = collect(last_dt)
|
||||||
|
# auto-reset if marker is ahead of all rows
|
||||||
|
if not fresh and last_dt and rows and last_dt >= rows[-1][0]:
|
||||||
|
last_dt = None
|
||||||
|
runtime_state.set_state("incidents_diff_last_ts", None)
|
||||||
|
fresh = collect(None)
|
||||||
|
|
||||||
|
def fmt_lines(items: list[tuple[datetime, str]], limit_chars: int = 3500) -> str:
|
||||||
|
buf = []
|
||||||
|
total_len = 0
|
||||||
|
for dt, line in items:
|
||||||
|
entry = f"{dt.astimezone().strftime('%m-%d %H:%M')} {line}"
|
||||||
|
if total_len + len(entry) + 1 > limit_chars:
|
||||||
|
break
|
||||||
|
buf.append(entry)
|
||||||
|
total_len += len(entry) + 1
|
||||||
|
return "\n".join(buf)
|
||||||
|
|
||||||
|
if not fresh:
|
||||||
|
note = f"since {last_dt.astimezone().strftime('%Y-%m-%d %H:%M')}" if last_dt else "for the period"
|
||||||
|
if rows:
|
||||||
|
sample = rows[-50:][::-1] # newest first
|
||||||
|
body = fmt_lines(sample)
|
||||||
|
await msg.answer(
|
||||||
|
f"📣 No new incidents {note} (window {hours}h).\nRecent sample:\n```\n{body}\n```",
|
||||||
|
reply_markup=system_logs_audit_kb,
|
||||||
|
parse_mode="Markdown",
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await msg.answer(
|
||||||
|
f"📣 No new incidents {note} (window {hours}h)",
|
||||||
|
reply_markup=system_logs_audit_kb,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
fresh.sort(key=lambda x: x[0], reverse=True)
|
||||||
|
body = fmt_lines(fresh)
|
||||||
|
await msg.answer(
|
||||||
|
f"📣 New incidents (since last mark, window {hours}h): {len(fresh)}\n```\n{body}\n```",
|
||||||
|
reply_markup=system_logs_audit_kb,
|
||||||
|
parse_mode="Markdown",
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
runtime_state.set_state("incidents_diff_last_ts", fresh[0][0].isoformat())
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
except Exception as e:
|
||||||
|
await msg.answer(f"⚠️ Diff error: {type(e).__name__}: {e}", reply_markup=system_logs_audit_kb)
|
||||||
|
|
||||||
|
|
||||||
@dp.message(F.text.startswith("/alerts_heatmap"))
|
@dp.message(F.text.startswith("/alerts_heatmap"))
|
||||||
|
|||||||
Reference in New Issue
Block a user