fix(dashboard): deduplicate repeated savings metrics (#1804)
Some checks failed
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime name:]) (push) Waiting to run
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-code name:code]) (push) Waiting to run
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-code-nonroot name:code-nonroot]) (push) Waiting to run
CI / changes (push) Failing after 38s
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-code-slim name:code-slim]) (push) Waiting to run
Docker / docker-manifest (map[bake_target:runtime-code-nonroot name:code-nonroot]) (push) Blocked by required conditions
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-code-slim-nonroot name:code-slim-nonroot]) (push) Waiting to run
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-nonroot name:nonroot]) (push) Waiting to run
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-slim name:slim]) (push) Waiting to run
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-slim-nonroot name:slim-nonroot]) (push) Waiting to run
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime name:]) (push) Waiting to run
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-code name:code]) (push) Waiting to run
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-code-nonroot name:code-nonroot]) (push) Waiting to run
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-code-slim name:code-slim]) (push) Waiting to run
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-code-slim-nonroot name:code-slim-nonroot]) (push) Waiting to run
CI / commitlint (push) Failing after 3s
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-nonroot name:nonroot]) (push) Waiting to run
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-slim name:slim]) (push) Waiting to run
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-slim-nonroot name:slim-nonroot]) (push) Waiting to run
Docker / docker-manifest (map[bake_target:runtime name:]) (push) Blocked by required conditions
Docker / docker-manifest (map[bake_target:runtime-code name:code]) (push) Blocked by required conditions
CI / build-wheel (push) Failing after 3s
CI / lint (push) Failing after 3s
Docker / docker-manifest (map[bake_target:runtime-code-slim name:code-slim]) (push) Blocked by required conditions
Docker / docker-manifest (map[bake_target:runtime-code-slim-nonroot name:code-slim-nonroot]) (push) Blocked by required conditions
Docker / docker-manifest (map[bake_target:runtime-nonroot name:nonroot]) (push) Blocked by required conditions
CI / prefetch-model (push) Failing after 4s
Docker / docker-manifest (map[bake_target:runtime-slim name:slim]) (push) Blocked by required conditions
Docker / docker-manifest (map[bake_target:runtime-slim-nonroot name:slim-nonroot]) (push) Blocked by required conditions
Docker / promote-latest (push) Blocked by required conditions
CI / build (push) Failing after 2s
CI / workflow-validation (push) Failing after 6s
CI / test-extras (push) Failing after 3s
CI / docker-native-e2e (push) Failing after 5s
CI / test-agno (push) Failing after 3s
CI / test (1) (push) Failing after 4s
CI / test (2) (push) Failing after 7s
CI / test (3) (push) Failing after 4s
CI / test-dashboard-ui (push) Failing after 4s
Deploy Documentation / validate (push) Failing after 5s
CI / test (4) (push) Failing after 3s
Deploy Documentation / deploy (push) Failing after 9s
Init E2E / docker-init-e2e (push) Failing after 8s
Init Native E2E / init-native (ubuntu-latest, claude) (push) Failing after 18s
Init Native E2E / init-native (ubuntu-latest, codex) (push) Failing after 16s
Init Native E2E / init-native (ubuntu-latest, copilot) (push) Failing after 18s
Install Native E2E / install-native (ubuntu-latest) (push) Failing after 12s
Merge Conflicts / merge-conflicts (push) Failing after 12s
Release Please / release-please (push) Failing after 17s
Security / CodeQL (javascript-typescript) (push) Failing after 51s
Security / CodeQL (python) (push) Failing after 46s
Wrap E2E / docker-wrap-e2e (push) Failing after 18s
Security / Dependency audit (pip-audit) (push) Failing after 1m27s
Wrap Native E2E / wrap-native (ubuntu-latest) (push) Failing after 7s
Security / Secret scan (gitleaks) (push) Failing after 9m1s
CI / windows-native-wrapper (push) Has been cancelled
CI / macos-native-wrapper (push) Has been cancelled
Init Native E2E / init-native (macos-latest, claude) (push) Has been cancelled
Init Native E2E / init-native (macos-latest, codex) (push) Has been cancelled
Init Native E2E / init-native (macos-latest, copilot) (push) Has been cancelled
Install Native E2E / install-native (macos-latest) (push) Has been cancelled
Wrap Native E2E / wrap-native (macos-latest) (push) Has been cancelled

## Description

The session dashboard repeats the same savings and performance numbers
in adjacent places. `proxy_compression_saved` appears in several
captions and detail rows, and average overhead and TTFB appear both in
the hero area and again in Performance without adding new context.

This narrows the non-hero dashboard presentation so repeated session
metrics have one visible home plus decomposition where it adds
information. It leaves `/stats`, savings math, cache attribution, and
the hero proxy savings card unchanged.

Refs #960

## Type of Change

- [x] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring (no functional changes)

## Changes Made

- Removed redundant non-hero session-view captions that restated
proxy-compression token counts without adding a new dimension.
- Kept canonical homes for proxy compression and token usage details.
- Preserved Performance range context while avoiding adjacent
restatement of hero averages.
- Added a static dashboard regression for repeated session metrics.

## Testing

- [x] Unit tests pass (`uv run pytest
tests/test_proxy_dashboard_stats_cache.py -q`)
- [x] Linting passes (`uv run ruff check
tests/test_proxy_dashboard_stats_cache.py`)
- [ ] Type checking passes (`uv run mypy headroom`)
- [x] New tests added for new functionality
- [x] Manual testing performed

### Test Output

```text
$ uv run pytest tests/test_proxy_dashboard_stats_cache.py -q
12 passed, 1 skipped, 1 warning in 19.24s

$ uv run ruff check tests/test_proxy_dashboard_stats_cache.py
All checks passed!
```

## Real Behavior Proof

- Environment: Windows, Python environment from `uv sync --extra dev`,
browserless dashboard HTML inspection.
- Exact command / steps: load `get_dashboard_html()` in the focused
dashboard stats test and assert removed duplicate captions stay removed
while canonical metric owners remain present.
- Observed result: session-view repeated savings and performance labels
no longer duplicate the same numbers without context.
- Not tested: full browser screenshot and history-view de-duplication.

## Review Readiness

- [x] I have performed a self-review
- [x] This PR is ready for human review

## Checklist

- [x] My code follows the project's style guidelines
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] I have updated the CHANGELOG.md if applicable

## Additional Notes

No `CHANGELOG.md` edit: this repo generates changelog entries from
conventional commits. This intentionally avoids the hero proxy savings
card already covered by #927 and #1649, and it does not fold provider
cache discount into Headroom-value savings.
This commit is contained in:
Rod Boev 2026-07-05 19:00:25 -04:00 committed by GitHub
parent 451b9f0867
commit 88f935a1eb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 11 additions and 9 deletions

View file

@ -433,7 +433,6 @@
<div>
<div class="text-xs text-gray-500 mb-1">Compression</div>
<div class="text-2xl font-light tabular-nums text-emerald-400" x-text="'$' + formatCurrency(stats.cost?.compression_savings_usd || 0)"></div>
<div class="text-xs text-gray-500" x-text="formatNumber(stats.tokens?.proxy_compression_saved || 0) + ' proxy tokens removed'"></div>
</div>
<template x-if="(stats.cost?.cache_savings_usd || 0) > 0">
<div>
@ -1079,18 +1078,10 @@
<div class="bg-surface rounded-lg p-4 border border-border">
<div class="text-sm font-medium mb-4 text-gray-300">Performance</div>
<div class="space-y-3">
<div class="flex justify-between items-center">
<span class="text-sm text-gray-400">Headroom Overhead</span>
<span class="font-mono text-sm" x-text="(stats.overhead?.average_ms || 0).toFixed(0) + 'ms avg'"></span>
</div>
<div class="flex justify-between items-center">
<span class="text-sm text-gray-400">Overhead Range</span>
<span class="font-mono text-sm" x-text="(stats.overhead?.min_ms || 0).toFixed(0) + ' - ' + (stats.overhead?.max_ms || 0).toFixed(0) + 'ms'"></span>
</div>
<div class="flex justify-between items-center">
<span class="text-sm text-gray-400">TTFB (upstream)</span>
<span class="font-mono text-sm" x-text="((stats.ttfb?.average_ms || 0) / 1000).toFixed(2) + 's avg'"></span>
</div>
<div class="flex justify-between items-center">
<span class="text-sm text-gray-400">TTFB Range</span>
<span class="font-mono text-sm" x-text="((stats.ttfb?.min_ms || 0) / 1000).toFixed(2) + ' - ' + ((stats.ttfb?.max_ms || 0) / 1000).toFixed(2) + 's'"></span>

View file

@ -605,6 +605,17 @@ def test_dashboard_uses_cached_stats_and_lazy_history_feed_polling() -> None:
assert "cliFilteringLabel + ' Filtered (lifetime)'" in html
def test_dashboard_session_metrics_do_not_repeat_proxy_tokens_without_new_context() -> None:
html = get_dashboard_html()
assert "proxy tokens removed" not in html
assert '<span class="text-sm text-gray-400">Headroom Overhead</span>' not in html
assert '<span class="text-sm text-gray-400">TTFB (upstream)</span>' not in html
assert "Overhead Range" in html
assert "TTFB Range" in html
assert "Proxy Removed" in html
def test_proxy_throughput_in_stats_endpoint(monkeypatch: pytest.MonkeyPatch) -> None:
"""Verify that the /stats endpoint includes a 'throughput' key in the response.