feat(traffic): a host's top senders, on its page and as get_host_senders (#6115)
The host page gains a "Who's sending" panel, and the MCP a tool, that put the host's outbound (or inbound) traffic down to its containers and NFS mounts: read in shared time buckets, so the host's busiest bucket says who was sending in it. A swarm service's tasks add up under its name; what none of them accounts for is the host itself. Also fixes CI 9488: per-container net_rx_bps / net_tx_bps join the docker alert catalog, so a rule can catch a container flooding the uplink. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -957,6 +957,23 @@ async def host_detail_charts(host_id: str):
|
||||
return await render_template("_host_charts.html", series=series, range_key=range_key)
|
||||
|
||||
|
||||
@host_agent_bp.get("/<host_id>/senders")
|
||||
@require_role(UserRole.viewer)
|
||||
async def host_detail_senders(host_id: str):
|
||||
"""Who sent the host's traffic over the range (#6115), lazy-loaded below
|
||||
the charts and refreshed with them."""
|
||||
from .senders import senders
|
||||
since, range_key = parse_range(request.args.get("range"))
|
||||
async with current_app.db_sessionmaker() as session:
|
||||
host = (await session.execute(
|
||||
select(Host).where(Host.id == host_id))).scalar_one_or_none()
|
||||
if host is None:
|
||||
return "", 404
|
||||
raw_days = int(await get_setting(session, "metrics.retention.raw_days") or 7)
|
||||
got = await senders(session, host.name, since, raw_days=raw_days)
|
||||
return await render_template("_host_senders.html", got=got, range_key=range_key)
|
||||
|
||||
|
||||
def _new_token_pair() -> tuple[str, str]:
|
||||
raw = secrets.token_urlsafe(32)
|
||||
return raw, _hash_token(raw)
|
||||
|
||||
Reference in New Issue
Block a user