feat: adds support for custom selection of plugins for otel trace span exports - #3382
Conversation
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
|
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 (11)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (10)
📝 WalkthroughSummary by CodeRabbit
WalkthroughThis PR adds configurable filtering of OpenTelemetry plugin hook spans. Users can exclude or include specific plugins via a ChangesOTEL Plugin Span Filtering
Sequence Diagram(s)sequenceDiagram
participant Client
participant PluginsHandler
participant ConfigStore
participant PluginLoader
Client->>PluginsHandler: PUT /api/plugins/{name} (config)
PluginsHandler->>ConfigStore: GetPlugin(name)
PluginsHandler->>ConfigStore: UpdatePlugin(mergedConfig)
PluginsHandler->>PluginLoader: ReloadPlugin(name, mergedConfig)
PluginsHandler->>Client: 200 OK
sequenceDiagram
participant convertTrace as convertTraceToResourceSpan
participant buildReparent as buildReparentMap
participant shouldExport as shouldExportSpan
participant exporter as OTELExporter
convertTrace->>buildReparent: compute reparent map from trace spans
loop each span
convertTrace->>shouldExport: shouldExportSpan(span)
alt filtered
convertTrace->>exporter: skip span
else exported
convertTrace->>buildReparent: lookup parent remap
convertTrace->>exporter: emit span (ParentSpanId rewritten if mapped)
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 golangci-lint (2.12.2)level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies" Comment |
This stack of pull requests is managed by Graphite. Learn more about stacking. |
🧪 Test Suite AvailableThis PR can be tested by a repository admin. |
Confidence Score: 5/5The core filtering and reparenting logic is correct and well-tested; the config-merge fix prevents fields from being silently wiped on save. The filtering, reparenting, and config-merge paths are all well-covered by new tests and the logic is sound. The two findings are minor: a stale struct comment and the UI always saving in pluginTracingSheet.tsx (mode conversion on save) and main.go (stale comment on PluginSpanFilter field). Important Files Changed
Reviews (10): Last reviewed commit: "feat: adds support for custom selection ..." | Re-trigger Greptile |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
transports/config.schema.json (1)
1167-1186: ⚡ Quick winDeduplicate
plugin_span_filterschema to prevent drift.The same shape is defined twice. Consider defining a single
$defsentry (e.g.,$defs.plugin_span_filter) and referencing it from both top-levelotel_plugin_span_filterandplugins[].config.plugin_span_filter.Also applies to: 1630-1645
🤖 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 `@transports/config.schema.json` around lines 1167 - 1186, The otel_plugin_span_filter schema is duplicated; extract its object shape into a single reusable definition (e.g., $defs.plugin_span_filter) preserving "mode", "plugins", "required", and "additionalProperties": false, then replace the inline otel_plugin_span_filter and the plugins[].config.plugin_span_filter entries with $ref references to that $defs entry (use $ref: "#/$defs/plugin_span_filter") so both locations share the exact same schema and prevent drift.
🤖 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`:
- Line 132: The Init function currently accepts and stores the resolved
PluginSpanFilter without validating its mode; add validation logic to verify
pluginSpanFilter.mode is a recognized value before assigning it (e.g., check
against allowed modes like "include"/"exclude" or an enum), and return an error
if the mode is invalid so operator mistakes don't silently disable filtering;
update the same validation where PluginSpanFilter is accepted/assigned elsewhere
in the file (the same pattern around the other PluginSpanFilter assignment code)
and reference the PluginSpanFilter type and Init function when implementing the
check.
In `@transports/bifrost-http/handlers/config.go`:
- Around line 194-199: The code currently swallows json.Unmarshal errors for
h.store.OtelPluginSpanFilter and drops the field; update the block so that if
json.Unmarshal returns an error you log a clear diagnostic (include the error
and the raw bytes/string from h.store.OtelPluginSpanFilter using the service's
logger, e.g. h.logger or equivalent) and preserve the raw value in the output
map (e.g. set mapConfig["otel_plugin_span_filter_raw"] =
string(h.store.OtelPluginSpanFilter)) so bad persisted data can be inspected;
only set mapConfig["otel_plugin_span_filter"] when unmarshalling succeeds as it
does now.
---
Nitpick comments:
In `@transports/config.schema.json`:
- Around line 1167-1186: The otel_plugin_span_filter schema is duplicated;
extract its object shape into a single reusable definition (e.g.,
$defs.plugin_span_filter) preserving "mode", "plugins", "required", and
"additionalProperties": false, then replace the inline otel_plugin_span_filter
and the plugins[].config.plugin_span_filter entries with $ref references to that
$defs entry (use $ref: "#/$defs/plugin_span_filter") so both locations share the
exact same schema and prevent drift.
🪄 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: 81113209-eebc-447a-8e17-10386412ee6a
📒 Files selected for processing (16)
docs/deployment-guides/config-json/plugins.mdxdocs/features/observability/otel.mdxplugins/otel/converter.goplugins/otel/converter_test.goplugins/otel/filter_test.goplugins/otel/main.gotransports/bifrost-http/handlers/config.gotransports/bifrost-http/handlers/plugins.gotransports/bifrost-http/handlers/plugins_test.gotransports/bifrost-http/lib/config.gotransports/bifrost-http/lib/config_test.gotransports/bifrost-http/server/plugins.gotransports/config.schema.jsonui/app/workspace/plugins/page.tsxui/app/workspace/plugins/sheets/pluginTracingSheet.tsxui/lib/types/config.ts
👮 Files not reviewed due to content moderation or server errors (4)
- plugins/otel/converter_test.go
- transports/bifrost-http/handlers/plugins_test.go
- transports/bifrost-http/lib/config.go
- ui/app/workspace/plugins/sheets/pluginTracingSheet.tsx
79e9a71 to
b2159f9
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 153-160: ValidateConfig should reject invalid plugin span filter
modes early: add the same validation logic present in Init to ValidateConfig to
check config.PluginSpanFilter != nil and ensure config.PluginSpanFilter.Mode is
either PluginSpanFilterModeInclude or PluginSpanFilterModeExclude; if not,
return a formatted error (matching the Init message) referencing
PluginSpanFilterModeInclude and PluginSpanFilterModeExclude so invalid mode
strings fail config/API validation instead of only during Init.
🪄 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: e1756dfe-d6ec-4c5b-ac4e-d8010cf57bd1
📒 Files selected for processing (16)
docs/deployment-guides/config-json/plugins.mdxdocs/features/observability/otel.mdxplugins/otel/converter.goplugins/otel/converter_test.goplugins/otel/filter_test.goplugins/otel/main.gotransports/bifrost-http/handlers/config.gotransports/bifrost-http/handlers/plugins.gotransports/bifrost-http/handlers/plugins_test.gotransports/bifrost-http/lib/config.gotransports/bifrost-http/lib/config_test.gotransports/config.schema.jsonui/app/workspace/plugins/page.tsxui/app/workspace/plugins/sheets/pluginTracingSheet.tsxui/app/workspace/plugins/views/pluginsEmptyState.tsxui/lib/types/config.ts
✅ Files skipped from review due to trivial changes (5)
- transports/bifrost-http/handlers/config.go
- docs/features/observability/otel.mdx
- plugins/otel/filter_test.go
- docs/deployment-guides/config-json/plugins.mdx
- ui/lib/types/config.ts
🚧 Files skipped from review as they are similar to previous changes (9)
- ui/app/workspace/plugins/page.tsx
- transports/config.schema.json
- transports/bifrost-http/handlers/plugins_test.go
- plugins/otel/converter.go
- transports/bifrost-http/lib/config_test.go
- ui/app/workspace/plugins/sheets/pluginTracingSheet.tsx
- transports/bifrost-http/handlers/plugins.go
- plugins/otel/converter_test.go
- transports/bifrost-http/lib/config.go
b2159f9 to
256c125
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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 `@transports/bifrost-http/lib/config_test.go`:
- Around line 18236-18239: The test only asserts filterMap["mode"] but misses
verifying the passthrough of the plugin list; update the test that builds/reads
raw -> filterMap (variables raw and filterMap) to also assert that
filterMap["plugins"] exists and equals the expected plugin slice (the original
plugin list used for plugin_span_filter) so the plugins list is preserved
through parsing.
In `@ui/app/workspace/plugins/sheets/pluginTracingSheet.tsx`:
- Around line 114-126: Add a data-testid prop to both TriStateCheckbox "select
all" controls in pluginTracingSheet.tsx: for the built-in plugins
TriStateCheckbox (the one using allIds={[...BUILTIN_PLUGIN_NAMES]} and
selectedIds={BUILTIN_PLUGIN_NAMES.filter(...)}) add
data-testid="select-all-builtins" (or similar consistent name), and add a
matching data-testid (e.g., "select-all-plugins") to the other TriStateCheckbox
instance later in the file (the second "select all" control referenced in the
comment). Ensure the prop is passed directly to the TriStateCheckbox components
so E2E tests can target them.
- Around line 65-71: The sheet currently seeds toggle defaults when opened
before the OTEL plugin data arrives, so saved filter state can be overwritten;
update the useEffect to only initialize toggles after otelPlugin (the result of
useGetPluginQuery("otel")) is available and contains config (e.g., check
otelPlugin != null and otelPlugin.config is defined) and only then call
setToggles(resolveToggleState(...)) and set wasOpenRef.current = true after
initialization; reference resolveToggleState, setToggles, wasOpenRef,
otelPlugin, and the useEffect to ensure initialization waits for OTEL data
rather than running on open alone.
🪄 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: 275b6c3e-2de1-4979-a8da-20bdeca83399
📒 Files selected for processing (15)
docs/deployment-guides/config-json/plugins.mdxdocs/features/observability/otel.mdxplugins/otel/converter.goplugins/otel/converter_test.goplugins/otel/filter_test.goplugins/otel/main.gotransports/bifrost-http/handlers/plugins.gotransports/bifrost-http/handlers/plugins_test.gotransports/bifrost-http/lib/config.gotransports/bifrost-http/lib/config_test.gotransports/config.schema.jsonui/app/workspace/plugins/page.tsxui/app/workspace/plugins/sheets/pluginTracingSheet.tsxui/app/workspace/plugins/views/pluginsEmptyState.tsxui/lib/types/config.ts
✅ Files skipped from review due to trivial changes (3)
- transports/bifrost-http/lib/config.go
- docs/features/observability/otel.mdx
- transports/bifrost-http/handlers/plugins_test.go
🚧 Files skipped from review as they are similar to previous changes (6)
- plugins/otel/filter_test.go
- plugins/otel/converter_test.go
- ui/app/workspace/plugins/views/pluginsEmptyState.tsx
- plugins/otel/converter.go
- transports/bifrost-http/handlers/plugins.go
- ui/app/workspace/plugins/page.tsx
256c125 to
320b4c6
Compare
|
@coderabbitai full-review |
|
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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 910-947: Restructure the OTEL feature section to use Mintlify tabs
titled "Web UI", "API", and "config.json": move the current UI instructions into
the "Web UI" tab, add any HTTP/API guidance into the "API" tab (if none exists,
put a short note or omit), and place the shown JSON example and
config.json-specific notes (including plugin_span_filter, trace_type, protocol,
collector_url and version guidance) into the "config.json" tab; ensure the
config.json example validates against transports/config.schema.json and keep the
note about plugin_span_filter precedence (version) inside the config.json tab.
In `@plugins/otel/main.go`:
- Around line 76-78: Update the field comment for PluginSpanFilter to reflect
the current config flow: state that PluginSpanFilter comes from
Config.plugin_span_filter (the config package's Config struct) and is used
directly at Init time, that Init no longer accepts a separate pluginSpanFilter
argument, and remove any mention of the legacy otel_plugin_span_filter top-level
field or an Init override; keep note if this field is still a DB-stored fallback
if applicable.
In `@transports/bifrost-http/handlers/plugins_test.go`:
- Around line 39-41: The CreatePlugin method on capturePluginsStore is a no-op
so tests that only assert "not 500" can pass for wrong status codes; implement
CreatePlugin to persist the incoming *configstoreTables.TablePlugin into the
store's in-memory slice/map (the capturePluginsStore backing state) and update
the test that exercises the handler to assert a 200 OK success response (instead
of only checking not-500) and that the persisted plugin exists in
capturePluginsStore after the handler runs; refer to CreatePlugin and
capturePluginsStore and the handler test that currently checks response status
around the 154–157 area when making these changes.
🪄 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: ea92cb48-163b-417b-ab6e-02f0239f7897
📒 Files selected for processing (16)
docs/deployment-guides/config-json/plugins.mdxdocs/features/observability/otel.mdxplugins/otel/converter.goplugins/otel/converter_test.goplugins/otel/filter_test.goplugins/otel/main.gotransports/bifrost-http/handlers/plugins.gotransports/bifrost-http/handlers/plugins_test.gotransports/bifrost-http/lib/config.gotransports/bifrost-http/lib/config_test.gotransports/config.schema.jsonui/app/workspace/plugins/page.tsxui/app/workspace/plugins/sheets/pluginTracingSheet.tsxui/app/workspace/plugins/views/pluginsEmptyState.tsxui/components/ui/tristateCheckbox.tsxui/lib/types/config.ts
320b4c6 to
406f0bb
Compare
406f0bb to
071333d
Compare
071333d to
23f2911
Compare
aef041d to
942cba6
Compare
942cba6 to
726f84c
Compare
The base branch was changed.
Merge activity
|
…n exports (#3382) ## Summary Adds a `plugin_span_filter` feature to the OTEL plugin that lets operators control which plugin hook spans are exported to the OTEL collector. Without filtering, every plugin generates two spans per request (pre- and post-hook), which can produce 16+ plugin spans per request with the default set of built-in plugins. This change introduces a `plugin_span_filter` field inside the OTEL plugin config (both config.json and DB) and a UI sheet ("Configure Plugin Tracing") for managing this at runtime. ## Changes - **`plugins/otel`**: Added `PluginSpanFilter` type with `include`/`exclude` modes. `shouldExportSpan` checks each span against the filter; `buildReparentMap` resolves chains of consecutive filtered spans so their children are re-parented to the nearest exported ancestor, keeping the trace hierarchy intact. `Init` and `ValidateConfig` both validate that `plugin_span_filter.mode` is a recognized value. - **`transports/bifrost-http/handlers/plugins.go`**: `updatePlugin` now fetches the existing plugin before saving and merges the incoming config over the existing DB config using `maps.Copy`, so fields like `plugin_span_filter` that are not sent by the OTEL config form are not silently wiped on save. - **UI**: Added `PluginTracingSheet` — a side sheet accessible via a new "Configure Plugin Tracing" button on the Plugins page (and on the empty state). It renders per-plugin toggles (built-in and custom) with tri-state select-all checkboxes, reads the current filter from the OTEL plugin's DB config, and saves only `plugin_span_filter` into the OTEL plugin config via `updatePlugin`. Added `PluginSpanFilter` and `PluginSpanFilterMode` types to the UI type definitions. - **Docs**: Added a "Filtering Plugin Spans" section to the OTEL observability page and a `config.plugin_span_filter` row to the plugins config reference. - **Schema**: Added `plugin_span_filter` inside the OTEL plugin config object to `config.schema.json`. - **Tests**: Added `converter_test.go` (unit tests for `shouldExportSpan` and `buildReparentMap`), `filter_test.go` (JSON round-trip tests for `PluginSpanFilter` and `Config`), `plugins_test.go` in the handlers package (config merge behavior), and passthrough tests in `config_test.go`. ## Type of change - [ ] Bug fix - [x] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [x] Core (Go) - [x] Transports (HTTP) - [ ] Providers/Integrations - [x] Plugins - [x] UI (React) - [x] Docs ## How to test ```sh # Backend go test ./plugins/otel/... go test ./transports/bifrost-http/handlers/... go test ./transports/bifrost-http/lib/... # UI cd ui pnpm i pnpm build ``` **config.json (inside the OTEL plugin config):** ```json { "plugins": [ { "name": "otel", "enabled": true, "config": { "collector_url": "...", "trace_type": "genai_extension", "protocol": "http", "plugin_span_filter": { "mode": "exclude", "plugins": ["logging", "compat", "telemetry", "otel"] } } } ] } ``` Restart Bifrost and verify that traces no longer contain spans for the listed plugins, and that child spans of filtered plugins are re-parented to the nearest exported ancestor. **UI flow:** Navigate to Plugins → click "Configure Plugin Tracing" → toggle individual plugins off → Save. Verify the OTEL plugin's DB config contains `plugin_span_filter` and that subsequent saves of the OTEL config form do not wipe the filter. **Precedence:** Set `plugin_span_filter` in config.json with a higher `version` value and a different value via the UI. Restart and confirm the config.json value takes effect. ## Breaking changes - [x] No ## Security considerations No new secrets or PII are introduced. The filter configuration contains only plugin names and a mode string. ## Checklist - [x] I added/updated tests where appropriate - [x] I updated documentation where needed - [x] I verified builds succeed (Go and UI)
…n exports (#3382) ## Summary Adds a `plugin_span_filter` feature to the OTEL plugin that lets operators control which plugin hook spans are exported to the OTEL collector. Without filtering, every plugin generates two spans per request (pre- and post-hook), which can produce 16+ plugin spans per request with the default set of built-in plugins. This change introduces a `plugin_span_filter` field inside the OTEL plugin config (both config.json and DB) and a UI sheet ("Configure Plugin Tracing") for managing this at runtime. ## Changes - **`plugins/otel`**: Added `PluginSpanFilter` type with `include`/`exclude` modes. `shouldExportSpan` checks each span against the filter; `buildReparentMap` resolves chains of consecutive filtered spans so their children are re-parented to the nearest exported ancestor, keeping the trace hierarchy intact. `Init` and `ValidateConfig` both validate that `plugin_span_filter.mode` is a recognized value. - **`transports/bifrost-http/handlers/plugins.go`**: `updatePlugin` now fetches the existing plugin before saving and merges the incoming config over the existing DB config using `maps.Copy`, so fields like `plugin_span_filter` that are not sent by the OTEL config form are not silently wiped on save. - **UI**: Added `PluginTracingSheet` — a side sheet accessible via a new "Configure Plugin Tracing" button on the Plugins page (and on the empty state). It renders per-plugin toggles (built-in and custom) with tri-state select-all checkboxes, reads the current filter from the OTEL plugin's DB config, and saves only `plugin_span_filter` into the OTEL plugin config via `updatePlugin`. Added `PluginSpanFilter` and `PluginSpanFilterMode` types to the UI type definitions. - **Docs**: Added a "Filtering Plugin Spans" section to the OTEL observability page and a `config.plugin_span_filter` row to the plugins config reference. - **Schema**: Added `plugin_span_filter` inside the OTEL plugin config object to `config.schema.json`. - **Tests**: Added `converter_test.go` (unit tests for `shouldExportSpan` and `buildReparentMap`), `filter_test.go` (JSON round-trip tests for `PluginSpanFilter` and `Config`), `plugins_test.go` in the handlers package (config merge behavior), and passthrough tests in `config_test.go`. ## Type of change - [ ] Bug fix - [x] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [x] Core (Go) - [x] Transports (HTTP) - [ ] Providers/Integrations - [x] Plugins - [x] UI (React) - [x] Docs ## How to test ```sh # Backend go test ./plugins/otel/... go test ./transports/bifrost-http/handlers/... go test ./transports/bifrost-http/lib/... # UI cd ui pnpm i pnpm build ``` **config.json (inside the OTEL plugin config):** ```json { "plugins": [ { "name": "otel", "enabled": true, "config": { "collector_url": "...", "trace_type": "genai_extension", "protocol": "http", "plugin_span_filter": { "mode": "exclude", "plugins": ["logging", "compat", "telemetry", "otel"] } } } ] } ``` Restart Bifrost and verify that traces no longer contain spans for the listed plugins, and that child spans of filtered plugins are re-parented to the nearest exported ancestor. **UI flow:** Navigate to Plugins → click "Configure Plugin Tracing" → toggle individual plugins off → Save. Verify the OTEL plugin's DB config contains `plugin_span_filter` and that subsequent saves of the OTEL config form do not wipe the filter. **Precedence:** Set `plugin_span_filter` in config.json with a higher `version` value and a different value via the UI. Restart and confirm the config.json value takes effect. ## Breaking changes - [x] No ## Security considerations No new secrets or PII are introduced. The filter configuration contains only plugin names and a mode string. ## Checklist - [x] I added/updated tests where appropriate - [x] I updated documentation where needed - [x] I verified builds succeed (Go and UI)
…n exports (#3382) ## Summary Adds a `plugin_span_filter` feature to the OTEL plugin that lets operators control which plugin hook spans are exported to the OTEL collector. Without filtering, every plugin generates two spans per request (pre- and post-hook), which can produce 16+ plugin spans per request with the default set of built-in plugins. This change introduces a `plugin_span_filter` field inside the OTEL plugin config (both config.json and DB) and a UI sheet ("Configure Plugin Tracing") for managing this at runtime. ## Changes - **`plugins/otel`**: Added `PluginSpanFilter` type with `include`/`exclude` modes. `shouldExportSpan` checks each span against the filter; `buildReparentMap` resolves chains of consecutive filtered spans so their children are re-parented to the nearest exported ancestor, keeping the trace hierarchy intact. `Init` and `ValidateConfig` both validate that `plugin_span_filter.mode` is a recognized value. - **`transports/bifrost-http/handlers/plugins.go`**: `updatePlugin` now fetches the existing plugin before saving and merges the incoming config over the existing DB config using `maps.Copy`, so fields like `plugin_span_filter` that are not sent by the OTEL config form are not silently wiped on save. - **UI**: Added `PluginTracingSheet` — a side sheet accessible via a new "Configure Plugin Tracing" button on the Plugins page (and on the empty state). It renders per-plugin toggles (built-in and custom) with tri-state select-all checkboxes, reads the current filter from the OTEL plugin's DB config, and saves only `plugin_span_filter` into the OTEL plugin config via `updatePlugin`. Added `PluginSpanFilter` and `PluginSpanFilterMode` types to the UI type definitions. - **Docs**: Added a "Filtering Plugin Spans" section to the OTEL observability page and a `config.plugin_span_filter` row to the plugins config reference. - **Schema**: Added `plugin_span_filter` inside the OTEL plugin config object to `config.schema.json`. - **Tests**: Added `converter_test.go` (unit tests for `shouldExportSpan` and `buildReparentMap`), `filter_test.go` (JSON round-trip tests for `PluginSpanFilter` and `Config`), `plugins_test.go` in the handlers package (config merge behavior), and passthrough tests in `config_test.go`. ## Type of change - [ ] Bug fix - [x] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [x] Core (Go) - [x] Transports (HTTP) - [ ] Providers/Integrations - [x] Plugins - [x] UI (React) - [x] Docs ## How to test ```sh # Backend go test ./plugins/otel/... go test ./transports/bifrost-http/handlers/... go test ./transports/bifrost-http/lib/... # UI cd ui pnpm i pnpm build ``` **config.json (inside the OTEL plugin config):** ```json { "plugins": [ { "name": "otel", "enabled": true, "config": { "collector_url": "...", "trace_type": "genai_extension", "protocol": "http", "plugin_span_filter": { "mode": "exclude", "plugins": ["logging", "compat", "telemetry", "otel"] } } } ] } ``` Restart Bifrost and verify that traces no longer contain spans for the listed plugins, and that child spans of filtered plugins are re-parented to the nearest exported ancestor. **UI flow:** Navigate to Plugins → click "Configure Plugin Tracing" → toggle individual plugins off → Save. Verify the OTEL plugin's DB config contains `plugin_span_filter` and that subsequent saves of the OTEL config form do not wipe the filter. **Precedence:** Set `plugin_span_filter` in config.json with a higher `version` value and a different value via the UI. Restart and confirm the config.json value takes effect. ## Breaking changes - [x] No ## Security considerations No new secrets or PII are introduced. The filter configuration contains only plugin names and a mode string. ## Checklist - [x] I added/updated tests where appropriate - [x] I updated documentation where needed - [x] I verified builds succeed (Go and UI)
## Summary This PR cuts the `v1.5.11` / `v1.3.11` release across core, framework, and all plugins, and introduces a new Claude skill (`release-checklist`) for pre-release migration safety auditing. ## Changes - **`release-checklist` skill** — Adds `.claude/skills/release-checklist/SKILL.md`, a read-only pre-release audit tool that scans Go-defined database migrations changed in a release for high-scale deadlock/lock-contention risks and boot-time-blocking operations. It produces a structured `PASS`/`WARN`/`FAIL` report with a concrete remediation plan per finding. The skill is designed to grow via an extensible Checks Registry. - **Version bumps** — `core` → `1.5.11`, `framework` → `1.3.11`, `transports` → `1.5.3`, `plugins/governance` → `1.5.11`, `plugins/logging` → `1.5.11`, `plugins/semanticcache` → `1.5.11`, `plugins/otel` → `1.2.11`, `plugins/maxim` → `1.6.11`, `plugins/prompts` → `1.0.11`, and remaining plugins bumped accordingly. - **Changelogs populated** — All per-package changelogs updated with the full set of features and fixes shipping in this release. Key highlights in this release: - Temporary access tokens for scoped, time-limited API access - MCP per-user OAuth flow refactor - Bedrock Mantle inference engine support - Azure Realtime provider with enriched session tracking - Direct access control (DAC) and virtual key rotation - Cluster-aware log metadata and per-node usage aggregation - Feature flag framework - Config-hash-based file value override of DB on restart - Semantic cache plugin rewrite - Numerous streaming stability, Bedrock, Anthropic, and Gemini fixes - AWS SDK and dependency security updates ## Type of change - [ ] Bug fix - [ ] Feature - [ ] Refactor - [ ] Documentation - [x] Chore/CI ## Affected areas - [x] Core (Go) - [x] Transports (HTTP) - [x] Providers/Integrations - [x] Plugins - [x] UI (React) - [ ] Docs ## How to test ```sh # Verify version files reflect the new release cat core/version # expect 1.5.11 cat framework/version # expect 1.3.11 cat transports/version # expect 1.5.3 # Core/Transports go test ./... ``` To exercise the new `release-checklist` skill, invoke it via Claude with: ``` /release-checklist origin/dev...HEAD ``` Expected output: a structured report with `PASS`/`WARN`/`FAIL` per check and a Remediation Plan table for any findings. ## Screenshots/Recordings N/A ## Breaking changes - [ ] Yes - [x] No ## Related issues #3603, #3565, #3489, #3334, #3335, #3435, #3554, #3590, #3444, #3198, #3581, #3610, #3599, #3567, #3382, #3461 and others listed in the changelogs. ## Security considerations - AWS SDK and dependency security updates are included (#3461). - `FullyRedacted()` for proxy passwords and `MarshalForStorage()` for `ProxyConfig` prevent partial secret leakage in API responses (#3445). - The `release-checklist` skill is strictly read-only and never modifies files. ## Checklist - [x] I read `docs/contributing/README.md` and followed the guidelines - [x] I added/updated tests where appropriate - [x] I updated documentation where needed - [x] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable

Summary
Adds a
plugin_span_filterfeature to the OTEL plugin that lets operators control which plugin hook spans are exported to the OTEL collector. Without filtering, every plugin generates two spans per request (pre- and post-hook), which can produce 16+ plugin spans per request with the default set of built-in plugins. This change introduces aplugin_span_filterfield inside the OTEL plugin config (both config.json and DB) and a UI sheet ("Configure Plugin Tracing") for managing this at runtime.Changes
plugins/otel: AddedPluginSpanFiltertype withinclude/excludemodes.shouldExportSpanchecks each span against the filter;buildReparentMapresolves chains of consecutive filtered spans so their children are re-parented to the nearest exported ancestor, keeping the trace hierarchy intact.InitandValidateConfigboth validate thatplugin_span_filter.modeis a recognized value.transports/bifrost-http/handlers/plugins.go:updatePluginnow fetches the existing plugin before saving and merges the incoming config over the existing DB config usingmaps.Copy, so fields likeplugin_span_filterthat are not sent by the OTEL config form are not silently wiped on save.PluginTracingSheet— a side sheet accessible via a new "Configure Plugin Tracing" button on the Plugins page (and on the empty state). It renders per-plugin toggles (built-in and custom) with tri-state select-all checkboxes, reads the current filter from the OTEL plugin's DB config, and saves onlyplugin_span_filterinto the OTEL plugin config viaupdatePlugin. AddedPluginSpanFilterandPluginSpanFilterModetypes to the UI type definitions.config.plugin_span_filterrow to the plugins config reference.plugin_span_filterinside the OTEL plugin config object toconfig.schema.json.converter_test.go(unit tests forshouldExportSpanandbuildReparentMap),filter_test.go(JSON round-trip tests forPluginSpanFilterandConfig),plugins_test.goin the handlers package (config merge behavior), and passthrough tests inconfig_test.go.Type of change
Affected areas
How to test
config.json (inside the OTEL plugin config):
{ "plugins": [ { "name": "otel", "enabled": true, "config": { "collector_url": "...", "trace_type": "genai_extension", "protocol": "http", "plugin_span_filter": { "mode": "exclude", "plugins": ["logging", "compat", "telemetry", "otel"] } } } ] }Restart Bifrost and verify that traces no longer contain spans for the listed plugins, and that child spans of filtered plugins are re-parented to the nearest exported ancestor.
UI flow: Navigate to Plugins → click "Configure Plugin Tracing" → toggle individual plugins off → Save. Verify the OTEL plugin's DB config contains
plugin_span_filterand that subsequent saves of the OTEL config form do not wipe the filter.Precedence: Set
plugin_span_filterin config.json with a higherversionvalue and a different value via the UI. Restart and confirm the config.json value takes effect.Breaking changes
Security considerations
No new secrets or PII are introduced. The filter configuration contains only plugin names and a mode string.
Checklist