feat(obs): add model label to aisix_llm_tokens_by_client_total and record it on /v1/responses - #784
Conversation
…n /v1/responses aisix_llm_tokens_by_client_total now carries a model label (the requested logical model, same value as the aisix_llm_* families' model) so operators can see which models each client type spends tokens on. The /v1/responses usage funnel now records the series too — codex is an allowlisted client_type but talks to /v1/responses, which previously recorded nothing, leaving codex traffic invisible in the metric. Fixes api7/AISIX-Cloud#1044
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 47 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: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthrough
ChangesClient token metrics by model
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant ChatEndpoint
participant MessagesEndpoint
participant ResponsesEndpoint
participant Metrics
Client->>ChatEndpoint: Send chat completion request
ChatEndpoint->>Metrics: Record tokens with client type and logical model
Client->>MessagesEndpoint: Send Anthropic messages request
MessagesEndpoint->>Metrics: Record usage with client type and logical model
Client->>ResponsesEndpoint: Send Responses request
ResponsesEndpoint->>Metrics: Record usage and cache-inclusive total
Metrics-->>Client: Expose input, output, and total metric series
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@tests/e2e/src/cases/tokens-by-client-model-1044-e2e.test.ts`:
- Around line 144-148: Update the shared beforeAll setup containing createApiKey
to await waitConfigPropagation after seeding the models, then remove the
test-local wait so every test, including the Responses test, relies on shared
configuration readiness rather than execution order.
🪄 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: CHILL
Plan: Pro
Run ID: 106e1eb4-771f-404b-a5bf-780aa8486096
📒 Files selected for processing (6)
crates/aisix-obs/src/metrics.rscrates/aisix-proxy/src/chat.rscrates/aisix-proxy/src/messages.rscrates/aisix-proxy/src/responses.rstests/e2e/src/cases/tokens-by-client-model-1044-e2e.test.tstests/e2e/src/cases/tokens-by-client-total-1002-e2e.test.ts
Both tests now rely on shared readiness instead of the Responses test inheriting the first test's wait, so each is independently runnable.
Fixes api7/AISIX-Cloud#1044
Fixes api7/AISIX-Cloud#1091
What
modellabel onaisix_llm_tokens_by_client_total. Every series now carries the requested logical model — the exact value the same request records in theaisix_llm_*families'modellabel — sosum by (client_type, model)can answer "which models is each client type spending tokens on" (per-client model-usage analysis, cost governance, migration tracking)./v1/responsesnow records the by-client series. Codex is an allowlistedclient_typebut talks to/v1/responses, which previously recorded nothing into this metric — codex traffic was invisible. The recording sits in the endpoint's single usage funnel (emit_usage_event), covering the non-streaming, verbatim-streaming, and cross-provider bridge-streaming paths.Design notes
modelis threaded from each call site's existingUsageLabels.modelvalue (chat non-streaming / chat SSEon_complete/ messages funnel), so by-client and theaisix_llm_*families agree by construction — the label is the validated logical model, never the raw client string or the routedupstream_model. On/v1/responsesthe model resolved at dispatch on every usage-bearing path, so the label stays bounded by the configured model set.token_type="total"keeps its cache-inclusive semantics (feat(obs): add cache-inclusive token_type=total to tokens_by_client metric #740/#1002): chat/messages pass their canonical totals unchanged;/v1/responsesuses the sharedtotal_tokens_with_cachehelper (cache counters are non-zero only on the feat(auth): inbound OIDC/JWT authentication — trust providers + jwt_subject key binding #825 Anthropic bridge path).client_type × model × token_type— bounded client allowlist × configured model set × 3. Per-key/team/user dimensions intentionally remain exclusive to theaisix_llm_*_tokens_totalfamilies; the per-key family likewise intentionally stays chat/messages-scoped (cross-API audit fix(responses): attribute per-PK telemetry tags on /v1/responses usage events #646-652 judgment, unchanged here).Compatibility
Adding a label starts new time series; the old label-set series stop growing. Aggregations like
sum by (client_type)keep working; only exact-matcher queries pinning the full label set need updating. Docs PR updating the metrics reference: api7/docs (paired).Tests
token_typeslice; one client × two models → six independent series with per-model counts; all-zero no-op unchanged.aisix+ etcd + mock upstream): oneclient_typecalling two chat models (non-streaming + streaming) yields two per-model series with correct counts;/v1/responseswith a codex UA produces the series (fails before the fix — the endpoint recorded nothing); the #1002 cache-inclusive messages test now also pins themodellabel.Summary by CodeRabbit
New Features
Bug Fixes
Tests