-
Notifications
You must be signed in to change notification settings - Fork 646
Description
Problem
The Rust OTLP HTTP exporters have no programmatic way to provide a base URL and have the SDK automatically append the signal path (/v1/logs, /v1/traces, /v1/metrics).
.with_endpoint() treats its argument as a full URL and uses it verbatim — there is no programmatic equivalent of OTEL_EXPORTER_OTLP_ENDPOINT (which does append the signal path).
Comparison with Go SDK
The Go SDK distinguishes between two use cases via two separate methods:
// Base URL → SDK appends /v1/logs automatically ✅
otlploghttp.WithEndpoint("localhost:4318")
// Full URL → used as-is ✅
otlploghttp.WithEndpointURL("http://localhost:4318/v1/logs")The Rust SDK only has one method:
// Always treated as full URL → signal path never appended ✗
.with_endpoint("http://localhost:4318")There is no Rust equivalent of Go's WithEndpoint(host:port).
Root cause in exporter/http/mod.rs
resolve_http_endpoint (L705–735) has three code paths:
// 1. Programmatic .with_endpoint() → returned as-is, no path appended ✗
if let Some(provider_endpoint) = provided_endpoint.filter(|s| !s.is_empty()) {
return provider_endpoint.parse()
}
// 2. Signal-specific env var (e.g. OTEL_EXPORTER_OTLP_LOGS_ENDPOINT) → returned as-is ✗
// (comment: "per signal env var is not modified")
// 3. Generic OTEL_EXPORTER_OTLP_ENDPOINT → /v1/logs appended ✓
build_endpoint_uri(&s, signal_endpoint_path)Signal path appending is only reachable via the generic env var. There is no programmatic equivalent.
Impact
Applications that configure the OTLP endpoint programmatically (e.g. reading from a config file) cannot provide a base URL — they must either:
- Hardcode the full signal path (e.g.
http://localhost:4318/v1/logs), or - Fall back to setting
OTEL_EXPORTER_OTLP_ENDPOINTas an environment variable at runtime
This is a real footgun for library consumers such as Codex CLI, which reads an endpoint from user config and calls .with_endpoint() — requiring users to manually include /v1/logs in their config.
Suggested fix
Add a with_base_endpoint() method (or a flag on with_endpoint()) that appends the signal path, mirroring Go's WithEndpoint(host:port):
// New API — behaves like OTEL_EXPORTER_OTLP_ENDPOINT
.with_base_endpoint("http://localhost:4318")
// → exports to http://localhost:4318/v1/logsWorkaround
# Unset programmatic endpoint and use env var instead
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
# SDK appends /v1/logs, /v1/traces, /v1/metrics automaticallyEnvironment
- Crate:
opentelemetry-otlp - Transport: HTTP
- Signals affected: Logs, Traces, Metrics
Related
- opentelemetry-otlp: '/v1/traces' is not appended to endpoint for http exporter #997 — original traces endpoint issue (closed)
- Not able to use env var for otlp headers in config openai/codex#14465 — real-world consumer hit by this gap