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

feat: add default resource in TracerProvider if user didn't provide one. #571

Merged
merged 13 commits into from
Jun 19, 2021
Merged
1 change: 1 addition & 0 deletions opentelemetry-datadog/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ async-trait = "0.1"
indexmap = "1.6"
opentelemetry = { version = "0.15", path = "../opentelemetry", features = ["trace"] }
opentelemetry-http = { version = "0.4", path = "../opentelemetry-http" }
opentelemetry-semantic-conventions = { version = "0.7.0", path = "../opentelemetry-semantic-conventions" }
rmp = "0.8"
reqwest = { version = "0.11", default-features = false, optional = true }
surf = { version = "2.0", default-features = false, optional = true }
Expand Down
87 changes: 67 additions & 20 deletions opentelemetry-datadog/src/exporter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,20 @@ use http::{Method, Request, Uri};
use itertools::Itertools;
use opentelemetry::sdk::export::trace;
use opentelemetry::sdk::export::trace::SpanData;
use opentelemetry::sdk::trace::TraceRuntime;
use opentelemetry::sdk::resource::ResourceDetector;
use opentelemetry::sdk::resource::SdkProvidedResourceDetector;
use opentelemetry::sdk::trace::{Config, TraceRuntime};
use opentelemetry::sdk::Resource;
use opentelemetry::trace::TraceError;
use opentelemetry::{global, sdk, trace::TracerProvider};
use opentelemetry::{global, sdk, trace::TracerProvider, KeyValue};
use opentelemetry_http::{HttpClient, ResponseExt};
use opentelemetry_semantic_conventions as semcov;
use std::sync::Arc;
use std::time::Duration;

/// Default Datadog collector endpoint
const DEFAULT_AGENT_ENDPOINT: &str = "http://127.0.0.1:8126";

/// Default service name if no service is configured.
const DEFAULT_SERVICE_NAME: &str = "OpenTelemetry";

/// Header name used to inform the Datadog agent of the number of traces in the payload
const DATADOG_TRACE_COUNT_HEADER: &str = "X-Datadog-Trace-Count";

Expand Down Expand Up @@ -56,7 +59,7 @@ pub fn new_pipeline() -> DatadogPipelineBuilder {
/// Builder for `ExporterConfig` struct.
#[derive(Debug)]
pub struct DatadogPipelineBuilder {
service_name: String,
service_name: Option<String>,
agent_endpoint: String,
trace_config: Option<sdk::trace::Config>,
version: ApiVersion,
Expand All @@ -66,7 +69,7 @@ pub struct DatadogPipelineBuilder {
impl Default for DatadogPipelineBuilder {
fn default() -> Self {
DatadogPipelineBuilder {
service_name: DEFAULT_SERVICE_NAME.to_string(),
service_name: None,
agent_endpoint: DEFAULT_AGENT_ENDPOINT.to_string(),
trace_config: None,
version: ApiVersion::Version05,
Expand Down Expand Up @@ -95,11 +98,59 @@ impl Default for DatadogPipelineBuilder {
}

impl DatadogPipelineBuilder {
fn build_exporter(self) -> Result<DatadogExporter, TraceError> {
/// Building a new exporter.
///
/// This is useful if you are manually constructing a pipeline.
pub fn build_exporter(mut self) -> Result<DatadogExporter, TraceError> {
let (_, service_name) = self.build_config_and_service_name();
self.build_exporter_with_service_name(service_name)
}

fn build_config_and_service_name(&mut self) -> (Config, String) {
let service_name = self.service_name.take();
if let Some(service_name) = service_name {
let config = if let Some(mut cfg) = self.trace_config.take() {
cfg.resource = cfg.resource.map(|r| {
let without_service_name = r
.iter()
.filter(|(k, _v)| **k != semcov::resource::SERVICE_NAME)
.map(|(k, v)| KeyValue::new(k.clone(), v.clone()))
.collect::<Vec<KeyValue>>();
Arc::new(Resource::new(without_service_name))
});
cfg
} else {
Config {
resource: Some(Arc::new(Resource::empty())),
..Default::default()
}
};
(config, service_name)
} else {
let service_name = SdkProvidedResourceDetector
.detect(Duration::from_secs(0))
.get(semcov::resource::SERVICE_NAME)
.unwrap()
.to_string();
(
Config {
// use a empty resource to prevent TracerProvider to assign a service name.
resource: Some(Arc::new(Resource::empty())),
..Default::default()
},
service_name,
)
}
}

fn build_exporter_with_service_name(
self,
service_name: String,
) -> Result<DatadogExporter, TraceError> {
if let Some(client) = self.client {
let endpoint = self.agent_endpoint + self.version.path();
let exporter = DatadogExporter::new(
self.service_name,
service_name,
endpoint.parse().map_err::<Error, _>(Into::into)?,
self.version,
client,
Expand All @@ -112,13 +163,11 @@ impl DatadogPipelineBuilder {

/// Install the Datadog trace exporter pipeline using a simple span processor.
pub fn install_simple(mut self) -> Result<sdk::trace::Tracer, TraceError> {
let trace_config = self.trace_config.take();
let exporter = self.build_exporter()?;
let (config, service_name) = self.build_config_and_service_name();
let exporter = self.build_exporter_with_service_name(service_name)?;
let mut provider_builder =
sdk::trace::TracerProvider::builder().with_simple_exporter(exporter);
if let Some(config) = trace_config {
provider_builder = provider_builder.with_config(config);
}
provider_builder = provider_builder.with_config(config);
let provider = provider_builder.build();
let tracer = provider.get_tracer("opentelemetry-datadog", Some(env!("CARGO_PKG_VERSION")));
let _ = global::set_tracer_provider(provider);
Expand All @@ -131,13 +180,11 @@ impl DatadogPipelineBuilder {
mut self,
runtime: R,
) -> Result<sdk::trace::Tracer, TraceError> {
let trace_config = self.trace_config.take();
let exporter = self.build_exporter()?;
let (config, service_name) = self.build_config_and_service_name();
let exporter = self.build_exporter_with_service_name(service_name)?;
let mut provider_builder =
sdk::trace::TracerProvider::builder().with_batch_exporter(exporter, runtime);
if let Some(config) = trace_config {
provider_builder = provider_builder.with_config(config);
}
provider_builder = provider_builder.with_config(config);
let provider = provider_builder.build();
let tracer = provider.get_tracer("opentelemetry-datadog", Some(env!("CARGO_PKG_VERSION")));
let _ = global::set_tracer_provider(provider);
Expand All @@ -146,7 +193,7 @@ impl DatadogPipelineBuilder {

/// Assign the service name under which to group traces
pub fn with_service_name<T: Into<String>>(mut self, name: T) -> Self {
self.service_name = name.into();
self.service_name = Some(name.into());
self
}

Expand Down
1 change: 1 addition & 0 deletions opentelemetry-jaeger/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ futures-util = { version = "0.3", optional = true }
http = { version = "0.2", optional = true }
isahc = { version = "1.4", default-features = false, optional = true }
js-sys = { version = "0.3", optional = true }
opentelemetry-semantic-conventions = { version = "0.7.0", path = "../opentelemetry-semantic-conventions" }
opentelemetry = { version = "0.15", default-features = false, features = ["trace"], path = "../opentelemetry" }
opentelemetry-http = { version = "0.4", path = "../opentelemetry-http", optional = true }
pin-project = { version = "1.0", optional = true }
Expand Down
7 changes: 0 additions & 7 deletions opentelemetry-jaeger/src/exporter/env.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use crate::PipelineBuilder;
use std::env;

/// The name under which Jaeger will group reported spans.
const ENV_SERVICE_NAME: &str = "OTEL_SERVICE_NAME";

/// The hostname for the Jaeger agent.
/// e.g. "localhost"
const ENV_AGENT_HOST: &str = "OTEL_EXPORTER_JAEGER_AGENT_HOST";
Expand All @@ -27,10 +24,6 @@ const ENV_PASSWORD: &str = "OTEL_EXPORTER_JAEGER_PASSWORD";

/// Assign builder attributes from env
pub(crate) fn assign_attrs(mut builder: PipelineBuilder) -> PipelineBuilder {
if let Some(service_name) = env::var(ENV_SERVICE_NAME).ok().filter(|v| !v.is_empty()) {
builder = builder.with_service_name(service_name);
}

if let (Ok(host), Ok(port)) = (env::var(ENV_AGENT_HOST), env::var(ENV_AGENT_PORT)) {
builder = builder.with_agent_endpoint(format!("{}:{}", host.trim(), port.trim()));
}
Expand Down
Loading