Skip to content

feat(observability): send configured headers to every OTLP collector - #5083

Merged
krishicks merged 1 commit into
mainfrom
feat/5067-otlp-collector-headers/krishicks
Nov 2, 2026
Merged

krishicks merged 1 commit into
mainfrom
feat/5067-otlp-collector-headers/krishicks

Conversation

@krishicks

@krishicks krishicks commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Collectors that need an authorization token or a routing header could get one only through OTEL_EXPORTER_OTLP_*HEADERS in the gateway's environment, which never reached supervisor spans or the agent trace relay. Each [openshell.gateway.otlp] table now takes headers, or a headers_file that keeps credentials out of the configuration file, and every exporter sends them.

Related Issue

Closes #5067

Changes

  • headers (an inline table) and headers_file (one name=value header per line, at most 64 KiB) on every OTLP table, mutually exclusive and inherited with the rest of the collector. Setting either in a table without its own endpoint is a configuration error.
  • Headers are validated at load: valid names set once, no exporter-owned names (content-type, host, grpc-*, and others), no binary -bin names, and non-empty printable-ASCII values. Errors never include a value or a name that failed validation, and headers_file errors cite the line number instead. Debug output redacts values, and values read from headers_file are never serialized back out. Config parse errors now give the line, column (in characters), and parser message without quoting the file or any string in it, so a malformed header table cannot echo a token.
  • Exporters send headers as gRPC metadata or HTTP headers, with values sent exactly as configured. Environment headers still apply to the gateway's own exporters and replace configured headers of the same name. Supervisor trace export and the agent relay send only their table's configured headers; supervisor OCSF export keeps the environment merge it already has.
  • Supervisors receive each lane's headers in their launch credentials, never through the sandbox environment. The VM driver receives the same trace headers as the gateway's own exporter, in its environment. Standalone drivers send only their own OTEL_EXPORTER_OTLP_*HEADERS.
  • Gateway configuration docs describe the keys, validation, relative paths, cleartext caveats, external-driver endpoints, version skew, and rollback; the traces page mentions headers.

Release Notes

OTLP collectors can require authentication or routing headers: set headers or headers_file on [openshell.gateway.otlp] or a signal table. Supervisors and the agent trace relay send them too, so MLflow can ingest relayed agent traces directly with x-mlflow-experiment-id.

Testing

  • CI lint locally on this commit: tracked lockfile and alignment checks, cargo fmt --check, and every mise run rust:lint clippy invocation with --locked
  • openshell-server config tests pass on this commit; its tracing and compute tests and openshell-gateway lib tests pass at the top of the stack
  • Unit tests added/updated: header validation, inheritance, headers_file parsing and line-numbered errors, redaction, parse errors that do not quote the file, environment headers winning on the gateway's exporters, which headers each driver and supervisor lane receives, and headers arriving at loopback gRPC and HTTP collectors from the gateway, supervisor, and relay
  • E2E tests added/updated (if applicable)

Manually verified before the latest rebase: a dev Docker gateway relayed Pi agent traces directly to MLflow over OTLP/HTTP with x-mlflow-experiment-id, and each trace carried openshell.sandbox.id.

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Architecture docs updated (if applicable)

@krishicks krishicks added area:docs Documentation and examples topic:observability Logging, metrics, and observability work area:supervisor Proxy and routing-path work area:gateway Gateway server and control-plane work area:compute labels Oct 30, 2026
@copy-pr-bot

copy-pr-bot Bot commented Oct 30, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@krishicks
krishicks added this pull request to stack #5085 October 30, 2026 22:12
@github-actions

Copy link
Copy Markdown

@krishicks
krishicks marked this pull request as ready for review October 30, 2026 22:16
@github-actions

Copy link
Copy Markdown

Compatibility review (advisory)

New or updated breaking changes; see the full report for all findings.

1. api-behavior — No explicit risk acceptance found

With trace export enabled, existing OTEL_EXPORTER_OTLP_TRACES_HEADERS or OTEL_EXPORTER_OTLP_HEADERS settings now add traces_otlp_headers to launch_authentication instead of preserving the baseline JSON payload.

  • Impact: Previously compatible external compute drivers using the baseline decoder fail sandbox creation and start-from-stopped with an unknown-field error.
  • Action: For v0.1.7, negotiate trace-header support and omit new launch fields for legacy peers rather than requiring existing external drivers to upgrade.
  • PR: feat(observability): send configured headers to every OTLP collector #5083
Review details
  • Execution: complete
  • Candidate: PR #5083 (c736ddc358f21178dc1100bdd7920221bf4588e4)
  • Baseline: 0d79a30690a1cc366d5477ef02d0d866298a4a12 (0d79a30690a1cc366d5477ef02d0d866298a4a12)
  • Reviewed: rust-sdk, python-sdk, go-sdk, typescript-sdk, api-behavior, cli, configuration, policy, helm, state

Advisory review; publication gates are unchanged.

Branch check run

@krishicks
krishicks force-pushed the feat/5067-otlp-collector-headers/krishicks branch 2 times, most recently from c9ae50e to dc42f93 Compare November 2, 2026 15:49

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

cc-review Summary

This is an agent-assisted review: cc-review ran several reviewer agents plus Codex and CodeRabbit over the diff. The redaction design holds up well, but three items should be fixed first: two error paths that can echo a credential into the gateway startup log, and an upgrade compatibility question that needs a maintainer decision. The failure scenarios come from reading the code, not from running a gateway. The one exception is the toml error message quoted in the parse_error_detail comment, which a reviewer agent reproduced in a scratch program against toml 0.8.23. The Minor findings are non-blocking, and once the three Important items are addressed (or a maintainer settles the compatibility question) this should be ready for a maintainer.

What Went Well

  • Credential values stay out of logs. The hand-written Debug impls for OtlpTarget and OtlpHeaders print header names only, SupervisorAuthBundle redacts the new header fields, and ConfigFileError::Parse reports line and column instead of quoting the source.
  • append_otlp_args hands the VM driver its trace headers through OTEL_EXPORTER_OTLP_TRACES_HEADERS rather than argv, and vm_driver_receives_trace_headers_in_its_environment_only checks that no argument contains the secret.
  • read_headers_file caps the read with take(MAX_HEADERS_FILE_BYTES + 1) and rejects non-UTF-8, malformed and duplicate lines before validation.
  • Header parsing now lives in the shared headers.rs, used by the gateway, supervisor and relay alike, with a round-trip test for values containing ,, =, % and spaces. configure_http removes the duplicated HTTP exporter setup between traces and logs.
  • RawCollector::resolve applies one rule to every lane (own endpoint, or inherit the whole shared collector), so one collector's credentials can't leak to another.

Findings

Severity File Description Source
Important crates/openshell-server/src/config_file.rs:485 Invalid header name error echoes the headers_file line, so a padded token reaches the startup log security
Important crates/openshell-server/src/config_file.rs:1232 parse_error_detail forwards serde messages that quote a string-typed headers value security
Important crates/openshell-server/src/otel_tracing.rs:325 Env-only header setups now add traces_otlp_headers, which older supervisors and drivers reject production
Minor crates/openshell-gateway/src/vm.rs:730 VM driver trace headers come from the supervisor helper, a second derivation of the same value architecture
Minor crates/openshell-otel/src/lib.rs:318 configure_http decodes header values twice on OTLP/HTTP, changing literal %XX sequences correctness
Minor crates/openshell-otel/src/lib.rs:681 Header tests don't clear OTEL_EXPORTER_OTLP_*HEADERS and fail when a developer has them set test-quality
Minor crates/openshell-server/src/config_file.rs:460 An unreadable headers_file stops the gateway from starting; the docs should say so production
Minor crates/openshell-server/src/config_file.rs:795 Endpoint-required check duplicates RawCollector::resolve, and shared skips raw_collector! architecture
Minor crates/openshell-server/src/config_file.rs:2111 No-echo assertions cover two of about fifteen header validation error cases test-quality
Minor crates/openshell-server/src/otel_tracing.rs:899 No test for env headers overriding configured headers on the gateway's own exporters test-quality
Minor crates/openshell-server/src/tracing_setup.rs:77 No test that in-process compute drivers receive the trace collector's configured headers test-quality

Review Details

  • Findings posted: 11 (11 inline)
  • Findings reviewed and not posted: 2 (documented behavior: header rotation needs restarts; external drivers must use the gateway's endpoints)
  • Gate outcome: FAIL (3 Important)
  • Participating reviewers: architecture, correctness, goal-alignment, production, security, test-quality, gator, codex, coderabbit

Comment thread crates/openshell-gateway/src/vm.rs Resolved
Comment thread crates/openshell-otel/src/lib.rs Resolved
Comment thread crates/openshell-otel/src/lib.rs Resolved

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

cc-review found no issues at a69ff8e.

Base automatically changed from feat/5067-otlp-http-protocol/krishicks to main November 2, 2026 20:26
Collectors that require authentication or a routing header could only get
one through OTEL_EXPORTER_OTLP_*HEADERS in the gateway's environment, which
reached the gateway's own exporters and supervisors' OCSF records but not
supervisor spans or the agent relay, so a backend such as MLflow needed a
sidecar collector to add its experiment header.

Each [openshell.gateway.otlp] table now takes a headers table, or a
headers_file of name=value lines that keeps credentials out of the config
file, inherited with the rest of the collector by tables without their own
endpoint. Exporters send them as gRPC metadata or HTTP headers, with
environment headers replacing configured ones of the same name. Supervisors
receive each lane's headers in their launch bundle and the VM driver in its
environment; the agent relay uses only its table's headers. Config parse
errors give a line and column instead of quoting the file, so a malformed
header table cannot echo a token.

Closes #5067

Signed-off-by: Kris Hicks <khicks@nvidia.com>
@krishicks
krishicks force-pushed the feat/5067-otlp-collector-headers/krishicks branch from a69ff8e to 73c5c33 Compare November 2, 2026 20:26
@krishicks
krishicks requested a review from rhuss November 2, 2026 21:40
@krishicks
krishicks enabled stacked auto-merge November 2, 2026 21:43
@krishicks
krishicks added this pull request to the merge queue Nov 2, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Nov 2, 2026
@krishicks
krishicks added this pull request to the merge queue Nov 2, 2026
Merged via the queue into main with commit 5dfb225 Nov 2, 2026
84 checks passed
@krishicks
krishicks deleted the feat/5067-otlp-collector-headers/krishicks branch November 2, 2026 23:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:compute area:docs Documentation and examples area:gateway Gateway server and control-plane work area:supervisor Proxy and routing-path work topic:observability Logging, metrics, and observability work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(observability): support OTLP/HTTP and collector headers for relayed agent traces

3 participants