fix: close operational panel page review findings

This commit is contained in:
gti
2026-09-22 20:34:03 -03:00
parent a4d837f151
commit 0eeb7d159c
9 changed files with 263 additions and 38 deletions
+43 -6
View File
@@ -227,7 +227,7 @@ def _parse_age(value):
return None
def _blockers_query(session, *, tenant_id=None, agent_id=None, blocker_type=None, field=None, status="OPEN", client=None, installation=None, search=None, age=None):
def _blockers_query(session, *, tenant_id=None, agent_id=None, product_code=None, blocker_type=None, field=None, status="OPEN", client=None, installation=None, search=None, age=None):
query = select(BlockedProduct, Tenant, Installation, Agent).join(Tenant, Tenant.id == BlockedProduct.tenant_id).outerjoin(Installation, Installation.id == BlockedProduct.installation_id).outerjoin(Agent, Agent.id == Installation.agent_id)
status = (status or "OPEN").upper()
if status == "OPEN":
@@ -238,6 +238,8 @@ def _blockers_query(session, *, tenant_id=None, agent_id=None, blocker_type=None
query = query.where(BlockedProduct.tenant_id == tenant_id)
if agent_id is not None:
query = query.where(Agent.id == agent_id)
if product_code is not None:
query = query.where(BlockedProduct.product_code == product_code)
if blocker_type:
query = query.where(BlockedProduct.blocker_type == blocker_type)
if field:
@@ -255,11 +257,30 @@ def _blockers_query(session, *, tenant_id=None, agent_id=None, blocker_type=None
return query
def list_blockers(session, *, tenant_id=None, agent_id=None, page=1, page_size=50, blocker_type=None, field=None, resolved=False, client=None, installation=None, status="OPEN", age=None, search=None):
def blocker_filter_summary(session, *, tenant_id=None, agent_id=None, product_code=None, blocker_type=None, field=None, status="OPEN", client=None, installation=None, age=None, search=None):
query = _blockers_query(session, tenant_id=tenant_id, agent_id=agent_id, product_code=product_code, blocker_type=blocker_type, field=field, status=status, client=client, installation=installation, search=search, age=age)
open_count = func.sum(case((BlockedProduct.resolved_at.is_(None), 1), else_=0))
open_count, = session.execute(query.with_only_columns(open_count).order_by(None)).one()
rows = session.execute(query.with_only_columns(func.coalesce(BlockedProduct.field, "OTHER"), func.count(BlockedProduct.id)).group_by(func.coalesce(BlockedProduct.field, "OTHER")).order_by(None)).all()
breakdown = {field: 0 for field in BLOCKER_FIELDS}
for field_name, count in rows:
key = str(field_name or "").upper()
breakdown[key if key in breakdown else "OTHER"] += int(count)
pair_query = query.with_only_columns(BlockedProduct.tenant_id, BlockedProduct.product_code).distinct().subquery()
client_query = query.with_only_columns(BlockedProduct.tenant_id).distinct().subquery()
return {
"open_blockers": int(open_count or 0),
"affected_products": int(session.scalar(select(func.count()).select_from(pair_query)) or 0),
"affected_clients": int(session.scalar(select(func.count()).select_from(client_query)) or 0),
"blocker_breakdown": breakdown,
}
def list_blockers(session, *, tenant_id=None, agent_id=None, product_code=None, page=1, page_size=50, blocker_type=None, field=None, resolved=False, client=None, installation=None, status="OPEN", age=None, search=None):
page, page_size = _page(page, page_size)
if resolved and status == "OPEN":
status = "RESOLVED"
query = _blockers_query(session, tenant_id=tenant_id, agent_id=agent_id, blocker_type=blocker_type, field=field, status=status, client=client, installation=installation, search=search, age=age)
query = _blockers_query(session, tenant_id=tenant_id, agent_id=agent_id, product_code=product_code, blocker_type=blocker_type, field=field, status=status, client=client, installation=installation, search=search, age=age)
ordered = query.order_by(BlockedProduct.last_seen_at.desc(), BlockedProduct.id.desc())
rows = session.execute(ordered.offset((page - 1) * page_size).limit(page_size)).all()
items = [_blocker_item(blocker, tenant, installation_row, agent, now=datetime.now(timezone.utc)) for blocker, tenant, installation_row, agent in rows]
@@ -290,11 +311,13 @@ def _job_item(row, agent, installation, tenant, *, now=None):
}
def list_jobs(session, *, agent_id=None, page=1, page_size=50, status=None, kind=None, since=None, until=None, client=None, search=None):
def list_jobs(session, *, agent_id=None, job_id=None, page=1, page_size=50, status=None, kind=None, since=None, until=None, client=None, search=None):
page, page_size = _page(page, page_size)
query = select(Job, Agent, Installation, Tenant).join(Agent, Agent.id == Job.agent_id).join(Installation, Installation.agent_id == Agent.id).join(Tenant, Tenant.id == Installation.tenant_id)
if agent_id is not None:
query = query.where(Job.agent_id == agent_id)
if job_id is not None:
query = query.where(Job.id == job_id)
if status:
query = query.where(Job.status == status)
if kind:
@@ -380,6 +403,19 @@ def dashboard_summary(session, now=None):
attention.sort(key=lambda entry: (entry[1], -(entry[0]["timestamp"] is not None), entry[2]))
failed_jobs = session.scalar(select(func.count(Job.id)).where(Job.status == "FAILED")) or 0
failed_job_rows = session.execute(
select(Job, Agent, Installation, Tenant).join(Agent, Agent.id == Job.agent_id)
.join(Installation, Installation.agent_id == Agent.id).join(Tenant, Tenant.id == Installation.tenant_id)
.where(Job.status == "FAILED").order_by(Job.created_at.desc(), Job.id.desc()).limit(10)
).all()
recent_failed_jobs = []
for job, agent, installation, tenant in failed_job_rows:
item = _job_item(job, agent, installation, tenant, now=now)
item["error"] = (item["error"] or "")[:240]
item["created_age"] = format_age(job.created_at, now)
item["finished_age"] = format_age(job.finished_at, now)
item["link"] = f"/jobs?job_id={job.id}"
recent_failed_jobs.append(item)
return {
"agents_total": sum(counts.values()),
**{key.lower(): value for key, value in counts.items()},
@@ -393,6 +429,7 @@ def dashboard_summary(session, now=None):
"open_blocker_breakdown": open_blocker_breakdown,
"attention_items": [entry[0] for entry in attention[:10]],
"failed_jobs": failed_jobs,
"recent_failed_jobs": recent_failed_jobs,
}
@@ -432,6 +469,6 @@ def blocker_detail(session, blocker_id):
}
def list_panel_events(session, installation_db_id, **filters):
rows = list_events(session, installation_db_id, **filters)
def list_panel_events(session, installation_db_id, *, include_more=False, **filters):
rows = list_events(session, installation_db_id, fetch_extra=include_more, **filters)
return [{"id": row.id, "severity": row.severity, "event_type": row.event_type, "message": row.message, "context": row.structured_context, "job_id": row.job_id, "product_code": row.product_code, "occurred_at": _iso(row.occurred_at)} for row in rows]