Skip to content

feat(observability): OpenAI answer spend snapshot on the deep health probe#585

Merged
BigSimmo merged 1 commit into
mainfrom
claude/spend-telemetry
Jul 13, 2026
Merged

feat(observability): OpenAI answer spend snapshot on the deep health probe#585
BigSimmo merged 1 commit into
mainfrom
claude/spend-telemetry

Conversation

@BigSimmo

Copy link
Copy Markdown
Owner

What

Wave 2a of the repo-productivity program. Turns the already-persisted per-answer token counts (rag_retrieval_logs.metadata.answer.tokens) into a cost signal on the deep /api/health probe, so a budget regression — like the reasoning-token starvation incident, or a pricing/traffic change — is visible before the bill arrives.

  • src/lib/observability/spend-metrics.tsspendSnapshot() aggregates answer-path token usage over a trailing window, derives USD from a configurable per-token price, splits by route (fast/strong) and model, and adds a 24h projection + alert flag. Zero-migration (reads existing JSONB). Reasoning tokens are surfaced but billed within output (never double-counted); cached input billed at the cheaper rate. Throws on query error so the caller nulls the block.
  • src/lib/health-response.ts — optional spend block gated exactly like slo/cache (token-authorized deep probe + healthy Supabase, errors → null, never flips liveness). Suppressible via includeSpend: false.
  • src/lib/env.tsOPENAI_PRICE_{INPUT,CACHED_INPUT,OUTPUT}_PER_MTOK (operator-tunable placeholders — set to live OpenAI price) + SPEND_ALERT_DAILY_USD.
  • tests/spend-metrics.test.ts — 9 offline tests (cost math, route/model split, daily projection + alert, empty window, truncated sample, error path).

Verification

20/20 vitest (spend + health-route + answer-slo), tsc --noEmit, eslint, prettier — all green. No live provider calls; the block only activates behind the existing secret-gated deep probe.

Operator note

The three OPENAI_PRICE_* env vars ship as placeholders — set them to the live OpenAI price for the answer model to make the USD figures accurate. SPEND_ALERT_DAILY_USD=0 (default) leaves the alert flag off.

🤖 Generated with Claude Code

…probe

Wave 2a of the repo-productivity program. Turns the already-persisted per-answer
token counts (rag_retrieval_logs.metadata.answer.tokens) into a cost signal so a
budget regression — like the reasoning-token starvation incident, or a pricing/
traffic change — is visible before the bill arrives.

- src/lib/observability/spend-metrics.ts: spendSnapshot() aggregates answer-path
  token usage over a trailing window, derives USD from a configurable per-token
  price, and splits by route (fast/strong) and model, with a 24h projection and
  an alert flag. Zero-migration (reads existing JSONB); reasoning tokens surfaced
  but billed within output (never double-counted); cached input billed at the
  cheaper rate. Throws on query error so the caller nulls the block.
- health-response.ts: optional `spend` block gated exactly like `slo`/`cache`
  (token-authorized deep probe + healthy Supabase, errors → null, never flips
  liveness). Suppressible via includeSpend: false.
- env.ts: OPENAI_PRICE_{INPUT,CACHED_INPUT,OUTPUT}_PER_MTOK (operator-tunable
  placeholders) + SPEND_ALERT_DAILY_USD.
- tests/spend-metrics.test.ts: 9 offline tests (cost math, route/model split,
  daily projection + alert, empty window, truncated sample, error path).

Verified: 20/20 vitest (spend + health-route + answer-slo), tsc --noEmit, eslint,
prettier — all green. No live provider calls.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@supabase

supabase Bot commented Jul 13, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project sjrfecxgysukkwxsowpy because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@BigSimmo
BigSimmo enabled auto-merge (squash) July 13, 2026 13:55
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added spend tracking for answer generation, including token-based cost calculations by model and route.
    • Added projected 24-hour spending, configurable daily spend alerts, and sample-truncation indicators.
    • Added optional spend details to deep health-check responses.
    • Added configurable OpenAI pricing and daily alert threshold settings.
  • Tests

    • Added coverage for spend calculations, aggregation, alerts, empty results, truncation, and error handling.

Walkthrough

Adds OpenAI pricing and spend-alert environment settings, implements token-based spend aggregation, and exposes spend snapshots through authorized deep health probes with test coverage.

Changes

Answer Spend Telemetry

Layer / File(s) Summary
Spend contracts and cost calculation
src/lib/observability/spend-metrics.ts, tests/spend-metrics.test.ts
Defines spend types, safe numeric handling, token-cost calculation, probe-client contracts, and unit tests for pricing behavior.
Spend snapshot aggregation
src/lib/observability/spend-metrics.ts, tests/spend-metrics.test.ts
Queries retrieval logs, aggregates spend by route and model, projects daily spend, evaluates alerts, handles capped samples, and tests errors and empty windows.
Health probe spend integration
src/lib/env.ts, src/lib/health-response.ts
Adds pricing and threshold configuration, conditionally fetches spend for authorized deep probes, and includes successful snapshots in health responses.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant HealthProbe
  participant SpendSnapshot
  participant Supabase
  HealthProbe->>Supabase: validate deep health state
  HealthProbe->>SpendSnapshot: request configured spend snapshot
  SpendSnapshot->>Supabase: query retrieval log token metadata
  Supabase-->>SpendSnapshot: return rows
  SpendSnapshot-->>HealthProbe: return aggregated spend
  HealthProbe-->>HealthProbe: serialize spend in response
Loading
🚥 Pre-merge checks | ✅ 5 | ❌ 6

❌ Failed checks (6 inconclusive)

Check name Status Explanation Resolution
Generated And Sensitive Files ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Verification Claims ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Risky Git Or Deployment Actions ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Supabase Project And Schema Safety ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Runtime And Package Manager Integrity ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Api Route Failure Handling ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely matches the main change: adding an OpenAI spend snapshot to the deep health probe.
Description check ✅ Passed The description is detailed and covers summary and verification, but it omits the template's Clinical Governance Preflight and Notes sections.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/spend-telemetry
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/spend-telemetry

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 323d9cb5d9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/lib/health-response.ts
@github-actions

Copy link
Copy Markdown

@codex resolve actionable Codex review findings for this pull request and current head using the repository instructions. This is the pull request's single automatic repair pass: do not perform a fresh review, create new standalone findings, or request another review. Work only the existing unresolved Codex threads on the current head. Always fix P0 and P1 findings. For P2 and lower findings, fix only clear, scoped, low-risk issues; otherwise disposition them with a concise reason. After fixing or dispositioning a thread, reply in that thread with as the first line, followed by a concise summary; that marker authorizes the workflow to close that exact thread. If human input or new authorization is required, do not use the marker and leave the thread open with the blocker. Finish only after every actionable thread is fixed or dispositioned and closed, or explicitly left open for a human decision. Do not update the branch from main, address unrelated reviews, broaden scope, or create more than one scoped fix commit. Do not use external APIs, paid services, credentials, dependency changes, or broad refactors unless explicitly authorized. Add targeted tests where behavior changes and run the narrowest relevant validation.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

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

🧹 Nitpick comments (1)
src/lib/observability/spend-metrics.ts (1)

142-147: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add an explicit order before .limit(rowCap) for deterministic truncation.

Without .order(), PostgREST/Postgres row order under the cap is unspecified, so when sampleTruncated is true the specific 5000 rows retained (and thus the totals/projection) can vary between otherwise-identical calls. Ordering by created_at (e.g. descending, to keep the most recent activity when truncated) would make the lower-bound behavior documented in the sampleTruncated comment (Line 55-56) actually deterministic.

♻️ Suggested fix
   const result = await client
     .from("rag_retrieval_logs")
     .select("query_class, metadata")
     .gt("created_at", sinceIso)
     .eq("metadata->answer->>log_source", "answer")
+    .order("created_at", { ascending: false })
     .limit(rowCap);
🤖 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 `@src/lib/observability/spend-metrics.ts` around lines 142 - 147, Update the
query chain in the spend-metrics retrieval flow to add an explicit created_at
ordering before limit(rowCap), using descending order to retain the most recent
rows when truncated. Keep the existing filters and cap unchanged.
🤖 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.

Nitpick comments:
In `@src/lib/observability/spend-metrics.ts`:
- Around line 142-147: Update the query chain in the spend-metrics retrieval
flow to add an explicit created_at ordering before limit(rowCap), using
descending order to retain the most recent rows when truncated. Keep the
existing filters and cap unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 86a19291-5edc-4ca3-8634-5de8a47d9988

📥 Commits

Reviewing files that changed from the base of the PR and between b8b4843 and 323d9cb.

📒 Files selected for processing (4)
  • src/lib/env.ts
  • src/lib/health-response.ts
  • src/lib/observability/spend-metrics.ts
  • tests/spend-metrics.test.ts

@BigSimmo
BigSimmo merged commit c2ba53e into main Jul 13, 2026
18 checks passed
@BigSimmo
BigSimmo deleted the claude/spend-telemetry branch July 13, 2026 16:37
@coderabbitai coderabbitai Bot mentioned this pull request Jul 19, 2026
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.

1 participant