feat(inference): log gateway quota headers on 429 - #2241
feat(inference): log gateway quota headers on 429#2241rosetta-livekit-bot[bot] wants to merge 1 commit into
Conversation
🦋 Changeset detectedLatest commit: d385403 The changes in this PR will be included in the next version bump. This PR includes changesets to release 39 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
| 'X-LiveKit-Inference-Credits-Used': 'creditsUsed', | ||
| } as const; | ||
|
|
||
| export function extractQuotaUsage(headers: Headers): Record<string, string> { |
There was a problem hiding this comment.
🟡 New shared helper for reading quota data is published without documentation
The newly exported helper that pulls quota numbers out of response headers (extractQuotaUsage at agents/src/inference/utils.ts:34) ships with no TypeDoc comment, which the repository's contribution rules require for every new exported function.
Impact: The generated API documentation will have an undocumented entry, so users cannot tell what the helper returns.
Rule source and location
CONTRIBUTING.md states: "If writing new methods/interfaces/enums/classes, document them. This project uses TypeDoc for automatic API documentation generation, and every new addition has to be properly documented." The new exported function at agents/src/inference/utils.ts:34-41 has only a non-doc // comment above the constant at agents/src/inference/utils.ts:23-24, not a /** */ TypeDoc block on the function itself.
| export function extractQuotaUsage(headers: Headers): Record<string, string> { | |
| /** | |
| * Extract the inference gateway quota usage headers (RPM/TPM/credits limits and | |
| * usage) from a response's headers. Missing or empty dimensions are omitted. | |
| * | |
| * @param headers - Response headers stamped by the inference gateway. | |
| * @returns A map of camelCase quota field names to their stringified values. | |
| */ | |
| export function extractQuotaUsage(headers: Headers): Record<string, string> { |
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
Port livekit/agents#6736 so inference LLM 429 responses log the gateway's RPM, TPM, and credits quota snapshot before preserving the existing error path.
HeaderslookupSource diff coverage
livekit-agents/livekit/agents/inference/_utils.py->agents/src/inference/utils.ts. PythonMappinglookup is adapted to nativeHeaders.get(), preserving case-insensitive lookup and omission of missing/empty values. Structured field names use the target's camelCase logging convention.livekit-agents/livekit/agents/inference/llm.py->agents/src/inference/llm.ts. The source's 429 warning is adapted to the existing OpenAIAPIErrorbranch and Pino object-first logger while leavingAPIStatusErrorconversion and retryability unchanged.tests/test_inference_utils.py->agents/src/inference/utils.test.tsandagents/src/inference/llm.test.ts. All four quota extraction cases and both 429 logging cases added by the source PR are ported, split according to the target's co-located test organization.No source files or behaviors were omitted. The target already had the required response-header, request-ID, and structured-logging infrastructure.
Testing
pnpm test agents(1,591 passed, 5 skipped)pnpm buildpnpm lintpnpm format:checkpnpm --filter @livekit/agents typecheckSource: livekit/agents#6736
Ported from livekit/agents#6736
Original PR description
Summary
When an
inference.LLMrequest is rejected with a 429, customers currently get a bareAPIStatusErrorwith no indication of which limit they hit or by how much. The agent gateway now stamps quota telemetry headers on LLM completions responses (livekit/agent-gateway,X-LiveKit-Inference-*), including on rate-limit rejections — this PR surfaces that snapshot in the agent logs.On a 429,
inference.LLMnow emits a structured warning before raising:X-LiveKit-Inference-RPM-{Limit,Used}— requests/min for the project × model bucketX-LiveKit-Inference-TPM-{Limit,Used}— tokens/minX-LiveKit-Inference-Credits-{Limit,Used}— cumulative token-credit balanceOnly dimensions the gateway actually stamped are logged (a missing header means "not enforced / no data", never zero), so responses from older gateways just log model + request_id. The existing
APIStatusErrorraise path is unchanged.Changes
inference/_utils.py:extract_quota_usage()maps the gateway's quota headers to log-friendly fields (rpm_limit,tpm_used, …)inference/llm.py:LLMStream._log_rate_limited()logs the quota snapshot on 429 before re-raisingtests/test_inference_utils.py: unit coverage for header extraction (all dimensions, partial, empty, case-insensitivehttpx.Headers) and the 429 log path (with and without quota headers)Testing
ruff format/ruff checkclean;make type-checkshows only the pre-existingboto3stub error in the AWS plugin.🤖 Generated with Claude Code