Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow specifying OTLP HTTP headers from env variable #1290

Merged
merged 8 commits into from
Oct 8, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 64 additions & 6 deletions opentelemetry-otlp/src/exporter/http/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::{ExportConfig, Protocol, OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_TIMEOUT};
use crate::{
ExportConfig, Protocol, OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_HEADERS,
OTEL_EXPORTER_OTLP_TIMEOUT,
};
use http::{HeaderName, HeaderValue, Uri};
use opentelemetry_http::HttpClient;
use std::collections::HashMap;
Expand Down Expand Up @@ -143,6 +146,7 @@
signal_endpoint_var: &str,
signal_endpoint_path: &str,
signal_timeout_var: &str,
signal_http_headers_var: &str,

Check warning on line 149 in opentelemetry-otlp/src/exporter/http/mod.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-otlp/src/exporter/http/mod.rs#L149

Added line #L149 was not covered by tests
) -> Result<OtlpHttpClient, crate::Error> {
let endpoint = resolve_endpoint(
signal_endpoint_var,
Expand All @@ -167,8 +171,7 @@
.take()
.ok_or(crate::Error::NoHttpClient)?;

#[allow(clippy::mutable_key_type)] // http headers are not mutated
let headers = self
let mut headers: HashMap<HeaderName, HeaderValue> = self

Check warning on line 174 in opentelemetry-otlp/src/exporter/http/mod.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-otlp/src/exporter/http/mod.rs#L174

Added line #L174 was not covered by tests
.http_config
.headers
.take()
Expand All @@ -182,6 +185,12 @@
})
.collect();

if let Ok(input) =
env::var(signal_http_headers_var).or_else(|_| env::var(OTEL_EXPORTER_OTLP_HEADERS))
lalitb marked this conversation as resolved.
Show resolved Hide resolved
{
add_header_from_string(&input, &mut headers);
}

Check warning on line 192 in opentelemetry-otlp/src/exporter/http/mod.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-otlp/src/exporter/http/mod.rs#L188-L192

Added lines #L188 - L192 were not covered by tests

Ok(OtlpHttpClient::new(http_client, endpoint, headers, timeout))
}

Expand All @@ -190,12 +199,16 @@
pub fn build_span_exporter(
mut self,
) -> Result<crate::SpanExporter, opentelemetry::trace::TraceError> {
use crate::{OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_TIMEOUT};
use crate::{
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_HEADERS,
OTEL_EXPORTER_OTLP_TRACES_TIMEOUT,
};

let client = self.build_client(
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT,
"/v1/traces",
OTEL_EXPORTER_OTLP_TRACES_TIMEOUT,
OTEL_EXPORTER_OTLP_TRACES_HEADERS,

Check warning on line 211 in opentelemetry-otlp/src/exporter/http/mod.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-otlp/src/exporter/http/mod.rs#L211

Added line #L211 was not covered by tests
)?;

Ok(crate::SpanExporter::new(client))
Expand All @@ -204,12 +217,16 @@
/// Create a log exporter with the current configuration
#[cfg(feature = "logs")]
pub fn build_log_exporter(mut self) -> opentelemetry::logs::LogResult<crate::LogExporter> {
use crate::{OTEL_EXPORTER_OTLP_LOGS_ENDPOINT, OTEL_EXPORTER_OTLP_LOGS_TIMEOUT};
use crate::{
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT, OTEL_EXPORTER_OTLP_LOGS_HEADERS,
OTEL_EXPORTER_OTLP_LOGS_TIMEOUT,
};

let client = self.build_client(
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT,
"/v1/logs",
OTEL_EXPORTER_OTLP_LOGS_TIMEOUT,
OTEL_EXPORTER_OTLP_LOGS_HEADERS,

Check warning on line 229 in opentelemetry-otlp/src/exporter/http/mod.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-otlp/src/exporter/http/mod.rs#L229

Added line #L229 was not covered by tests
)?;

Ok(crate::LogExporter::new(client))
Expand All @@ -222,12 +239,16 @@
aggregation_selector: Box<dyn opentelemetry_sdk::metrics::reader::AggregationSelector>,
temporality_selector: Box<dyn opentelemetry_sdk::metrics::reader::TemporalitySelector>,
) -> opentelemetry::metrics::Result<crate::MetricsExporter> {
use crate::{OTEL_EXPORTER_OTLP_METRICS_ENDPOINT, OTEL_EXPORTER_OTLP_METRICS_TIMEOUT};
use crate::{
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT, OTEL_EXPORTER_OTLP_METRICS_HEADERS,
OTEL_EXPORTER_OTLP_METRICS_TIMEOUT,
};

let client = self.build_client(
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT,
"/v1/metrics",
OTEL_EXPORTER_OTLP_METRICS_TIMEOUT,
OTEL_EXPORTER_OTLP_METRICS_HEADERS,

Check warning on line 251 in opentelemetry-otlp/src/exporter/http/mod.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-otlp/src/exporter/http/mod.rs#L251

Added line #L251 was not covered by tests
)?;

Ok(crate::MetricsExporter::new(
Expand Down Expand Up @@ -291,6 +312,26 @@
.map_err(From::from)
}

fn add_header_from_string(input: &str, headers: &mut HashMap<HeaderName, HeaderValue>) {
for pair in input.split(',') {
lalitb marked this conversation as resolved.
Show resolved Hide resolved
if pair.is_empty() {
continue;

Check warning on line 318 in opentelemetry-otlp/src/exporter/http/mod.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-otlp/src/exporter/http/mod.rs#L318

Added line #L318 was not covered by tests
}
let mut kv_iter = pair.splitn(2, '=');
match (kv_iter.next(), kv_iter.next()) {
lalitb marked this conversation as resolved.
Show resolved Hide resolved
(Some(k), Some(v)) if !k.trim().is_empty() && !v.trim().is_empty() => {
headers.insert(
HeaderName::from_str(k.trim()).ok().unwrap(),
HeaderValue::from_str(v.trim()).ok().unwrap(),
);
}
_ => {
break; // stop parsing on error

Check warning on line 329 in opentelemetry-otlp/src/exporter/http/mod.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-otlp/src/exporter/http/mod.rs#L329

Added line #L329 was not covered by tests
}
}
}
}

#[cfg(test)]
mod tests {
use crate::{OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT};
Expand Down Expand Up @@ -410,4 +451,21 @@
// You may also want to assert on the specific error type if applicable
});
}

#[test]
fn test_add_header_from_string() {
lalitb marked this conversation as resolved.
Show resolved Hide resolved
use http::{HeaderName, HeaderValue};
use std::collections::HashMap;
let mut headers: HashMap<HeaderName, HeaderValue> = std::collections::HashMap::new();
headers.insert(
HeaderName::from_static("k1"),
HeaderValue::from_static("v1"),
);
headers.insert(
HeaderName::from_static("k2"),
HeaderValue::from_static("v2"),
);
super::add_header_from_string("k1=new_v1, k3=v3", &mut headers);
assert_eq!(headers.len(), 3);
}
}
4 changes: 4 additions & 0 deletions opentelemetry-otlp/src/exporter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ use std::time::Duration;
pub const OTEL_EXPORTER_OTLP_ENDPOINT: &str = "OTEL_EXPORTER_OTLP_ENDPOINT";
/// Default target to which the exporter is going to send signals.
pub const OTEL_EXPORTER_OTLP_ENDPOINT_DEFAULT: &str = OTEL_EXPORTER_OTLP_HTTP_ENDPOINT_DEFAULT;
/// Key-value pairs to be used as headers associated with gRPC or HTTP requests
/// Example: `k1=v1,k2=v2`
/// Note: as of now, this is only supported for HTTP requests.
pub const OTEL_EXPORTER_OTLP_HEADERS: &str = "OTEL_EXPORTER_OTLP_HEADERS";
/// Protocol the exporter will use. Either `http/protobuf` or `grpc`.
pub const OTEL_EXPORTER_OTLP_PROTOCOL: &str = "OTEL_EXPORTER_OTLP_PROTOCOL";
/// Compression algorithm to use, defaults to none.
Expand Down
2 changes: 1 addition & 1 deletion opentelemetry-otlp/src/exporter/tonic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ impl TonicExporterBuilder {
signal_compression_var: &str,
) -> Result<(Channel, BoxInterceptor, Option<CompressionEncoding>), crate::Error> {
let config = &mut self.exporter_config;
let tonic_config = &mut self.tonic_config;
let tonic_config: &mut TonicConfig = &mut self.tonic_config;

let endpoint = match env::var(signal_endpoint_var)
.ok()
Expand Down
10 changes: 6 additions & 4 deletions opentelemetry-otlp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,25 +211,27 @@ pub use crate::exporter::ExportConfig;
#[cfg(feature = "trace")]
pub use crate::span::{
OtlpTracePipeline, SpanExporter, SpanExporterBuilder, OTEL_EXPORTER_OTLP_TRACES_COMPRESSION,
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_TIMEOUT,
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_HEADERS,
OTEL_EXPORTER_OTLP_TRACES_TIMEOUT,
};

#[cfg(feature = "metrics")]
pub use crate::metric::{
MetricsExporter, MetricsExporterBuilder, OtlpMetricPipeline,
OTEL_EXPORTER_OTLP_METRICS_COMPRESSION, OTEL_EXPORTER_OTLP_METRICS_ENDPOINT,
OTEL_EXPORTER_OTLP_METRICS_TIMEOUT,
OTEL_EXPORTER_OTLP_METRICS_HEADERS, OTEL_EXPORTER_OTLP_METRICS_TIMEOUT,
};

#[cfg(feature = "logs")]
pub use crate::logs::{
LogExporter, LogExporterBuilder, OtlpLogPipeline, OTEL_EXPORTER_OTLP_LOGS_COMPRESSION,
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT, OTEL_EXPORTER_OTLP_LOGS_TIMEOUT,
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT, OTEL_EXPORTER_OTLP_LOGS_HEADERS,
OTEL_EXPORTER_OTLP_LOGS_TIMEOUT,
};

pub use crate::exporter::{
HasExportConfig, WithExportConfig, OTEL_EXPORTER_OTLP_COMPRESSION, OTEL_EXPORTER_OTLP_ENDPOINT,
OTEL_EXPORTER_OTLP_ENDPOINT_DEFAULT, OTEL_EXPORTER_OTLP_PROTOCOL,
OTEL_EXPORTER_OTLP_ENDPOINT_DEFAULT, OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_PROTOCOL,
OTEL_EXPORTER_OTLP_PROTOCOL_DEFAULT, OTEL_EXPORTER_OTLP_TIMEOUT,
OTEL_EXPORTER_OTLP_TIMEOUT_DEFAULT,
};
Expand Down
6 changes: 6 additions & 0 deletions opentelemetry-otlp/src/logs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ pub const OTEL_EXPORTER_OTLP_LOGS_ENDPOINT: &str = "OTEL_EXPORTER_OTLP_LOGS_ENDP
/// Maximum time the OTLP exporter will wait for each batch logs export.
pub const OTEL_EXPORTER_OTLP_LOGS_TIMEOUT: &str = "OTEL_EXPORTER_OTLP_LOGS_TIMEOUT";

/// Key-value pairs to be used as headers associated with gRPC or HTTP requests
/// for sending logs.
/// Example: `k1=v1,k2=v2`
/// Note: this is only supported for HTTP.
pub const OTEL_EXPORTER_OTLP_LOGS_HEADERS: &str = "OTEL_EXPORTER_OTLP_LOGS_HEADERS";

impl OtlpPipeline {
/// Create a OTLP logging pipeline.
pub fn logging(self) -> OtlpLogPipeline<NoExporterConfig> {
Expand Down
5 changes: 5 additions & 0 deletions opentelemetry-otlp/src/metric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ pub const OTEL_EXPORTER_OTLP_METRICS_ENDPOINT: &str = "OTEL_EXPORTER_OTLP_METRIC
pub const OTEL_EXPORTER_OTLP_METRICS_TIMEOUT: &str = "OTEL_EXPORTER_OTLP_METRICS_TIMEOUT";
/// Compression algorithm to use, defaults to none.
pub const OTEL_EXPORTER_OTLP_METRICS_COMPRESSION: &str = "OTEL_EXPORTER_OTLP_METRICS_COMPRESSION";
/// Key-value pairs to be used as headers associated with gRPC or HTTP requests
/// for sending metrics.
/// Example: `k1=v1,k2=v2`
/// Note: this is only supported for HTTP.
pub const OTEL_EXPORTER_OTLP_METRICS_HEADERS: &str = "OTEL_EXPORTER_OTLP_METRICS_HEADERS";
impl OtlpPipeline {
/// Create a OTLP metrics pipeline.
pub fn metrics<RT>(self, rt: RT) -> OtlpMetricPipeline<RT, NoExporterConfig>
Expand Down
5 changes: 5 additions & 0 deletions opentelemetry-otlp/src/span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ pub const OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: &str = "OTEL_EXPORTER_OTLP_TRACES_
pub const OTEL_EXPORTER_OTLP_TRACES_TIMEOUT: &str = "OTEL_EXPORTER_OTLP_TRACES_TIMEOUT";
/// Compression algorithm to use, defaults to none.
pub const OTEL_EXPORTER_OTLP_TRACES_COMPRESSION: &str = "OTEL_EXPORTER_OTLP_TRACES_COMPRESSION";
/// Key-value pairs to be used as headers associated with gRPC or HTTP requests
/// for sending spans.
/// Example: `k1=v1,k2=v2`
/// Note: this is only supported for HTTP.
pub const OTEL_EXPORTER_OTLP_TRACES_HEADERS: &str = "OTEL_EXPORTER_OTLP_TRACES_HEADERS";

impl OtlpPipeline {
/// Create a OTLP tracing pipeline.
Expand Down
Loading