fix(passthrough): OTLP route/identity attribution, route on rejected events, header_key 401 names its header - #983
Conversation
…events, header_key 401 names its header A passthrough relay exported as a bare chat.completions span: the OTLP sink builds attributes by hand and had no passthrough branch, so the route name and the identity_header-extracted end-user identity never reached the trace backend (the serde-serializing sinks already carried both). Spans now export as 'passthrough <route>' with aisix.passthrough.route_name, and aisix.client_identity exports whenever set, unconditioned on the protocol. The error path lost the same attribution: emit_error_usage_event cannot set handler-specific fields, so a 401/403 event dropped the matched route. Split into build_error_usage_event + emit_prepared_usage_event (other callers untouched) and attribute the route in the passthrough arm. A header_key route's missing-key 401 said 'missing or malformed Authorization header' — the one header a BYO integrator must NOT touch, since it carries the caller's own upstream credential. New MissingRouteAuthHeader variant names the configured header instead.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (8)
Included review availability: 0 reviews are currently available. Based on recent review activity, included reviews refill at 1 per hour. 📝 WalkthroughWalkthroughPassthrough routes now enforce authentication-field combinations, report missing configured headers with specific 401 errors, attach route names to error events, and export passthrough route and client identity data in OTLP spans. ChangesPassthrough authentication and telemetry
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to The change improves passthrough attribution, rejected-request route reporting, header-specific 401 messages, and auth-schema validation without any identified current-head merge-blocking risk; it is merge-ready after normal checks and review. Possibly related PRs
Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
A companion outside its auth mode (auth_header_name off header_key, anonymous_key_id off anonymous) is never consulted at runtime — a row carrying one was accepted-and-ignored, the configuration shape that saves fine and never fires. Two coupling branches now reject the leftovers (handling the absent-auth_mode = gateway_key default); the CP enforces the identical rule on create and patch. source_cidrs stays mode-agnostic on purpose: it is an extra IP allowlist on every mode.
|
@coderabbitai review |
✅ Action performedReview finished.
|
Observability and error-surface follow-ups to #982, found by running the forward-proxy acceptance harness (a real TLS-terminating-device simulation relaying live traffic through a standalone gateway with an OTLP exporter attached):
OTLP spans now carry passthrough attribution. The usage event has carried
passthrough_route_name/client_identitysince feat(passthrough): explicit PassthroughRoute resources replace the implicit provider tunnel #982, but the OTLP sink builds span attributes by hand and had no passthrough branch — a relayed request exported as a barechat.completionsspan with the route and end-user identity recorded nowhere, andgen_ai.operation.name: chatmisclassified relays as model inference. Passthrough events now export aspassthrough <route>withaisix.passthrough.route_name;aisix.client_identityexports unconditionally when set, so any future handler that populates it inherits the attribute. The JSON-serializing sinks (Datadog, SLS, object store) already carried both fields and are unchanged.Rejected requests keep their route. The passthrough error path emitted usage events through the shared
emit_error_usage_event, which cannot set handler-specific fields — a 401/403/422 event lostpassthrough_route_nameeven though the route had matched. The helper is split intobuild_error_usage_event+emit_prepared_usage_event(the 11 other call sites are untouched), and the passthrough arm attributes the route before emitting.header_key401s name the right header. A missing gateway key on aheader_keyroute answered "missing or malformed Authorization header" — but on those routesAuthorizationdeliberately carries the caller's own upstream credential, so the message pointed at exactly the wrong header. NewMissingRouteAuthHeadervariant names the route's configured header.The strict schema rejects cross-mode auth companions.
auth_header_nameoutsideheader_keyandanonymous_key_idoutsideanonymouswere accepted-and-ignored; two new coupling branches reject them (covering the absent-auth_modedefault), with the CP enforcing the identical rule on its side.source_cidrsstays mode-agnostic — the gateway honors it as an extra IP allowlist on every mode.Tests: two OTLP sink unit tests, a coupling test for the cross-mode rejections (passthrough span shape + protocol-ungated identity), and the header_key e2e scenario now asserts the 401 names the configured header and not
Authorization(fails on the pre-fix message).Verified live on the acceptance harness: the relayed span exports
passthrough copilot-auxiliary+ both attributes, and the 401 namesx-aisix-api-key.Refs api7/AISIX-Cloud#1312.
Summary by CodeRabbit
New Features
Bug Fixes