refactor: replay metrics come from spans, and ReplayMetrics is gone
Summary
Part of #389, the replay area, and fixes #318: the replay queue size gauge carried a session_id label, so every session left its own series behind. The fifteen instruments in ReplayMetrics now come from spans.
Changes
EventReplayService leaves a span where it used to record each metric: replay.session_created, replay.session_started, replay.status_change, replay.event, replay.batch, replay.session_completed and replay.target. The collector's signaltometrics connector turns them into the same series. The API's scheduler gets one more job: every 10 s report_sessions reports the sessions held per status, zeros included, and the loaded events still to send, summed over sessions. replay_sessions_active goes, since running plus paused from the per-status gauge is the same number, and the dashboard panel now sums those. Labels take the span attribute names (replay_status, replay_target, ...).
Type of Change
- 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
- Refactoring (no functional changes)
- CI/CD or tooling changes
Test Plan
- Backend unit tests pass (
cd backend && uv run pytest tests/unit) - Frontend unit tests pass (
cd frontend && npm run test) - Backend E2E tests pass (
docker compose exec -T backend sh -c 'uv sync --group test --no-dev --frozen --no-install-project --no-build && pytest tests/e2e') - Frontend E2E tests pass (
cd frontend && npm run test:e2e) - API spec and client regenerated if routes or schemas changed (
./deploy.sh openapi, then./deploy.sh types), never edited by hand - Manual testing performed
Validation: unit 570 passed, contract 3 passed, e2e 488 passed and 1 skipped. Four real sessions run from the API container gave exactly the expected totals at the collector (4 created, 4 batches of 10, speed multipliers summing to 398). Duration and throughput are only unit-tested: no live session could complete, since main's dispatch job skips its own next run when the delay is short.
Checklist
- My code follows the project's style guidelines
- I have run
pre-commit run --all-filesand all checks pass - I have added tests that prove my fix/feature works
- I have updated documentation if needed
- My changes don't introduce new warnings
Summary by cubic
Moves replay metrics from the ReplayMetrics instruments to spans that the collector's signaltometrics connector turns into the same series, deleting ReplayMetrics as part of #389. Fixes #318 by dropping the session_id label from the queue size gauge, which had created a series per session.
EventReplayServicenow recordsreplay.session_created,replay.session_started,replay.status_change,replay.event,replay.batch,replay.session_completed, andreplay.targetspans.- The API scheduler runs
report_sessionsevery 10 s to report sessions per status (zeros included) and loaded events still to send. replay_sessions_activeis gone; the dashboard panel sums running and paused from the per-status gauge instead.- Labels use the span attribute names (
replay_status,replay_target, ...).