Skip to content

fix(responses): attribute per-PK telemetry tags on /v1/responses usage events - #646

Merged
jarvis9443 merged 1 commit into
mainfrom
fix/responses-provider-telemetry-867
Jun 25, 2026
Merged

fix(responses): attribute per-PK telemetry tags on /v1/responses usage events#646
jarvis9443 merged 1 commit into
mainfrom
fix/responses-provider-telemetry-867

Conversation

@jarvis9443

@jarvis9443 jarvis9443 commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Problem

Codex talks to the gateway over /v1/responses. After #613 made streaming /v1/responses calls log at all, their dashboard Logs rows were still missing the provider attribution that Claude-Code (/v1/messages) rows carry — 服务商类型 (provider_kind), 品牌服务商 (branded_provider), and PK 标签 (pk_label). claude-code logs show them; codex logs show none.

Root cause

The /v1/responses usage-event helpers (emit_usage_event / emit_zero_token_event) left the five per-PK telemetry attribution fields — provider_kind, provider_featured, branded_provider, pk_label, byo_label — at Default. They were wired for the chat surface only; the responses handler never resolved the target's ProviderKey telemetry_tags. These fields reach cp-api (and the dashboard's dpmgr_usage_events-backed Logs) via the usage-sink POST.

Fix

Resolve the winning target's ProviderKey telemetry_tags from the live snapshot — the same lookup /v1/messages and /v1/chat/completions already do — and populate the fields on every emit path:

  • the non-streaming handler emit (via a new provider_key_id on ResponseDispatchSuccess),
  • the verbatim-OpenAI and cross-provider streaming Drop guards,
  • the failed-attempt zero-token events.

The dispatch loop now records each attempt's provider_key_id on its AttemptRecord, so failed attempts attribute it too. A small provider_telemetry_tags helper shares the snapshot lookup between the two emit helpers; an empty/unknown provider_key_id (pre-dispatch error) yields all-empty tags → wire NULL, matching the chat/messages contract.

Behavior change

/v1/responses usage events now carry the upstream vendor + PK label, so Codex logs match Claude-Code logs. No wire/schema change — the cp-api columns already exist; they were simply never filled by this endpoint.

Tests

Integration tests (real router + OpenAI bridge + mock upstream + usage sink) assert the emitted UsageEvent carries the resolved PK's tags, on both the streaming path (Codex's always-streaming path) and the non-streaming path. Both fail before the fix (empty tags) and pass after.

E2E note: these attribution tags don't traverse the OTLP fan-out the standalone DP E2E harness observes (the OTLP encoder is an intentional allowlist, shared with chat/messages, that excludes them) — they only reach cp-api via the usage-sink POST, which the standalone harness doesn't receive. This matches how the original telemetry-attribution feature (chat/messages) was tested: Rust integration tests, no standalone E2E.

Fixes api7/AISIX-Cloud#867

Summary by CodeRabbit

  • Bug Fixes

    • Improved /v1/responses usage telemetry so events now include the correct provider attribution tags more consistently.
    • Fixed streaming and non-streaming response tracking to carry the resolved provider key through to final usage reporting.
    • Ensured zero-token failure events also report the expected provider labels and metadata.
  • Tests

    • Added coverage for /v1/responses to verify usage events include the correct provider kind, featured status, branding, and label fields.

…e events

Codex talks to the gateway over /v1/responses, and its dashboard Logs rows
were missing the provider attribution that Claude-Code (/v1/messages) rows
show: provider_kind, provider_featured, branded_provider, and pk_label.

The /v1/responses usage-event helpers left those five fields at default —
they were wired for the chat surface only. Resolve the winning target's
ProviderKey telemetry_tags from the snapshot (same lookup as /v1/messages
and /v1/chat/completions) and populate them on every emit path: the
non-streaming handler emit, the verbatim and cross-provider streaming Drop
guards, and the failed-attempt zero-token events. The dispatch loop now
records each attempt's provider_key_id so failed attempts attribute it too.

Integration tests cover the streaming (Codex's always-streaming path) and
non-streaming OpenAI paths, asserting the emitted UsageEvent carries the
resolved PK's tags; both fail before the fix and pass after.

Fixes api7/AISIX-Cloud#867
@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

/v1/responses now threads resolved ProviderKey IDs through dispatch, streaming, and non-streaming flows. Usage and zero-token events resolve ProviderKey telemetry tags for provider labels, and tests cover the updated attribution output.

Changes

Provider-key telemetry propagation

Layer / File(s) Summary
Dispatch state carries provider IDs
crates/aisix-proxy/src/responses.rs
ResponseDispatchSuccess and AttemptRecord.provider_key_id store the resolved ProviderKey UUID during dispatch handling.
OpenAI paths thread provider_key_id
crates/aisix-proxy/src/responses.rs
OpenAI buffered, streaming, and JSON branches include provider_key_id in success payloads and streaming closures.
Bridged paths thread provider_key_id
crates/aisix-proxy/src/responses.rs
Non-OpenAI dispatch and bridged streaming and non-streaming branches preserve provider_key_id for later telemetry emission.
Usage events resolve ProviderKey labels
crates/aisix-proxy/src/responses.rs
emit_usage_event and emit_zero_token_event look up ProviderKey telemetry tags, sanitize provider labels, and consume provider_key_id from success and failure call sites.
Tagged fixtures and log coverage
crates/aisix-proxy/src/responses.rs
New fixture data and /v1/responses tests assert provider attribution fields in streaming and non-streaming logs.

Sequence Diagram(s)

sequenceDiagram
  participant emit_usage_event
  participant emit_zero_token_event
  participant provider_telemetry_tags
  participant sanitize_tag
  participant UsageEvent

  emit_usage_event->>provider_telemetry_tags: provider_key_id
  provider_telemetry_tags-->>emit_usage_event: telemetry_tags
  emit_usage_event->>sanitize_tag: provider_kind / provider_featured / branded_provider / pk_label / byo_label
  sanitize_tag-->>emit_usage_event: sanitized labels
  emit_usage_event->>UsageEvent: set provider attribution fields

  emit_zero_token_event->>provider_telemetry_tags: provider_key_id
  provider_telemetry_tags-->>emit_zero_token_event: telemetry_tags
  emit_zero_token_event->>sanitize_tag: provider_kind / provider_featured / branded_provider / pk_label / byo_label
  sanitize_tag-->>emit_zero_token_event: sanitized labels
  emit_zero_token_event->>UsageEvent: set provider attribution fields
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
E2e Test Quality Review ⚠️ Warning telemetry tags are still resolved from state.snapshot.load() at emit time, so a snapshot refresh during a streamed request can misattribute logs; tests only cover the happy path. Capture TelemetryTags (or snapshot version + resolved tags) at dispatch/attempt creation and thread them into emitters; add regression tests for snapshot-refresh and failed-attempt attribution.
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately describes the main change: per-ProviderKey telemetry tagging for /v1/responses usage events.
Linked Issues check ✅ Passed The changes directly address #867 by populating missing provider attribution data in Codex /v1/responses logs.
Out of Scope Changes check ✅ Passed The PR stays focused on telemetry tag propagation and related tests, with no clear unrelated code changes.
Security Check ✅ Passed No security issues found: the patch only reads sanitized ProviderKey telemetry metadata and emits UsageEvents; no secret/header logging, storage, or auth changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 fix/responses-provider-telemetry-867

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

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
crates/aisix-proxy/src/responses.rs (1)

3327-3453: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for the other changed attribution paths.

These tests pin OpenAI success events, but the PR also changed bridged streaming and failed-attempt zero-token attribution. Add a tagged cross-provider case and a tagged upstream-failure case so Lines 1153 and 1757 are exercised too.

🤖 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 `@crates/aisix-proxy/src/responses.rs` around lines 3327 - 3453, The current
tests only cover OpenAI success attribution in the `/v1/responses` path, but
they miss the other changed telemetry branches. Add a tagged cross-provider test
for the bridged streaming path and a tagged upstream-failure test for zero-token
attribution, using the same `UsageSink`/`ProxyState` setup pattern so the
updated provider telemetry is exercised. Anchor the new coverage around the
`/v1/responses` handler flow and the existing response-event assertions so the
changed bridged streaming and failed-attempt paths are verified too.
🤖 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 `@crates/aisix-proxy/src/responses.rs`:
- Around line 1648-1649: The streaming usage emitters are re-resolving provider
tags at completion time via provider_telemetry_tags, which can misattribute logs
if the snapshot changes mid-flight. Update the dispatch path in responses.rs to
resolve and store the TelemetryTags together with provider_key_id when the
target is created, then thread those frozen tags through the usage/event
emitters instead of calling snapshot.load() again. Use the existing
target-dispatch flow around provider_key_id and TelemetryTags to locate the
change.

---

Nitpick comments:
In `@crates/aisix-proxy/src/responses.rs`:
- Around line 3327-3453: The current tests only cover OpenAI success attribution
in the `/v1/responses` path, but they miss the other changed telemetry branches.
Add a tagged cross-provider test for the bridged streaming path and a tagged
upstream-failure test for zero-token attribution, using the same
`UsageSink`/`ProxyState` setup pattern so the updated provider telemetry is
exercised. Anchor the new coverage around the `/v1/responses` handler flow and
the existing response-event assertions so the changed bridged streaming and
failed-attempt paths are verified too.
🪄 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: d9d17f9b-1fd2-4221-8c9b-ea571902a45d

📥 Commits

Reviewing files that changed from the base of the PR and between f8a33b3 and 32567ed.

📒 Files selected for processing (1)
  • crates/aisix-proxy/src/responses.rs

Comment thread crates/aisix-proxy/src/responses.rs
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