Skip to content

Commit

Permalink
parse OTLP endpoint address
Browse files Browse the repository at this point in the history
the endpoint address is often specified as host:port instead of a full
URL: https://github.com/open-telemetry/opentelemetry-collector/blob/main/exporter/otlpexporter/README.md#getting-started

Unfortunately, the url crate would parse 'collector:4317' as an URL with
the 'collector' scheme and no host. It also will not recognize
'IP:port'.

This adds a layer to URl parsing to recognize those cases, and configure
the HTTPS scheme manually
  • Loading branch information
Geoffroy Couprie committed Nov 17, 2021
1 parent 5cd9cdc commit c5553bb
Showing 1 changed file with 34 additions and 3 deletions.
37 changes: 34 additions & 3 deletions crates/apollo-router/src/configuration/otlp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::configuration::ConfigurationError;
use opentelemetry::sdk::resource::Resource;
use opentelemetry::sdk::trace::{Sampler, Tracer};
use opentelemetry_otlp::{Protocol, WithExportConfig};
use serde::{Deserialize, Serialize};
use serde::{Deserialize, Deserializer, Serialize};
use std::time::Duration;
use url::Url;

Expand Down Expand Up @@ -60,15 +60,15 @@ impl Tracing {
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(deny_unknown_fields, rename_all = "snake_case")]
pub struct ExportConfig {
pub endpoint: Option<Url>,
pub endpoint: Option<EndpointUrl>,
pub protocol: Option<Protocol>,
pub timeout: Option<u64>,
}

impl ExportConfig {
pub fn apply<T: WithExportConfig>(&self, mut exporter: T) -> T {
if let Some(url) = self.endpoint.as_ref() {
exporter = exporter.with_endpoint(url.as_str());
exporter = exporter.with_endpoint(url.endpoint.as_str());
}
if let Some(protocol) = self.protocol {
exporter = exporter.with_protocol(protocol);
Expand All @@ -80,6 +80,37 @@ impl ExportConfig {
}
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(transparent)]
pub struct EndpointUrl {
#[serde(deserialize_with = "endpoint_url")]
endpoint: Url,
}

fn endpoint_url<'de, D>(deserializer: D) -> Result<Url, D::Error>
where
D: Deserializer<'de>,
{
let mut buf = String::deserialize(deserializer)?;

// support the case of a IP:port endpoint
if buf.parse::<std::net::SocketAddr>().is_ok() {
buf = format!("https://{}", buf);
}

let mut url = Url::parse(&buf).map_err(serde::de::Error::custom)?;

// support the case of 'collector:4317' where url parses 'collector'
// as the scheme instead of the host
if url.host().is_none() && (url.scheme() != "http" || url.scheme() != "https") {
buf = format!("https://{}", buf);

url = Url::parse(&buf).map_err(serde::de::Error::custom)?;
}

Ok(url)
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct TraceConfig {
Expand Down

0 comments on commit c5553bb

Please sign in to comment.