"""HTML view renderer for the Sentry/GlitchTip observability console (#649, Phase 4). Renders connection status widgets, error correlation links, and gated issue creation affordances over the read-only observability snapshot. """ from __future__ import annotations import html from typing import Any from webui.layout import render_page from webui.observability_loader import ObservabilitySnapshot, snapshot_to_dict def _badge(status: str) -> str: st = (status or "").lower() if st == "healthy": return 'healthy' if st == "disabled": return 'disabled (dry-run)' if st in {"missing_token", "not_configured"}: return f'{html.escape(st)}' return f'{html.escape(st)}' def _provider_card(p: dict[str, Any]) -> str: name = html.escape(str(p.get("provider", "provider")).upper()) base_url = html.escape(str(p.get("base_url", ""))) org = html.escape(str(p.get("org", ""))) proj = html.escape(str(p.get("project", ""))) status_badge = _badge(str(p.get("status", ""))) min_events = p.get("min_events_for_issue", 2) lookback = html.escape(str(p.get("lookback", "24h"))) bridge_enabled = "yes" if p.get("bridge_enabled") else "no" return f"""
| Base URL: | {base_url} |
| Scope: | {org} / {proj} |
| Bridge Enabled: | {bridge_enabled} |
| Min Events for Issue: | {min_events} |
| Lookback Window: | {lookback} |
No providers configured.
" links = data.get("links", []) link_rows = [] for l in links: prov = html.escape(str(l.get("provider", ""))) p_issue_id = html.escape(str(l.get("provider_issue_id", ""))) fingerprint = html.escape(str(l.get("fingerprint") or "—")) g_issue_num = int(l.get("gitea_issue_number", 0)) g_org = html.escape(str(l.get("gitea_org", ""))) g_repo = html.escape(str(l.get("gitea_repo", ""))) g_issue_link = f'#{g_issue_num} ({g_org}/{g_repo})' event_cnt = int(l.get("event_count", 1)) last_seen = html.escape(str(l.get("last_seen") or "—")) short_id = html.escape(str(l.get("provider_short_id") or p_issue_id)) link_rows.append(f"""{prov}{fingerprint}Read-only console surface for Sentry/GlitchTip provider connections, error correlation, and durable Gitea issue linkage.
#612 bridge APIs.
| Provider | Incident ID | Fingerprint | Gitea Issue Link | Events | Last Seen |
|---|
Create or reconcile durable Gitea issues from provider observations using the #612 incident bridge:
mcp call gitea_observability_reconcile_incident --provider sentry --apply false