Skip to content

feat: add separate headers support for traces and metrics in OTEL collector - #5940

Merged
akshaydeo merged 1 commit into
devfrom
08-07-feat_add_separate_headers_support_for_traces_and_metrics_in_otel_collector
Aug 10, 2026
Merged

feat: add separate headers support for traces and metrics in OTEL collector#5940
akshaydeo merged 1 commit into
devfrom
08-07-feat_add_separate_headers_support_for_traces_and_metrics_in_otel_collector

Conversation

@roroghost17

@roroghost17 roroghost17 commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds support for per-signal HTTP headers in OTel profiles, allowing separate headers to be sent exclusively to the trace endpoint or the metrics endpoint, in addition to the existing shared headers field. This is particularly useful when a metrics collector requires a signal-specific header (e.g. a Databricks table name) that should not be forwarded to the trace endpoint.

Changes

  • Added trace_headers and metrics_headers fields to the Profile struct and profileForStorage struct, alongside the existing headers field.
  • headers continues to apply to both endpoints. trace_headers and metrics_headers are overlaid on top of the common headers at build time, with per-signal keys winning on collision.
  • Introduced mergedResolvedHeaders to merge common and per-signal header maps and resolve env.VAR_NAME references without mutating the inputs.
  • Extracted redactHeaderMap to eliminate duplicated redaction logic and applied it to all three header maps in Redacted().
  • Updated the JSON schema (config.schema.json) with descriptions for all three header fields.
  • Updated the UI form to render separate HeadersTable inputs for common, trace-only, and metrics-only headers, each with descriptive labels and FormDescription text.
  • Updated the Zod schema and form serialization to include trace_headers and metrics_headers.

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (React)
  • Docs

How to test

# Core/Transports
go test ./plugins/otel/...

# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build

Configure an OTel profile with all three header fields:

{
  "headers": { "Authorization": "env.OTEL_TOKEN" },
  "trace_headers": { "X-Trace-Only": "trace-value" },
  "metrics_headers": { "X-Databricks-Table": "my_table" }
}

Verify that:

  • Trace requests include Authorization and X-Trace-Only but not X-Databricks-Table.
  • Metrics requests include Authorization and X-Databricks-Table but not X-Trace-Only.
  • env.OTEL_TOKEN is resolved from the environment on both endpoints.
  • Redacted config masks literal header values and preserves env. references across all three maps.

Breaking changes

  • Yes
  • No

Security considerations

All three header maps (headers, trace_headers, metrics_headers) are subject to the same redaction logic in Redacted(). Literal header values are masked and env. references are preserved as-is, consistent with prior behavior. No new secret storage paths are introduced.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added separate header configuration for OTEL trace and metrics endpoints.
    • Shared headers apply to both endpoints, while signal-specific headers override shared values.
    • Added dedicated trace and metrics header sections to observability profile forms.
    • Environment-based header values remain supported, with secret values protected during storage and display.
    • Headers for inactive signals no longer prevent profile initialization.

Walkthrough

OTEL profiles now support shared, trace-specific, and metrics-specific headers. The backend persists, redacts, resolves, and applies each map independently. The UI and configuration schemas expose the new fields with secret-variable support.

Changes

OTEL signal-specific headers

Layer / File(s) Summary
Header contracts and storage
plugins/otel/main.go, transports/config.schema.json, ui/lib/types/schemas.ts
Profiles and schemas define optional trace and metrics header maps. Storage persists them, and redaction masks literal values while preserving environment references.
Signal header resolution
plugins/otel/main.go, plugins/otel/profiles_test.go
Shared headers are merged with signal-specific headers. Signal-specific values override shared values. Environment references resolve without mutating inputs. Trace clients and metrics exporters receive their respective resolved maps. Tests cover storage, redaction, precedence, and inactive-signal errors.
Header configuration UI
ui/app/workspace/observability/fragments/otelFormFragment.tsx, ui/app/workspace/observability/views/plugins/otelView.tsx
The OTEL form adds secret-capable trace and metrics header tables. Save logic converts all header maps to backend-compatible string maps.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant OTEL Profile
  participant Header Resolver
  participant Trace Client
  participant Metrics Exporter
  OTEL Profile->>Header Resolver: resolve shared and trace headers
  Header Resolver->>Trace Client: provide resolved trace headers
  OTEL Profile->>Header Resolver: resolve shared and metrics headers
  Header Resolver->>Metrics Exporter: provide resolved metrics headers
Loading

Possibly related PRs

Suggested reviewers: akshaydeo, bearts

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly describes the primary change: adding separate trace and metrics headers for OTEL collectors.
Description check ✅ Passed The description covers the purpose, implementation, affected areas, testing steps, security impact, and breaking-change status.
✨ 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 08-07-feat_add_separate_headers_support_for_traces_and_metrics_in_otel_collector

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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)
plugins/otel/profiles_test.go (1)

531-538: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover trace-header redaction.

The test verifies literal-value masking only for MetricsHeaders. Add a literal TraceHeaders value and assert that Redacted() masks it. This detects a regression where trace headers bypass redactHeaderMap.

🤖 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 `@plugins/otel/profiles_test.go` around lines 531 - 538, Add a literal entry to
the test profile’s TraceHeaders alongside the existing MetricsHeaders fixture,
then extend the redacted profile assertions to verify that Redacted() masks the
trace-header value rather than preserving the literal. Keep the existing
environment-reference preservation and metrics-header checks unchanged.
🤖 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 `@plugins/otel/main.go`:
- Around line 557-563: Update the profile header resolution flow around
mergedResolvedHeaders so trace headers are resolved only when traces are enabled
and metrics headers only when metrics are enabled; preserve common headers and
enabled-signal merging, while ignoring unset environment references in inactive
signal maps. Add trace-only and metrics-only tests covering an unset environment
reference in the disabled signal’s headers.

---

Nitpick comments:
In `@plugins/otel/profiles_test.go`:
- Around line 531-538: Add a literal entry to the test profile’s TraceHeaders
alongside the existing MetricsHeaders fixture, then extend the redacted profile
assertions to verify that Redacted() masks the trace-header value rather than
preserving the literal. Keep the existing environment-reference preservation and
metrics-header checks unchanged.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 79a11d6b-e1ff-4424-9fbb-b8f164412bd0

📥 Commits

Reviewing files that changed from the base of the PR and between a8828bc and e48d172.

📒 Files selected for processing (6)
  • plugins/otel/main.go
  • plugins/otel/profiles_test.go
  • transports/config.schema.json
  • ui/app/workspace/observability/fragments/otelFormFragment.tsx
  • ui/app/workspace/observability/views/plugins/otelView.tsx
  • ui/lib/types/schemas.ts

Comment thread plugins/otel/main.go Outdated
@roroghost17
roroghost17 force-pushed the 08-07-feat_add_separate_headers_support_for_traces_and_metrics_in_otel_collector branch from e48d172 to a6883e2 Compare August 7, 2026 09:49
@roroghost17
roroghost17 force-pushed the 08-06-feat_add_support_for_separate_metrics_tab_independent_of_traces_for_otel branch from a8828bc to ebbecb6 Compare August 7, 2026 09:49
@CLAassistant

CLAassistant commented Aug 7, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 7, 2026

akshaydeo commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Merge activity

  • Aug 10, 3:13 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Aug 10, 3:18 PM UTC: Graphite rebased this pull request as part of a merge.
  • Aug 10, 3:19 PM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo
akshaydeo changed the base branch from 08-06-feat_add_support_for_separate_metrics_tab_independent_of_traces_for_otel to graphite-base/5940 August 10, 2026 15:16
@akshaydeo
akshaydeo changed the base branch from graphite-base/5940 to dev August 10, 2026 15:16
@akshaydeo
akshaydeo dismissed coderabbitai[bot]’s stale review August 10, 2026 15:16

The base branch was changed.

@akshaydeo
akshaydeo requested a review from a team as a code owner August 10, 2026 15:16
@akshaydeo
akshaydeo force-pushed the 08-07-feat_add_separate_headers_support_for_traces_and_metrics_in_otel_collector branch from a6883e2 to 8a5f90f Compare August 10, 2026 15:18
@akshaydeo
akshaydeo merged commit a13e24c into dev Aug 10, 2026
12 of 14 checks passed
@akshaydeo
akshaydeo deleted the 08-07-feat_add_separate_headers_support_for_traces_and_metrics_in_otel_collector branch August 10, 2026 15:19
akshaydeo pushed a commit that referenced this pull request Aug 10, 2026
…lector (#5940)

## Summary

Adds support for per-signal HTTP headers in OTel profiles, allowing separate headers to be sent exclusively to the trace endpoint or the metrics endpoint, in addition to the existing shared `headers` field. This is particularly useful when a metrics collector requires a signal-specific header (e.g. a Databricks table name) that should not be forwarded to the trace endpoint.

## Changes

- Added `trace_headers` and `metrics_headers` fields to the `Profile` struct and `profileForStorage` struct, alongside the existing `headers` field.
- `headers` continues to apply to both endpoints. `trace_headers` and `metrics_headers` are overlaid on top of the common headers at build time, with per-signal keys winning on collision.
- Introduced `mergedResolvedHeaders` to merge common and per-signal header maps and resolve `env.VAR_NAME` references without mutating the inputs.
- Extracted `redactHeaderMap` to eliminate duplicated redaction logic and applied it to all three header maps in `Redacted()`.
- Updated the JSON schema (`config.schema.json`) with descriptions for all three header fields.
- Updated the UI form to render separate `HeadersTable` inputs for common, trace-only, and metrics-only headers, each with descriptive labels and `FormDescription` text.
- Updated the Zod schema and form serialization to include `trace_headers` and `metrics_headers`.

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [x] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [x] Plugins
- [x] UI (React)
- [ ] Docs

## How to test

```sh
# Core/Transports
go test ./plugins/otel/...

# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

Configure an OTel profile with all three header fields:

```json
{
  "headers": { "Authorization": "env.OTEL_TOKEN" },
  "trace_headers": { "X-Trace-Only": "trace-value" },
  "metrics_headers": { "X-Databricks-Table": "my_table" }
}
```

Verify that:
- Trace requests include `Authorization` and `X-Trace-Only` but not `X-Databricks-Table`.
- Metrics requests include `Authorization` and `X-Databricks-Table` but not `X-Trace-Only`.
- `env.OTEL_TOKEN` is resolved from the environment on both endpoints.
- Redacted config masks literal header values and preserves `env.` references across all three maps.

## Breaking changes

- [ ] Yes
- [x] No

## Security considerations

All three header maps (`headers`, `trace_headers`, `metrics_headers`) are subject to the same redaction logic in `Redacted()`. Literal header values are masked and `env.` references are preserved as-is, consistent with prior behavior. No new secret storage paths are introduced.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
akshaydeo pushed a commit that referenced this pull request Aug 13, 2026
…lector (#5940)

## Summary

Adds support for per-signal HTTP headers in OTel profiles, allowing separate headers to be sent exclusively to the trace endpoint or the metrics endpoint, in addition to the existing shared `headers` field. This is particularly useful when a metrics collector requires a signal-specific header (e.g. a Databricks table name) that should not be forwarded to the trace endpoint.

## Changes

- Added `trace_headers` and `metrics_headers` fields to the `Profile` struct and `profileForStorage` struct, alongside the existing `headers` field.
- `headers` continues to apply to both endpoints. `trace_headers` and `metrics_headers` are overlaid on top of the common headers at build time, with per-signal keys winning on collision.
- Introduced `mergedResolvedHeaders` to merge common and per-signal header maps and resolve `env.VAR_NAME` references without mutating the inputs.
- Extracted `redactHeaderMap` to eliminate duplicated redaction logic and applied it to all three header maps in `Redacted()`.
- Updated the JSON schema (`config.schema.json`) with descriptions for all three header fields.
- Updated the UI form to render separate `HeadersTable` inputs for common, trace-only, and metrics-only headers, each with descriptive labels and `FormDescription` text.
- Updated the Zod schema and form serialization to include `trace_headers` and `metrics_headers`.

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [x] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [x] Plugins
- [x] UI (React)
- [ ] Docs

## How to test

```sh
# Core/Transports
go test ./plugins/otel/...

# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

Configure an OTel profile with all three header fields:

```json
{
  "headers": { "Authorization": "env.OTEL_TOKEN" },
  "trace_headers": { "X-Trace-Only": "trace-value" },
  "metrics_headers": { "X-Databricks-Table": "my_table" }
}
```

Verify that:
- Trace requests include `Authorization` and `X-Trace-Only` but not `X-Databricks-Table`.
- Metrics requests include `Authorization` and `X-Databricks-Table` but not `X-Trace-Only`.
- `env.OTEL_TOKEN` is resolved from the environment on both endpoints.
- Redacted config masks literal header values and preserves `env.` references across all three maps.

## Breaking changes

- [ ] Yes
- [x] No

## Security considerations

All three header maps (`headers`, `trace_headers`, `metrics_headers`) are subject to the same redaction logic in `Redacted()`. Literal header values are masked and `env.` references are preserved as-is, consistent with prior behavior. No new secret storage paths are introduced.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
akshaydeo pushed a commit that referenced this pull request Aug 13, 2026
…lector (#5940)

## Summary

Adds support for per-signal HTTP headers in OTel profiles, allowing separate headers to be sent exclusively to the trace endpoint or the metrics endpoint, in addition to the existing shared `headers` field. This is particularly useful when a metrics collector requires a signal-specific header (e.g. a Databricks table name) that should not be forwarded to the trace endpoint.

## Changes

- Added `trace_headers` and `metrics_headers` fields to the `Profile` struct and `profileForStorage` struct, alongside the existing `headers` field.
- `headers` continues to apply to both endpoints. `trace_headers` and `metrics_headers` are overlaid on top of the common headers at build time, with per-signal keys winning on collision.
- Introduced `mergedResolvedHeaders` to merge common and per-signal header maps and resolve `env.VAR_NAME` references without mutating the inputs.
- Extracted `redactHeaderMap` to eliminate duplicated redaction logic and applied it to all three header maps in `Redacted()`.
- Updated the JSON schema (`config.schema.json`) with descriptions for all three header fields.
- Updated the UI form to render separate `HeadersTable` inputs for common, trace-only, and metrics-only headers, each with descriptive labels and `FormDescription` text.
- Updated the Zod schema and form serialization to include `trace_headers` and `metrics_headers`.

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [x] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [x] Plugins
- [x] UI (React)
- [ ] Docs

## How to test

```sh
# Core/Transports
go test ./plugins/otel/...

# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

Configure an OTel profile with all three header fields:

```json
{
  "headers": { "Authorization": "env.OTEL_TOKEN" },
  "trace_headers": { "X-Trace-Only": "trace-value" },
  "metrics_headers": { "X-Databricks-Table": "my_table" }
}
```

Verify that:
- Trace requests include `Authorization` and `X-Trace-Only` but not `X-Databricks-Table`.
- Metrics requests include `Authorization` and `X-Databricks-Table` but not `X-Trace-Only`.
- `env.OTEL_TOKEN` is resolved from the environment on both endpoints.
- Redacted config masks literal header values and preserves `env.` references across all three maps.

## Breaking changes

- [ ] Yes
- [x] No

## Security considerations

All three header maps (`headers`, `trace_headers`, `metrics_headers`) are subject to the same redaction logic in `Redacted()`. Literal header values are masked and `env.` references are preserved as-is, consistent with prior behavior. No new secret storage paths are introduced.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
@akshaydeo akshaydeo mentioned this pull request Aug 13, 2026
akshaydeo added a commit that referenced this pull request Aug 13, 2026
## ✨ Features

- **MCP Per-User OAuth** - MCP clients can hold per-user OAuth
credentials and per-user headers, configurable from `config.json` as
well as the UI, with a documented shared vs per-identity token lookup
contract and VK/Users filters on the OAuth Grants and MCP Auth Sessions
sidebars
- **Token Exchange IDP Credentials** - New `use_idp_credentials` on
`token_exchange` reuses SSO login app credentials for providers that
require it, such as Microsoft Entra ID; `client_id` becomes optional
when it is set (#6068, #6069)
- **Bedrock VPC Endpoints** - AWS Bedrock keys can target VPC endpoints
(#6064)
- **Per-Request Flat-Fee Pricing** - New `cost_per_request` field flows
through datasheet sync, the cost engine, custom overrides and the UI
override form (#6079)
- **Pricing Overrides in the Model Catalog** - `/api/models/details`
exposes resolved pricing overrides, and catalog rows resolve overrides
server-side (#6055, #6056)
- **MCP Tool Discovery Persistence** - Discovered MCP tools persist and
resync uniformly across all client types through a hash-gated core
callback, surviving restarts and propagating across a cluster
- **W3C Trace ID Propagation** - Requests carry a W3C trace ID on the
context (#5945)
- **Cancellable Log Cost Recalculation** - Log cost recalculation tasks
can be cancelled from the backend (#5801)
- **Separate OTEL Metrics Pipeline** - The OTEL collector supports a
metrics tab independent of traces, plus separate headers for traces and
metrics (#5939, #5940)
- **Roots-Only Log Filter** - New `roots_only` filter collapses fallback
chains into their root entry with child aggregates (#5737)
- **MCP Log Redaction and Plugin Logs** - MCP tool logs carry redaction
mappings and plugin logs (#5744, #5746)
- **User Agent and App Attribution in Logs** - Logs and MCP tool logs
record user agent, app, source, decision, app key and device ID
- **S3 Log Export Metadata** - Additional metadata is written alongside
S3 log exports (#6070)
- **Matview Maintenance Off Switch** - `matview_refresh_interval`
accepts `"off"` to disable logstore matview maintenance entirely (thanks
[@jeremym-tanium](https://github.com/jeremym-tanium)!) (#5693)
- **Video Request Info in Logs UI** - Video requests surface their
details in the logs UI (#5946)
- **Shell Rewriter Hook** - The UI handler exposes a `ShellRewriter`
hook for pre-hydration HTML rewriting (#5807)
- **Auth Skip Path** - Adds a context path letting trusted internal
callers bypass auth resolution

## 🐞 Fixed

- **Path Normalization Auth Bypass** - Fixed a path normalization flaw
that allowed auth to be bypassed (#5763)
- **Minimal Reasoning Effort on GPT-5 Models** - `reasoning_effort:
"minimal"` is preserved for GPT-5-family OpenAI models instead of being
downgraded to `low` (thanks [@jitokim](https://github.com/jitokim)!)
(#6046)
- **Gemini Truncated Response Finish Reason** - Truncated Gemini
responses report `MAX_TOKENS` instead of `OTHER` (thanks
[@AdityaPainuli](https://github.com/AdityaPainuli)!) (#5979)
- **Null Tool-Call Function Name on Streaming** - Streaming continuation
deltas no longer materialize an absent tool-call function name as `null`
(thanks [@AdityaPainuli](https://github.com/AdityaPainuli)!) (#5966)
- **Bedrock Document Uploads** - Fixed Bedrock file handling in
inference so office and PDF documents sent as OpenAI `type: "file"` are
accepted (#5947)
- **xAI Usage Cost** - Fixed USD cost ticks for xAI usage (#5950)
- **Anthropic Encrypted Reasoning** - Added an Anthropic error branch
when stripping encrypted reasoning content
- **MCP Reconnect and Lock Ordering** - Broke a lock-order inversion in
`ConnectionCheckerManager`, rebuilt ephemeral clients across the whole
connect+init retry, preserved last-known tool maps across close-first
reconnects, bound connect attempts to entry identity, deduped background
reconnects and gated SSE `OnConnectionLost` on connection identity
- **MCP OAuth Session Correctness** - Restricted `Reauthorize` to shared
OAuth clients, rejected inactive tokens in `ValidateToken`, made the
OAuth flow claim atomic against concurrent reauth, stopped dropping
stored scopes on decode failure, and closed a verify-headers
double-submit race that also dropped TLS, timeout and per-user-header
fields
- **Session Stickiness Reconciliation** - `needs_session_stickiness` is
pinned across `config.json` reconciliation, so an unrelated file edit
can no longer silently revert a client to per-call
- **Credential Cache Cancellation** - `headerCredentialCache.Fill` and
`userTokenCache.Fill` propagate context so a cancelled request unblocks
instead of waiting on an unrelated leader; LRU entries carry a version
so a rejected stale `Get` cannot evict a concurrently-updated value
- **Governance List-Models Call** - Budgets and rate limits no longer
trigger a list-models call (#6051)
- **Realtime Response Create Input** - Guarded `response.create` input
(#6050)
- **HTTP Server Timeouts** - Configured bounded `http.Server` timeouts
and a request-body limit
- **MCP Client State Badges** - State badges render with spaces instead
of underscores, and the state filter bucket was renamed from
`disconnected` to `unstable`
- **Entra OBO Scope** - `offline_access` is combined with
`<audience>/.default` for Entra OBO instead of replacing it (#6078)

## 🔧 Maintenance

- **Governance Route Families** - Editions can override governance route
families (#5839)
- **Dependency Upgrades** - Dependabot updates across all modules, plus
module path fixes (#6040, #5864)
- **Documentation** - config.schema.json doc fixes and Datadog env var
reference fixes in the helm chart docs (#5938, #6019)

## 🗄️ Database Migrations

**configstore:**

- **add_mcp_client_pending_oauth_config_json_column** - Adds
`pending_oauth_config_json` to `config_mcp_clients`. Reversible: drops
the added column.
- **merge_oauth_token_tables** - Consolidates `oauth_tokens` and
`oauth_user_tokens` into `mcp_oauth_tokens`. **Non-reversible**:
rollback deliberately leaves `mcp_oauth_tokens` in place, because every
OAuth read and write targets it from this migration onward and dropping
it would destroy any token created or refreshed since, forcing every
holder to re-authorize.
- **create_mcp_oauth_flows_table** - Creates `mcp_oauth_flows` to track
in-flight OAuth flows. Reversible: drops the new table.
- **drop_oauth_config_pkce_columns** - Drops CSRF state, PKCE verifier
and `expires_at` from the OAuth config table now that they live on
`mcp_oauth_flows`. **Non-reversible**: forward-only, the dropped values
were per-flow ephemeral and re-adding empty columns would restore
nothing.
- **drop_oauth_config_token_id_column** - Drops `token_id`.
**Non-reversible**: forward-only, it was a pure FK shortcut now
reachable via `(oauth_config_id, auth_mode)`.
- **add_mcp_admin_auth_mode_indexes** - Adds admin partial unique
indexes on `mcp_oauth_tokens` and `mcp_per_user_header_credentials`.
Reversible: drops both indexes.
- **add_mcp_client_token_exchange_json_column** - Adds
`token_exchange_json` to `config_mcp_clients`. Reversible: drops the
added column.
- **add_needs_session_stickiness_column** - Adds
`needs_session_stickiness` to `config_mcp_clients`. Reversible: drops
the added column.
- **add_bedrock_endpoints_columns** - Adds Bedrock VPC endpoint columns
to the keys table. Reversible: drops the added columns.
- **add_cost_per_request_pricing_column** - Adds `cost_per_request` to
model pricing. Reversible: drops the added column.

**logstore:**

- **logs_add_guardrail_debug_column** - Adds `guardrail_debug` to logs.
Reversible: drops the added column.
- **mcp_tool_logs_add_redaction_mapping_column** - Adds the redaction
mapping column to MCP tool logs. **Non-reversible**: rollback is a no-op
because dropping the column would permanently destroy reveal data for
already-redacted MCP logs.
- **logs_add_user_agent_column** - Adds user agent and app columns,
their indexes, and a `UserAgentMapping` table. Reversible: drops the
indexes and the mapping table.
- **mcp_tool_logs_add_user_agent_column** - Adds user agent and app
columns plus indexes to MCP tool logs. Reversible: drops both indexes
and the `app` column.
- **mcp_tool_logs_add_endpoint_columns** - Adds `source`, `decision`,
`app_key` and `device_id` to MCP tool logs. Reversible: drops all four
columns.
- **mcp_tool_logs_add_plugin_logs_column** - Adds `plugin_logs` to MCP
tool logs. Reversible: drops the added column.
- **logs_recreate_matviews_with_user_agent_column** and
**logs_recreate_matviews_with_app_column** - Recreate the log
materialized views to include the new columns. Rollback is a no-op
because `ensureMatViews` recreates them on next startup.

<Warning>
**High-throughput deployments: run the logstore migrations during a
low-activity window.**

Every logstore migration above alters `logs` or `mcp_tool_logs`, the two
highest-insert tables in Bifrost, and several also build indexes on
them. On a busy instance the index builds hold locks that block
concurrent log inserts for the duration of the build, and the matview
recreations rebuild against the full table. Schedule the upgrade for a
low-traffic period, or expect elevated log-write latency and possible
request-path backpressure while the migrations run.
</Warning>

<Warning>
`merge_oauth_token_tables`, `drop_oauth_config_pkce_columns` and
`drop_oauth_config_token_id_column` transform or remove existing OAuth
state and cannot be rolled back. Take a database backup before
upgrading, and do not roll the binary back past this release once the
migration has run.
</Warning>

## 🐙 Closed GitHub Issues

- [#123](#123) - Files API
Support
- [#5472](#5472) - [Bug]:
Bedrock rejects office/PDF document uploads via OpenAI `type:"file"` -
"The PDF specified was not valid"
- [#5900](#5900) - [Bug]:
Streaming continuation chunks materialize omitted tool-call metadata as
null
- [#5978](#5978) - [Bug]:
Gemini egress reports truncated responses as FinishReason OTHER,
IncompleteDetails switch matches a string that never occurs
- [#6044](#6044) - [Bug]:
normalizeOpenAIReasoningEffort maps 'minimal' to 'low' for ALL OpenAI
models, even ones that natively support 'minimal'
akshaydeo pushed a commit that referenced this pull request Aug 14, 2026
…lector (#5940)

## Summary

Adds support for per-signal HTTP headers in OTel profiles, allowing separate headers to be sent exclusively to the trace endpoint or the metrics endpoint, in addition to the existing shared `headers` field. This is particularly useful when a metrics collector requires a signal-specific header (e.g. a Databricks table name) that should not be forwarded to the trace endpoint.

## Changes

- Added `trace_headers` and `metrics_headers` fields to the `Profile` struct and `profileForStorage` struct, alongside the existing `headers` field.
- `headers` continues to apply to both endpoints. `trace_headers` and `metrics_headers` are overlaid on top of the common headers at build time, with per-signal keys winning on collision.
- Introduced `mergedResolvedHeaders` to merge common and per-signal header maps and resolve `env.VAR_NAME` references without mutating the inputs.
- Extracted `redactHeaderMap` to eliminate duplicated redaction logic and applied it to all three header maps in `Redacted()`.
- Updated the JSON schema (`config.schema.json`) with descriptions for all three header fields.
- Updated the UI form to render separate `HeadersTable` inputs for common, trace-only, and metrics-only headers, each with descriptive labels and `FormDescription` text.
- Updated the Zod schema and form serialization to include `trace_headers` and `metrics_headers`.

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [x] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [x] Plugins
- [x] UI (React)
- [ ] Docs

## How to test

```sh
# Core/Transports
go test ./plugins/otel/...

# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

Configure an OTel profile with all three header fields:

```json
{
  "headers": { "Authorization": "env.OTEL_TOKEN" },
  "trace_headers": { "X-Trace-Only": "trace-value" },
  "metrics_headers": { "X-Databricks-Table": "my_table" }
}
```

Verify that:
- Trace requests include `Authorization` and `X-Trace-Only` but not `X-Databricks-Table`.
- Metrics requests include `Authorization` and `X-Databricks-Table` but not `X-Trace-Only`.
- `env.OTEL_TOKEN` is resolved from the environment on both endpoints.
- Redacted config masks literal header values and preserves `env.` references across all three maps.

## Breaking changes

- [ ] Yes
- [x] No

## Security considerations

All three header maps (`headers`, `trace_headers`, `metrics_headers`) are subject to the same redaction logic in `Redacted()`. Literal header values are masked and `env.` references are preserved as-is, consistent with prior behavior. No new secret storage paths are introduced.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
akshaydeo pushed a commit that referenced this pull request Aug 19, 2026
…lector (#5940)

## Summary

Adds support for per-signal HTTP headers in OTel profiles, allowing separate headers to be sent exclusively to the trace endpoint or the metrics endpoint, in addition to the existing shared `headers` field. This is particularly useful when a metrics collector requires a signal-specific header (e.g. a Databricks table name) that should not be forwarded to the trace endpoint.

## Changes

- Added `trace_headers` and `metrics_headers` fields to the `Profile` struct and `profileForStorage` struct, alongside the existing `headers` field.
- `headers` continues to apply to both endpoints. `trace_headers` and `metrics_headers` are overlaid on top of the common headers at build time, with per-signal keys winning on collision.
- Introduced `mergedResolvedHeaders` to merge common and per-signal header maps and resolve `env.VAR_NAME` references without mutating the inputs.
- Extracted `redactHeaderMap` to eliminate duplicated redaction logic and applied it to all three header maps in `Redacted()`.
- Updated the JSON schema (`config.schema.json`) with descriptions for all three header fields.
- Updated the UI form to render separate `HeadersTable` inputs for common, trace-only, and metrics-only headers, each with descriptive labels and `FormDescription` text.
- Updated the Zod schema and form serialization to include `trace_headers` and `metrics_headers`.

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [x] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [x] Plugins
- [x] UI (React)
- [ ] Docs

## How to test

```sh
# Core/Transports
go test ./plugins/otel/...

# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

Configure an OTel profile with all three header fields:

```json
{
  "headers": { "Authorization": "env.OTEL_TOKEN" },
  "trace_headers": { "X-Trace-Only": "trace-value" },
  "metrics_headers": { "X-Databricks-Table": "my_table" }
}
```

Verify that:
- Trace requests include `Authorization` and `X-Trace-Only` but not `X-Databricks-Table`.
- Metrics requests include `Authorization` and `X-Databricks-Table` but not `X-Trace-Only`.
- `env.OTEL_TOKEN` is resolved from the environment on both endpoints.
- Redacted config masks literal header values and preserves `env.` references across all three maps.

## Breaking changes

- [ ] Yes
- [x] No

## Security considerations

All three header maps (`headers`, `trace_headers`, `metrics_headers`) are subject to the same redaction logic in `Redacted()`. Literal header values are masked and `env.` references are preserved as-is, consistent with prior behavior. No new secret storage paths are introduced.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
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.

3 participants