Skip to content

feat(audit): show rewrite token savings on the Rewritten tab#507

Merged
SantiagoDePolonia merged 4 commits into
mainfrom
feat/audit-rewrite-tokens-saved-pill
Jul 7, 2026
Merged

feat(audit): show rewrite token savings on the Rewritten tab#507
SantiagoDePolonia merged 4 commits into
mainfrom
feat/audit-rewrite-tokens-saved-pill

Conversation

@SantiagoDePolonia

@SantiagoDePolonia SantiagoDePolonia commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

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% beside pro-token-compression.

  • Pill — the share of the request body the revision removed, computed from the revision's recorded bytes_before/bytes_after. Hidden when the revision didn't shrink the body. Styled with --prompt-cache-color / --prompt-cache-color-bg — the same --info blue family as the cached-tokens chart lines, with the existing per-theme tone mix keeping the text readable in both themes.
  • Recorded savings data (not displayed, available to API consumers and future UI): the audit request-revision snapshot records the rewriter-reported savings as a typed tokens_saved field (from ext.Result.TokensSaved), and usage log entries plus the audit API's per-request usage summary now expose the stored rewrite_tokens_saved / rewrite_cost_saved columns (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 savings
  • go test passes for usage, admin, auditlog, server
  • Pre-commit suite (race tests, lint, dashboard JS tests, perf guard) passes

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Audit logs now show a savings pill with the share of request body removed by a rewrite.
    • Usage summaries now include rewrite-related savings metrics for tokens and estimated cost.
  • Bug Fixes

    • Rewrite savings are now carried through consistently across log views and summaries.
    • Savings labels are hidden when the data is missing, invalid, or shows no reduction.

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>
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@SantiagoDePolonia, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 29 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d43e6e6c-27a7-4614-900d-0c532b5efa9d

📥 Commits

Reviewing files that changed from the base of the PR and between 13e8946 and 5cec2d2.

📒 Files selected for processing (4)
  • internal/usage/reader_mongodb_test.go
  • internal/usage/reader_postgresql_test.go
  • internal/usage/reader_sqlite_rewrite_savings_test.go
  • internal/usage/request_summary_test.go
📝 Walkthrough

Walkthrough

Adds 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.

Changes

Rewrite Savings Tracking

Layer / File(s) Summary
Audit savings pill
internal/auditlog/auditlog.go, internal/server/request_rewrite.go, internal/admin/dashboard/static/js/modules/audit-list.js, internal/admin/dashboard/static/js/modules/audit-list.test.cjs, internal/admin/dashboard/static/css/dashboard.css, internal/admin/dashboard/templates/page-audit-logs.html
RequestRevisionSnapshot records TokensSaved, the dashboard computes a savings label from revision sizes, and the audit log UI renders a conditional savings pill with tests covering the label logic.
Usage rewrite savings
internal/usage/reader.go, internal/usage/reader_mongodb.go, internal/usage/reader_postgresql.go, internal/usage/reader_sqlite.go, internal/usage/request_summary.go, internal/usage/request_summary_test.go
Usage log models and readers carry RewriteTokensSaved and RewriteCostSaved through MongoDB, PostgreSQL, and SQLite paths, and request summaries aggregate the new rewrite savings fields with test coverage.

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
Loading
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
Loading

Possibly related PRs

  • ENTERPILOT/GoModel#481: Both PRs propagate rewriter-reported savings through audit/usage data paths and add downstream handling for those fields.

Poem

A rabbit hops through savings bright,
From logs to charts in one soft bite.
A pill appears, neat, green, and small,
While usage totals softly call. 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: showing rewrite savings on the Rewritten audit tab.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/audit-rewrite-tokens-saved-pill

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov-commenter

codecov-commenter commented Jul 7, 2026

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 71.42857% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/usage/reader_postgresql.go 16.66% 4 Missing and 1 partial ⚠️
internal/usage/reader_sqlite.go 83.33% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@greptile-apps

greptile-apps Bot commented Jul 7, 2026

Copy link
Copy Markdown

Confidence Score: 5/5

Safe to merge with minimal risk.

The changes are focused and extend existing audit and usage enrichment paths without introducing identified correctness or security issues.

No files require special attention.

T-Rex T-Rex Logs

What T-Rex did

  • Ran the audit rewrite savings test suite and observed 41 tests passing with exit code 0.
  • Performed a browser capture of the audit rewrite savings scenario; the capture log exits 0.
  • Saved before/after videos and poster screenshots for the audit rewrite savings scenario.
  • Saved an HTML results page artifact for audit rewrite savings review.

View all artifacts

T-Rex Ran code and verified through T-Rex

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant R as Rewriter
participant S as Server request_rewrite
participant A as Audit log snapshot
participant U as Usage reader
participant API as Admin audit API
participant UI as Audit Rewritten tab

R->>S: "ext.Result{Body, TokensSaved, Detail}"
S->>A: "RequestRevisionSnapshot{bytes_before, bytes_after, tokens_saved}"
U->>API: "RequestUsageSummary{rewrite_tokens_saved, rewrite_cost_saved}"
API->>UI: audit entry + usage summary
UI->>UI: compose tokens · percent · cost pill
UI-->>UI: show savings pill beside rewriter badge
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant R as Rewriter
participant S as Server request_rewrite
participant A as Audit log snapshot
participant U as Usage reader
participant API as Admin audit API
participant UI as Audit Rewritten tab

R->>S: "ext.Result{Body, TokensSaved, Detail}"
S->>A: "RequestRevisionSnapshot{bytes_before, bytes_after, tokens_saved}"
U->>API: "RequestUsageSummary{rewrite_tokens_saved, rewrite_cost_saved}"
API->>UI: audit entry + usage summary
UI->>UI: compose tokens · percent · cost pill
UI-->>UI: show savings pill beside rewriter badge
Loading

Reviews (2): Last reviewed commit: "feat(audit): add percent and priced cost..." | Re-trigger Greptile

SantiagoDePolonia and others added 2 commits July 7, 2026 12:24
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>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 35852a4 and 13e8946.

📒 Files selected for processing (10)
  • internal/admin/dashboard/static/css/dashboard.css
  • internal/admin/dashboard/static/js/modules/audit-list.js
  • internal/admin/dashboard/static/js/modules/audit-list.test.cjs
  • internal/admin/dashboard/templates/page-audit-logs.html
  • internal/usage/reader.go
  • internal/usage/reader_mongodb.go
  • internal/usage/reader_postgresql.go
  • internal/usage/reader_sqlite.go
  • internal/usage/request_summary.go
  • internal/usage/request_summary_test.go

Comment on lines +40 to 42
RewriteTokensSaved int64 `bson:"rewrite_tokens_saved"`
RewriteCostSaved *float64 `bson:"rewrite_cost_saved"`
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 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.

Comment on lines 215 to 218
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)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 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.

Comment on lines 207 to 210
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 ?`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 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.

Comment thread internal/usage/request_summary_test.go Outdated
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>
@SantiagoDePolonia SantiagoDePolonia merged commit 47cc070 into main Jul 7, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants