fix(daily-digest): probe Firecrawl on its real liveness path and classify endpoints per fleet policy
PR Pipeline — Authorize → Validate → Review → Merge / auth (pull_request) Successful in 6s
PR Pipeline — Authorize → Validate → Review → Merge / validate (pull_request) Successful in 3s
PR Pipeline — Authorize → Validate → Review → Merge / lint (pull_request) Successful in 11s
PR Pipeline — Authorize → Validate → Review → Merge / ai-review (pull_request) Successful in 8s
PR Pipeline — Authorize → Validate → Review → Merge / gate (pull_request) Successful in 1s
PR Pipeline — Authorize → Validate → Review → Merge / auth (pull_request) Successful in 6s
PR Pipeline — Authorize → Validate → Review → Merge / validate (pull_request) Successful in 3s
PR Pipeline — Authorize → Validate → Review → Merge / lint (pull_request) Successful in 11s
PR Pipeline — Authorize → Validate → Review → Merge / ai-review (pull_request) Successful in 8s
PR Pipeline — Authorize → Validate → Review → Merge / gate (pull_request) Successful in 1s
Folds into the same branch as the Zulip delivery change, as instructed. FINDING 1 - the Firecrawl probe path was wrong; the service is fine. scripts/daily-infra-report.py probed http://192.168.68.7:3002/health, which Firecrawl does not serve - it 404s. The root answers 200 with {"message":"Firecrawl API",...}. Live 2026-09-26: Firecrawl(/) -> 200 Firecrawl(/health) -> 404 <- what the report was showing The probe is now the root, which is its liveness endpoint. FINDING 2 - the Network Endpoints classification was wrong twice over. It read: color = green if code in (200,302,401) else (yellow if code >= 400 else red). Two defects: (a) it ignored the fleet's own probe policy, codified 2026-09-14 in the monitoring contracts: ANY HTTP status proves the service answered, so the service is ALIVE, and only a failed CONNECTION is a failed probe. A 404 from a wrong path is not a service fault. (b) was a STRING comparison. Reproduced: 301 -> red (a live redirect rendered as a failure), 404 -> yellow, 500 -> yellow (a real server error softened to a warning). Replaced with classify_endpoint(), which returns: any 2xx/3xx/4xx -> green 'alive' (code still shown) 5xx -> yellow 'server error' (kept distinct from 4xx, as asked) 000/no answer -> red 'no connection' Verified against the live endpoints after the change: Gitea 200, Authentik 302, Zulip 302, Pulse 200, Proxmox 200, SearXNG 200, Firecrawl 200 - all green/alive; the only red state is a genuine no-connection. ALSO CHECKED, as asked: scripts/search-stack-check.py does NOT depend on the wrong route. It POSTs to {FIRECRAWL_URL}/v1/scrape with formats=[markdown], and that path really works - live POST returned HTTP 200 and 180 chars of markdown for https://example.com. It was never using /health. prose-lint: PASSED.
This commit is contained in:
@@ -243,7 +243,7 @@ def collect():
|
||||
("Pulse", "https://pulse.sysloggh.net"),
|
||||
("Proxmox", "https://192.168.68.12:8006"),
|
||||
("SearXNG", "http://192.168.68.7:8888"),
|
||||
("Firecrawl", "http://192.168.68.7:3002/health"),
|
||||
("Firecrawl", "http://192.168.68.7:3002/"), # Firecrawl serves no /health - the root is its liveness endpoint
|
||||
]
|
||||
report["endpoints"] = []
|
||||
for name, url in endpoints:
|
||||
@@ -389,6 +389,28 @@ def collect():
|
||||
|
||||
# ── HTML Dashboard ──
|
||||
|
||||
def classify_endpoint(code):
|
||||
"""Classify an endpoint probe per the fleet's probe policy.
|
||||
|
||||
Codified 2026-09-14 in the monitoring contracts: ANY HTTP status proves the
|
||||
service answered, so the service is ALIVE - 200/301/302/401/403/404 alike.
|
||||
Only a failed CONNECTION (000 / timeout / refused) is a failed probe. A 404
|
||||
from a wrong path is not a service fault and must not render as one.
|
||||
|
||||
This replaces a string comparison that was wrong in both directions
|
||||
(`ep["code"] >= "400"`): it rendered 301 as red, 404 as yellow, and a real
|
||||
500 as yellow. 5xx is kept as its own "server error" signal rather than
|
||||
being merged with 4xx.
|
||||
"""
|
||||
if not code or code == "000":
|
||||
return "red", "no connection"
|
||||
if code.startswith("5"):
|
||||
return "yellow", "server error"
|
||||
if code.startswith(("2", "3", "4")):
|
||||
return "green", "alive"
|
||||
return "yellow", f"unexpected {code}"
|
||||
|
||||
|
||||
def build_html(r):
|
||||
issues = []
|
||||
|
||||
@@ -624,7 +646,7 @@ Proxmox: {r.get('pve_probe_status', 'ok')} ({r['nodes_online']}/{r['node_count']
|
||||
# ── Network Endpoints ──
|
||||
html += '<div class="card"><h2>🌐 Network Endpoints</h2><table><tr><th>Service</th><th>Status</th></tr>'
|
||||
for ep in r["endpoints"]:
|
||||
color = "green" if ep["code"] in ("200","302","401") else ("yellow" if ep["code"] >= "400" else "red")
|
||||
color = classify_endpoint(ep["code"])[0]
|
||||
html += f'<tr><td>{ep["name"]}</td><td class="{color}">HTTP {ep["code"]}</td></tr>'
|
||||
html += '</table></div>'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user