fix: close operational panel page review findings
This commit is contained in:
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user