Skip to content

Commit c7ff91f

Browse files
committed
Show redacted event details on dashboard
1 parent d9f6110 commit c7ff91f

2 files changed

Lines changed: 84 additions & 6 deletions

File tree

src/codex_fast_proxy/dashboard.py

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,22 @@
1212
DASHBOARD_PATH = "/__codex_fast_proxy/dashboard"
1313
DASHBOARD_EVENT_LIMIT = 8
1414
BENCHMARK_FILENAME = "fast_proxy.benchmark.json"
15+
EVENT_DETAIL_FIELDS = (
16+
"ts",
17+
"request_id",
18+
"method",
19+
"path",
20+
"status",
21+
"duration_ms",
22+
"eligible",
23+
"service_tier_before",
24+
"service_tier_after",
25+
"service_tier_injected",
26+
"stream",
27+
"json_error",
28+
"response_content_type",
29+
"error_type",
30+
)
1531

1632

1733
def safe_url_display(url: str) -> str:
@@ -512,7 +528,7 @@ def render_dashboard(server: Any) -> str:
512528
<h2>Recent requests</h2>
513529
<p>pid {html_value(os.getpid())} / injected {injected_count}</p>
514530
</div>
515-
{render_status_badge(last_status)}
531+
{render_status_badge(last_status, event_detail(latest_event))}
516532
</div>
517533
<div class="table-wrap">
518534
<table>
@@ -600,17 +616,30 @@ def render_injection_state(event: dict[str, Any] | None) -> str:
600616
return "yes" if event.get("service_tier_injected") else "no"
601617

602618

603-
def render_status_badge(status: Any) -> str:
619+
def event_detail(event: dict[str, Any] | None) -> str | None:
620+
if not event:
621+
return None
622+
623+
lines = []
624+
for field in EVENT_DETAIL_FIELDS:
625+
value = event.get(field)
626+
if value is not None:
627+
lines.append(f"{field}: {value}")
628+
return "\n".join(lines) if lines else None
629+
630+
631+
def render_status_badge(status: Any, detail: str | None = None) -> str:
632+
title = f' title="{html_value(detail, "")}"' if detail else ""
604633
if status is None:
605-
return '<span class="badge"><span class="dot warn" aria-hidden="true"></span>No events</span>'
634+
return f'<span class="badge"{title}><span class="dot warn" aria-hidden="true"></span>No events</span>'
606635
try:
607636
status_code = int(status)
608637
except (TypeError, ValueError):
609-
return f'<span class="badge"><span class="dot warn" aria-hidden="true"></span>{html_value(status)}</span>'
638+
return f'<span class="badge"{title}><span class="dot warn" aria-hidden="true"></span>{html_value(status)}</span>'
610639

611640
dot_class = "bad" if status_code >= 400 else ""
612641
label = "Needs attention" if status_code >= 400 else "Healthy"
613-
return f'<span class="badge"><span class="dot {dot_class}" aria-hidden="true"></span>{label}</span>'
642+
return f'<span class="badge"{title}><span class="dot {dot_class}" aria-hidden="true"></span>{label}</span>'
614643

615644

616645
def benchmark_fast_label(benchmark: dict[str, Any]) -> str:
@@ -726,7 +755,7 @@ def render_event_row(event: dict[str, Any]) -> str:
726755
"<tr>"
727756
f"<td>{render_time_value(event.get('ts'))}</td>"
728757
f"<td class=\"path\" title=\"{html_value(event.get('path'), '')}\">{html_value(event.get('method'))} {html_value(event.get('path'))}</td>"
729-
f"<td>{render_status_badge(status)}</td>"
758+
f"<td>{render_status_badge(status, event_detail(event))}</td>"
730759
f"<td>{html_value(format_duration(event.get('duration_ms')))}</td>"
731760
f"<td>{render_tier_change(event)}</td>"
732761
f"<td>{render_boolean_badge(injected)}</td>"

tests/test_proxy.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,55 @@ def test_dashboard_uses_only_redacted_event_fields(self) -> None:
277277
self.assertNotIn("Bearer should-not-render", html)
278278
self.assertNotIn("prompt should-not-render", html)
279279

280+
def test_dashboard_status_badge_exposes_redacted_event_detail(self) -> None:
281+
temp_root = ROOT / ".test_tmp"
282+
temp_root.mkdir(exist_ok=True)
283+
temp_dir = temp_root / f"dashboard-detail-{uuid.uuid4().hex}"
284+
temp_dir.mkdir()
285+
try:
286+
log_path = temp_dir / "fast_proxy.jsonl"
287+
log_path.write_text(
288+
json.dumps({
289+
"ts": "2026-05-05T06:10:39.890+00:00",
290+
"request_id": "req-demo",
291+
"method": "POST",
292+
"path": "/v1/responses",
293+
"status": 502,
294+
"duration_ms": 24501.2,
295+
"eligible": True,
296+
"service_tier_before": "<absent>",
297+
"service_tier_after": "priority",
298+
"service_tier_injected": True,
299+
"stream": True,
300+
"response_content_type": None,
301+
"error_type": "client_disconnected",
302+
"Authorization": "Bearer should-not-render",
303+
"input": "prompt should-not-render",
304+
})
305+
+ "\n",
306+
encoding="utf-8",
307+
)
308+
server = SimpleNamespace(
309+
log_path=log_path,
310+
server_address=("127.0.0.1", 8787),
311+
proxy_base="/v1",
312+
upstream_base="https://api.example.test/v1",
313+
service_tier="priority",
314+
)
315+
316+
html = render_dashboard(server)
317+
finally:
318+
shutil.rmtree(temp_dir)
319+
320+
self.assertIn("Needs attention", html)
321+
self.assertIn("request_id: req-demo", html)
322+
self.assertIn("status: 502", html)
323+
self.assertIn("duration_ms: 24501.2", html)
324+
self.assertIn("error_type: client_disconnected", html)
325+
self.assertIn("service_tier_before: &lt;absent&gt;", html)
326+
self.assertNotIn("Bearer should-not-render", html)
327+
self.assertNotIn("prompt should-not-render", html)
328+
280329
def test_dashboard_renders_saved_benchmark_result(self) -> None:
281330
temp_root = ROOT / ".test_tmp"
282331
temp_root.mkdir(exist_ok=True)

0 commit comments

Comments
 (0)