fix(mcp): get_anomaly keeps the events nearest the occurrence and says how many it left out (#5861)

Each source in an anomaly's `around` was cut to its oldest 40 with
nothing in the reply to say so; on a busy host the events nearest the
occurrence were the ones dropped. Each source now keeps the 40 nearest
the occurrence's start, and `around_left_out` counts the rest. Sources
return everything their bounded query read (Docker and the host agent
no longer cut at 40 and 20 themselves), so the count is honest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-15 15:59:16 -04:00
co-authored by Claude Opus 5.5
parent 91bb199d14
commit 622addc09e
7 changed files with 63 additions and 28 deletions
+2 -2
View File
@@ -323,7 +323,7 @@ async def service_events(db, router: str, since, until) -> list[dict]:
host: a router anomaly has no host of its own to read events by (#5862).
[] without the Docker plugin, or when no single service matches."""
from steward.core.plugin_manager import loaded_plugin_submodule
from steward.mcp.tools._events import PER_SOURCE, event
from steward.mcp.tools._events import event
from steward.models.hosts import Host
models = loaded_plugin_submodule("docker", "models")
if models is None:
@@ -335,7 +335,7 @@ async def service_events(db, router: str, since, until) -> list[dict]:
rows = (await db.execute(
select(e, Host.name).join(Host, Host.id == e.host_id)
.where(e.container_name.startswith(f"{service}.", autoescape=True), e.at >= since, e.at <= until)
.order_by(e.at).limit(PER_SOURCE))).all()
.order_by(e.at).limit(500))).all()
return [event(ev.at, "container", f"{ev.container_name} {ev.event}" + (f" ({ev.detail})" if ev.detail else ""),
subject=f"{host}/{ev.container_name}") for ev, host in rows]