docs: adds docs for OTEL on OSS features list and examples - #3731
Conversation
📝 WalkthroughSummary by CodeRabbit
WalkthroughThis PR adds an OpenTelemetry feature page, registers it in docs navigation, and updates observability and provider docs to document that forwarded caller headers (x-bf-eh-* and allowlisted headers) are attached to ChangesOpenTelemetry Feature Documentation
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Confidence Score: 5/5Documentation-only change with no runtime logic; safe to merge. All four changed files are purely documentation. The factual claim about x-bf-dim-* values flowing through to OTel span attributes is corroborated by existing telemetry.mdx content. No broken links, no contradictions between the new pages, and the new features/otel entry is correctly wired into docs.json. No files require special attention. Important Files Changed
Reviews (3): Last reviewed commit: "docs: adds docs for OTEL on OSS features..." | Re-trigger Greptile |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
docs/providers/request-options.mdx (1)
698-715: ⚡ Quick winConvert this new example to required docs tab format.
Please present this added flow with
Web UI/API/config.jsontabs to match the MDX documentation standard.As per coding guidelines:
docs/**/*.mdx: Mintlify MDX documentation must have Web UI / API / config.json tabs; validate config.json examples against transports/config.schema.json.🤖 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 `@docs/providers/request-options.mdx` around lines 698 - 715, Convert the new "Example: forwarding a session ID" section into the MDX tabbed format required by docs: replace the standalone curl block and Result bullets with three tabs labeled "Web UI", "API", and "config.json"; put the current curl example under the "API" tab, add a short Web UI snippet showing how to set the `x-bf-eh-session-id` header via the UI form, and create a `config.json` example that shows the transport/header forwarding configuration for session-id (validate that the `config.json` content matches transports/config.schema.json). Ensure the OTel attribute description (`gen_ai.request.extra_header.session-id`) and the expected provider header receipt are preserved within the appropriate tabs.
🤖 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 `@docs/features/observability/otel.mdx`:
- Around line 667-672: The text currently refers to attributes being on the span
"llm.call" but earlier the doc uses request-type span names like "gen_ai.chat",
causing confusion; update this subsection to state that caller-supplied headers
are added to the request-type span (e.g., gen_ai.chat, gen_ai.call, etc.) rather
than a generic "llm.call", change the example to use one of the actual span
names used elsewhere (for instance: sending x-bf-eh-session-id produces
gen_ai.chat attribute gen_ai.request.extra_header.session-id = "sess-abc-123"),
and ensure all mentions of the attribute prefix
gen_ai.request.extra_header.<name> consistently reference those request-type
span names across the page.
In `@docs/features/otel.mdx`:
- Around line 81-87: The Setup section under the "## Setup" heading currently
only contains prose and a Card component; add the three required Mintlify MDX
tabs "Web UI", "API", and "config.json" wrapping the existing content and
corresponding examples (move the Card or duplicate content into the appropriate
tabs), ensure the config.json tab contains a full example that is validated
against transports/config.schema.json, and update any frontmatter/MDX tab
metadata so Mintlify renders the three tabs correctly.
---
Nitpick comments:
In `@docs/providers/request-options.mdx`:
- Around line 698-715: Convert the new "Example: forwarding a session ID"
section into the MDX tabbed format required by docs: replace the standalone curl
block and Result bullets with three tabs labeled "Web UI", "API", and
"config.json"; put the current curl example under the "API" tab, add a short Web
UI snippet showing how to set the `x-bf-eh-session-id` header via the UI form,
and create a `config.json` example that shows the transport/header forwarding
configuration for session-id (validate that the `config.json` content matches
transports/config.schema.json). Ensure the OTel attribute description
(`gen_ai.request.extra_header.session-id`) and the expected provider header
receipt are preserved within the appropriate tabs.
🪄 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: b3f4f616-dee1-4e1b-963b-b7a7d684248e
📒 Files selected for processing (4)
docs/docs.jsondocs/features/observability/otel.mdxdocs/features/otel.mdxdocs/providers/request-options.mdx
3ae04af to
62c69d8
Compare
b0ec1df to
0c85f0b
Compare
62c69d8 to
930e60e
Compare
0c85f0b to
bff5db0
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
docs/providers/request-options.mdx (1)
690-691: ⚡ Quick winConsider mentioning that sensitive headers are redacted in span attributes.
The statement "the same metadata you send to the provider is searchable" is accurate for most headers but omits that sensitive headers (e.g., authorization, cookie) are redacted in the span—Bifrost preserves the attribute key but sets the value to a redacted placeholder. Based on relevant code snippets from
core/bifrost.go, the implementation callsIsSensitiveHeaderand replaces values withRedactedAttrValuefor credential-bearing headers.Since the example uses
session-id(non-sensitive), it remains correct. However, adding a brief note about redaction would help users who forward auth-related headers understand what appears in their observability backend.Suggested addition
After line 691, consider adding:
When the OTel plugin is enabled, each forwarded header is also attached to the `llm.call` span as a `gen_ai.request.extra_header.<name>` attribute, so the same metadata you send to the provider is searchable in your observability backend without extra wiring. + +<Note> +Sensitive headers (e.g., `authorization`, `cookie`) are redacted in span attributes—the key is preserved but the value is replaced with a redacted placeholder to prevent credential leakage in observability systems. +</Note>🤖 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 `@docs/providers/request-options.mdx` around lines 690 - 691, Add a brief note in the docs clarifying that when OTel plugin attaches forwarded headers to the llm.call span as gen_ai.request.extra_header.<name>, sensitive headers are redacted: the implementation in core/bifrost.go checks IsSensitiveHeader and replaces credential-bearing values with the RedactedAttrValue placeholder, preserving the attribute key but not the raw secret value.
🤖 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 `@docs/providers/request-options.mdx`:
- Around line 690-691: Add a brief note in the docs clarifying that when OTel
plugin attaches forwarded headers to the llm.call span as
gen_ai.request.extra_header.<name>, sensitive headers are redacted: the
implementation in core/bifrost.go checks IsSensitiveHeader and replaces
credential-bearing values with the RedactedAttrValue placeholder, preserving the
attribute key but not the raw secret value.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e93685bc-3ffc-4b5d-a509-33fd6a0833f5
📒 Files selected for processing (4)
docs/docs.jsondocs/features/observability/otel.mdxdocs/features/otel.mdxdocs/providers/request-options.mdx
✅ Files skipped from review due to trivial changes (2)
- docs/features/observability/otel.mdx
- docs/features/otel.mdx
Merge activity
|
The base branch was changed.
## Summary Adds a new top-level OpenTelemetry feature page and documents that caller-supplied `x-bf-eh-*` headers (and direct-allowlist headers) are surfaced as `gen_ai.request.extra_header.<name>` span attributes on the `llm.call` span, enabling trace filtering and correlation by session, tenant, or correlation ID without additional instrumentation. ## Changes - Added `docs/features/otel.mdx` — a new top-level OTel overview page covering captured attributes, dynamic attribute injection via `x-bf-eh-*` headers, and links to the full integration guide and related references. - Registered `features/otel` in `docs/docs.json` so the new page appears in the navigation. - Updated `docs/features/observability/otel.mdx` to document the "Caller-Supplied Headers" behaviour under the captured data section, with an example showing `x-bf-eh-session-id` producing `gen_ai.request.extra_header.session-id` on the span. - Updated `docs/providers/request-options.mdx` to note that forwarded extra headers are also attached to the OTel span, and added a concrete `curl` example showing the dual effect on both the provider request and the `llm.call` span. ## Type of change - [ ] Bug fix - [ ] Feature - [ ] Refactor - [x] Documentation - [ ] Chore/CI ## Affected areas - [ ] Core (Go) - [ ] Transports (HTTP) - [ ] Providers/Integrations - [ ] Plugins - [ ] UI (React) - [x] Docs ## How to test Navigate to the docs site and verify: 1. The new **OpenTelemetry** page appears in the sidebar under Features. 2. The `features/otel` page renders correctly with the attribute table, dynamic injection section, and the `curl` example. 3. The `features/observability/otel` page shows the new **Caller-Supplied Headers** subsection under the captured data section. 4. The `providers/request-options` page shows the updated extra-headers description and the session-ID example with the expected OTel outcome. ## Breaking changes - [ ] Yes - [x] No ## Security considerations The documentation explicitly notes that the same security denylist and header filter configuration that gates provider forwarding also gates which headers appear as span attributes — no additional headers are exposed beyond what is already forwarded to the upstream provider. ## Checklist - [ ] I read `docs/contributing/README.md` and followed the guidelines - [ ] I added/updated tests where appropriate - [x] I updated documentation where needed - [ ] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable
## ✨ Features
- **Azure v1 API Migration** — Migrated Azure provider to the v1 API:
removed the `api-version` query parameter and the
`/openai/deployments/{model}/...` URL pattern in favor of
`/openai/v1/{operation}`; the `api_version` field has been dropped from
`AzureKeyConfig` (#3661, #3756)
- **EnvVar Support for OTEL & Prometheus Configs** — `CollectorURL`,
`MetricsEndpoint`, headers, push gateway URL, and basic auth credentials
can now be sourced from environment variables (e.g.,
`env.OTEL_COLLECTOR_URL`); added a new `ConfigMarshallerPlugin`
interface that lets plugins control storage/redaction round-trips
(#3651)
- **OTel Extra Header Forwarding** — `x-bf-eh-*` extra headers forwarded
to upstream providers are now also emitted on the request span under
`gen_ai.request.extra_header.*` for end-to-end tracing (#3730)
- **OTel Semantic Conventions** — Aligned OTel attribute keys with the
OpenTelemetry GenAI spec (canonical `gen_ai.*` and new `bifrost.*`
attributes); legacy attributes are retained in parallel to avoid
breaking existing dashboards (#3732)
- **VK Quota with Provider Configs** — `GetVirtualKeyQuotaByValue` and
the `getVirtualKeyQuota` HTTP response now include `provider_configs`
with their budgets and rate limits (#3721)
- **MCP Temp Token Non-Auth Toggle** — Added
`mcp_enable_temp_token_auth` client config flag to gate short-lived MCP
token minting for non-authenticated users (#3720)
- **Responses Stream in JSON Parser** — `jsonparser` plugin now handles
OpenAI Responses API streaming (`ResponsesStreamRequest`) in addition to
chat completions (#3749)
- **Session API Rework** — Logout now calls both the password-based
session logout and OAuth logout endpoints and resets all RTK Query cache
state (#3698)
## 🐞 Fixed
- **Streaming Latency for Observability** — Deferred root span
termination to the trace completer callback for streaming requests so
request latency is no longer inflated by header-flush time (#3762)
- **Stream Cancellation Race** — Set `BifrostContextKeyConnectionClosed`
before closing the stream and short-circuit `idleTimeoutReader.Read`
when the connection is already closed to avoid panics and hangs on
cancellation (#3733)
- **Bedrock Cache Points** — Strip cache points from Bedrock requests
for models that do not support prompt caching (e.g., GLM, Llama) to
avoid Converse API errors (#3754)
- **Bedrock Empty Text Blocks** — Skip empty/nil text blocks during
Bedrock response conversion to avoid invalid messages (#3747)
- **Bedrock Reasoning + Tools** — Preserve reasoning content blocks on
assistant turns that also contain tool calls in the Bedrock chat
converter (#3690)
- **Bedrock Search Content & Video** — Restored search content and video
parts that were being dropped from Bedrock-native passthrough requests
(#3729)
- **Structured Output Stop Reason** — Fixed an incorrect `tool_calls`
finish reason when structured output is combined with extended-thinking
tools (#3685)
- **Gemini Tool Schema Passthrough** — Forward full tool parameter
schemas via `parametersJsonSchema` instead of the lossy `parameters`
form; corrected tool response role to `user`; resolved structured output
+ tools conflict (#3761)
- **Anthropic Stop Reason & Tool Versions** — Normalized stop reason
mapping (`end_turn` to `stop`, `tool_use` to `tool_calls`, `max_tokens`
to `length`) and upgraded `text_editor_20250124`/`str_replace_editor` to
`text_editor_20250728` for computer-use tools (#3761)
- **Azure Endpoint Redaction** — Fixed a panic when
`AzureKeyConfig.Endpoint` is a literal value rather than an env
reference (#3761)
- **Auth Middleware Path Match** — Match temp-token auth middleware
whitelist against the request path only, not the full URI with query
parameters (#3737)
- **Governance Blocked Models UI** — Restored the missing Blocked Models
create/edit UI in the VK provider config sheet (#3750)
- **Logging Plugin Cleanup Drain** — Fixed a shutdown race where
`batchWriter` could drop in-flight log entries; `Cleanup` now drains
both the recovered batch and remaining queue within a 30-second budget
(#3717)
- **Model Rankings Empty Entries** — Excluded entries with empty `model`
values from model rankings matview queries so blank rows no longer
surface in the UI (#3758)
- **User Filter Duplicates** — Recreated `mv_filter_users` matview to
require non-empty `user_name`, eliminating duplicate filter dropdown
entries (#3764)
- **User Filter Display Name** — Use `user_name` instead of `user_id` as
the display label for users in logging filters (#3691)
- **Large Numeric ID Precision** — Preserve large numeric IDs in URL
search params by skipping JSON parsing for plain strings (#3692)
## 🔧 Refactors & Chores
- **Error Propagation for GetAvailable\* APIs** — `GetAvailable*`
methods on `LoggerPlugin`/`LogManager` now return wrapped errors instead
of silently logging and returning empty slices (#3759)
- **Governance Blocklist Matching** — Use `slices.Contains` for VK
blocked-model matching for clearer code with identical semantics (#3727)
- **Exported `ResolvePeriod`** — Renamed `resolvePeriod` to
`ResolvePeriod` so external packages can reuse the period parsing
(#3763)
## 📚 Docs
- **OTEL Env Var Documentation** — Documented `env.VAR_NAME` support for
`collector_url`, `metrics_endpoint`, and headers in OTEL/Prometheus
plugin docs
- **OTEL OSS Features & Examples** — Added OTEL documentation to the OSS
features list with usage examples (#3731)
- **Anthropic Auth Recommendation** — Recommend `ANTHROPIC_AUTH_TOKEN`
over `ANTHROPIC_CUSTOM_HEADERS` for Claude Code authentication (#3686)

Summary
Adds a new top-level OpenTelemetry feature page and documents that caller-supplied
x-bf-eh-*headers (and direct-allowlist headers) are surfaced asgen_ai.request.extra_header.<name>span attributes on thellm.callspan, enabling trace filtering and correlation by session, tenant, or correlation ID without additional instrumentation.Changes
docs/features/otel.mdx— a new top-level OTel overview page covering captured attributes, dynamic attribute injection viax-bf-eh-*headers, and links to the full integration guide and related references.features/otelindocs/docs.jsonso the new page appears in the navigation.docs/features/observability/otel.mdxto document the "Caller-Supplied Headers" behaviour under the captured data section, with an example showingx-bf-eh-session-idproducinggen_ai.request.extra_header.session-idon the span.docs/providers/request-options.mdxto note that forwarded extra headers are also attached to the OTel span, and added a concretecurlexample showing the dual effect on both the provider request and thellm.callspan.Type of change
Affected areas
How to test
Navigate to the docs site and verify:
features/otelpage renders correctly with the attribute table, dynamic injection section, and thecurlexample.features/observability/otelpage shows the new Caller-Supplied Headers subsection under the captured data section.providers/request-optionspage shows the updated extra-headers description and the session-ID example with the expected OTel outcome.Breaking changes
Security considerations
The documentation explicitly notes that the same security denylist and header filter configuration that gates provider forwarding also gates which headers appear as span attributes — no additional headers are exposed beyond what is already forwarded to the upstream provider.
Checklist
docs/contributing/README.mdand followed the guidelines