feat(audit): show rewrite token savings on the Rewritten tab#507
Conversation
Record the rewriter-reported TokensSaved as a typed tokens_saved field on the audit request-revision snapshot, and render it in the audit log record's tab strip as a blue pill next to the rewriter badge (e.g. "-12.3K tokens" beside pro-token-compression). The pill reuses the prompt-cache blue — the same --info family as the cached-tokens chart lines, tone-mixed per theme for contrast. Older entries without the typed field fall back to the compression report's tokens_saved_estimate in the revision detail. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 29 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughAdds rewrite savings fields to audit and usage data paths, records token savings on request revisions, computes and displays an audit savings pill, and aggregates rewrite savings through usage readers and request summaries. ChangesRewrite Savings Tracking
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant request_rewrite.go
participant auditlog.RequestRevisionSnapshot
participant audit-list.js
participant page-audit-logs.html
request_rewrite.go->>auditlog.RequestRevisionSnapshot: record TokensSaved from rewriter result
audit-list.js->>audit-list.js: auditRevisionPercentLabel(revision)
audit-list.js->>page-audit-logs.html: pane.savingsLabel
page-audit-logs.html->>page-audit-logs.html: render .audit-savings-pill when label is present
sequenceDiagram
participant MongoDB/PostgreSQL/SQLite readers
participant UsageLogEntry
participant SummarizeRequestUsage
participant RequestUsageSummary
MongoDB/PostgreSQL/SQLite readers->>UsageLogEntry: populate rewrite savings fields
UsageLogEntry->>SummarizeRequestUsage: pass entries into aggregation
SummarizeRequestUsage->>RequestUsageSummary: accumulate rewrite savings totals
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Extend the Rewritten tab's savings pill from "-89 tokens" to "-89 tokens · -21% · ~$0.0372": the percent is the share of the request body the revision removed (from the recorded byte sizes), and the cost is the request's priced rewrite savings apportioned by each revision's share of the saved tokens. The cost rides the audit API's existing per-request usage summary join — usage log entries and request summaries now expose the stored rewrite_tokens_saved / rewrite_cost_saved columns, so the pill shows exactly what the Usage page prices (tier-aware, per the request's recorded pricing). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Display just the share of the request body the rewrite removed (e.g. "-44%") instead of the tokens/percent/cost composite — one glanceable number next to the rewriter badge. The savings data stays recorded (typed tokens_saved on the revision snapshot, priced savings on the usage summary join) for the audit trail and API consumers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@internal/usage/reader_mongodb.go`:
- Around line 40-42: Add Mongo reader test coverage for the rewrite savings
mappings in the reader type used by the Mongo decode path. Update the tests
around the `ReaderMongoDB`/Mongo reader decoding so they explicitly verify
`rewrite_tokens_saved` and `rewrite_cost_saved` are read into
`RewriteTokensSaved` and `RewriteCostSaved`, including a case where
`rewrite_cost_saved` is nil. This should lock in the BSON-to-field mapping and
cover the missing branches in the decode logic.
In `@internal/usage/reader_postgresql.go`:
- Around line 215-218: Add table-driven test coverage around the PostgreSQL
usage reader’s SELECT/Scan path in reader_postgresql.go, focusing on the new
rewrite-savings fields. Exercise the query-building and row-scanning logic in
the usage reader methods that construct dataQuery and scan rows so both null and
non-null rewrite_cost_saved (and rewrite_tokens_saved) cases are covered. Use
the existing reader functions and scan targets to verify column order stays
aligned and catches regressions in the added rewrite-savings columns.
In `@internal/usage/reader_sqlite.go`:
- Around line 207-210: Add table-driven tests around the usage SQLite query/scan
path to cover the new rewrite-savings fields, especially null and non-null
rewrite_cost_saved values. Update the scan/query coverage in the reader_sqlite
flow (the SELECT built in the usage query plus the corresponding scan logic in
the usage reader methods) so the new COALESCE(rewrite_tokens_saved, 0) and
rewrite_cost_saved handling is exercised for both cases and the partial line is
covered.
In `@internal/usage/request_summary_test.go`:
- Around line 36-67: Refactor the two `SummarizeRequestUsage` test cases in
`request_summary_test.go` into a single table-driven test, keeping the same
assertions for rewrite token aggregation and nil/non-nil `RewriteCostSaved`
handling. Use a slice of cases with descriptive names and per-case expected
values so additional edge cases can be added easily, and preserve the existing
coverage currently provided by
`TestSummarizeRequestUsage_AggregatesRewriteSavings` and
`TestSummarizeRequestUsage_NoRewriteSavingsLeavesCostNil`.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 7ce36d09-d779-4efd-a96c-8ff674c701b6
📒 Files selected for processing (10)
internal/admin/dashboard/static/css/dashboard.cssinternal/admin/dashboard/static/js/modules/audit-list.jsinternal/admin/dashboard/static/js/modules/audit-list.test.cjsinternal/admin/dashboard/templates/page-audit-logs.htmlinternal/usage/reader.gointernal/usage/reader_mongodb.gointernal/usage/reader_postgresql.gointernal/usage/reader_sqlite.gointernal/usage/request_summary.gointernal/usage/request_summary_test.go
| RewriteTokensSaved int64 `bson:"rewrite_tokens_saved"` | ||
| RewriteCostSaved *float64 `bson:"rewrite_cost_saved"` | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
Add mongo reader test coverage for rewrite savings fields.
Codecov flags 2 missing lines in this file. Add a case to the mongo reader tests decoding rewrite_tokens_saved/rewrite_cost_saved (including the nil-cost case) to lock in the mapping.
Also applies to: 66-67
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@internal/usage/reader_mongodb.go` around lines 40 - 42, Add Mongo reader test
coverage for the rewrite savings mappings in the reader type used by the Mongo
decode path. Update the tests around the `ReaderMongoDB`/Mongo reader decoding
so they explicitly verify `rewrite_tokens_saved` and `rewrite_cost_saved` are
read into `RewriteTokensSaved` and `RewriteCostSaved`, including a case where
`rewrite_cost_saved` is nil. This should lock in the BSON-to-field mapping and
cover the missing branches in the decode logic.
| dataQuery := fmt.Sprintf(`SELECT id, request_id, provider_id, timestamp, model, provider, provider_name, endpoint, user_path, cache_type, labels, | ||
| input_tokens, output_tokens, total_tokens, input_cost, output_cost, total_cost, COALESCE(cost_source, ''), raw_data, COALESCE(costs_calculation_caveat, '') | ||
| input_tokens, output_tokens, total_tokens, input_cost, output_cost, total_cost, COALESCE(cost_source, ''), raw_data, COALESCE(costs_calculation_caveat, ''), | ||
| COALESCE(rewrite_tokens_saved, 0), rewrite_cost_saved | ||
| FROM "usage"%s ORDER BY timestamp DESC LIMIT $%d OFFSET $%d`, where, argIdx, argIdx+1) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
Add scan/query test coverage for the new rewrite-savings columns.
Codecov reports 6 missing lines in this file, aligning with the new SELECT/Scan additions. A table-driven test exercising both null and non-null rewrite_cost_saved rows would catch column-order regressions like this early.
Also applies to: 258-261, 293-295
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@internal/usage/reader_postgresql.go` around lines 215 - 218, Add table-driven
test coverage around the PostgreSQL usage reader’s SELECT/Scan path in
reader_postgresql.go, focusing on the new rewrite-savings fields. Exercise the
query-building and row-scanning logic in the usage reader methods that construct
dataQuery and scan rows so both null and non-null rewrite_cost_saved (and
rewrite_tokens_saved) cases are covered. Use the existing reader functions and
scan targets to verify column order stays aligned and catches regressions in the
added rewrite-savings columns.
| dataQuery := `SELECT id, request_id, provider_id, timestamp, model, provider, provider_name, endpoint, user_path, cache_type, labels, | ||
| input_tokens, output_tokens, total_tokens, input_cost, output_cost, total_cost, COALESCE(cost_source, ''), raw_data, COALESCE(costs_calculation_caveat, '') | ||
| input_tokens, output_tokens, total_tokens, input_cost, output_cost, total_cost, COALESCE(cost_source, ''), raw_data, COALESCE(costs_calculation_caveat, ''), | ||
| COALESCE(rewrite_tokens_saved, 0), rewrite_cost_saved | ||
| FROM usage` + where + ` ORDER BY ` + sqliteTimestampEpochExpr() + ` DESC, id DESC LIMIT ? OFFSET ?` |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
Add scan/query test coverage for the new rewrite-savings columns.
Codecov reports 2 missing + 1 partial line here, matching the new SELECT/Scan additions. Add table-driven coverage for null vs. non-null rewrite_cost_saved.
Also applies to: 249-252, 286-288
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@internal/usage/reader_sqlite.go` around lines 207 - 210, Add table-driven
tests around the usage SQLite query/scan path to cover the new rewrite-savings
fields, especially null and non-null rewrite_cost_saved values. Update the
scan/query coverage in the reader_sqlite flow (the SELECT built in the usage
query plus the corresponding scan logic in the usage reader methods) so the new
COALESCE(rewrite_tokens_saved, 0) and rewrite_cost_saved handling is exercised
for both cases and the partial line is covered.
Review follow-up: lock the new rewrite_tokens_saved / rewrite_cost_saved read paths — SQLite end-to-end through GetUsageLog and GetUsageByRequestIDs, the PostgreSQL scan path via a fake pgxRows laid out in SELECT column order, and the Mongo BSON-to-field mapping — each with null and non-null cost cases. Also fold the two rewrite-savings summary tests into one table-driven test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Summary
Audit log records now show how much a request rewrite compressed the request, as a blue pill on the Rewritten tab right next to the rewriter badge — e.g.
-44%besidepro-token-compression.bytes_before/bytes_after. Hidden when the revision didn't shrink the body. Styled with--prompt-cache-color/--prompt-cache-color-bg— the same--infoblue family as the cached-tokens chart lines, with the existing per-theme tone mix keeping the text readable in both themes.tokens_savedfield (fromext.Result.TokensSaved), and usage log entries plus the audit API's per-request usage summary now expose the storedrewrite_tokens_saved/rewrite_cost_savedcolumns (SQLite, PostgreSQL, MongoDB readers) — the tier-aware priced savings the Usage page reports.The pill applies to any rewriter revision that shrank the request, not just compression.
Test plan
audit-list.test.cjs: pane exposes the percent label; percent edge cases (missing sizes, grown body, sub-10% precision) (38/38 pass)request_summary_test.go: rewrite savings aggregation across usage entries; nil cost stays nil without savingsgo testpasses forusage,admin,auditlog,server🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes