diff --git a/opentelemetry-datadog/CHANGELOG.md b/opentelemetry-datadog/CHANGELOG.md index 72ebfd3a..a10ee726 100644 --- a/opentelemetry-datadog/CHANGELOG.md +++ b/opentelemetry-datadog/CHANGELOG.md @@ -2,6 +2,13 @@ ## vNext +## v0.12.0 + +### Changed + +- Bump opentelemetry and opentelemetry_sdk version to 0.24 +- Bump hyper to version 1 + ## v0.10.0 ### Added @@ -17,7 +24,6 @@ - allow send all traces to `datadog-agent` with `agent-sampling` feature. - allow `datadog-agent` generate metrics from spans for [APM](https://docs.datadoghq.com/tracing/metrics/). - ## v0.9.0 ### Changed diff --git a/opentelemetry-datadog/Cargo.toml b/opentelemetry-datadog/Cargo.toml index 6dfce75f..0f7e51d2 100644 --- a/opentelemetry-datadog/Cargo.toml +++ b/opentelemetry-datadog/Cargo.toml @@ -1,14 +1,11 @@ [package] name = "opentelemetry-datadog" -version = "0.11.0" +version = "0.12.0" description = "Datadog exporters and propagators for OpenTelemetry" homepage = "https://github.com/open-telemetry/opentelemetry-rust-contrib/tree/main/opentelemetry-datadog" repository = "https://github.com/open-telemetry/opentelemetry-rust-contrib/tree/main/opentelemetry-datadog" readme = "README.md" -categories = [ - "development-tools::debugging", - "development-tools::profiling", -] +categories = ["development-tools::debugging", "development-tools::profiling"] keywords = ["opentelemetry", "tracing"] license = "Apache-2.0" edition = "2021" @@ -30,17 +27,17 @@ intern-std = [] [dependencies] indexmap = "2.0" once_cell = "1.12" -opentelemetry = { version = "0.23", features = ["trace"] } -opentelemetry_sdk = { version = "0.23", features = ["trace"] } -opentelemetry-http = {version = "0.12" } +opentelemetry = { version = "0.24", features = ["trace"] } +opentelemetry_sdk = { version = "0.24", features = ["trace"] } +opentelemetry-http = { version = "0.13" } opentelemetry-semantic-conventions = { workspace = true } rmp = "0.8" url = "2.2" -reqwest = { version = "0.11", default-features = false, optional = true } +reqwest = { version = "0.12", default-features = false, optional = true } surf = { version = "2.0", default-features = false, optional = true } thiserror = "1.0" itertools = "0.11" -http = "0.2" +http = "1" futures-core = "0.3" ryu = "1" itoa = "1" @@ -51,10 +48,13 @@ async-trait = "0.1" base64 = "0.13" bytes = "1" futures-util = { version = "0.3", default-features = false, features = ["io"] } -isahc = "1.4" -opentelemetry_sdk = {version = "0.23", features = ["trace", "testing"] } +opentelemetry_sdk = { version = "0.24", features = ["trace", "testing"] } criterion = "0.5" rand = "0.8" +hyper = "1" +hyper-util = { version = "0.1.6", features = ["client", "full"] } +hyperlocal = "0.9.1" +http-body-util = "0.1.2" [[bench]] name = "datadog_exporter" diff --git a/opentelemetry-datadog/benches/datadog_exporter.rs b/opentelemetry-datadog/benches/datadog_exporter.rs index c6887d7d..2d9b3dda 100644 --- a/opentelemetry-datadog/benches/datadog_exporter.rs +++ b/opentelemetry-datadog/benches/datadog_exporter.rs @@ -1,7 +1,4 @@ -use std::{ - borrow::Cow, - time::{Duration, SystemTime}, -}; +use std::time::{Duration, SystemTime}; use criterion::{black_box, criterion_group, criterion_main, Criterion}; use http::Request; @@ -14,7 +11,6 @@ use opentelemetry_http::HttpClient; use opentelemetry_sdk::{ export::trace::{SpanData, SpanExporter}, trace::{SpanEvents, SpanLinks}, - Resource, }; use rand::seq::SliceRandom; use rand::{rngs::ThreadRng, thread_rng, RngCore}; @@ -154,7 +150,6 @@ fn get_span(trace_id: u128, parent_span_id: u64, span_id: u64, rng: &mut ThreadR ]; let events = SpanEvents::default(); let links = SpanLinks::default(); - let resource = Resource::new(vec![KeyValue::new("host.name", "test")]); let instrumentation_lib = InstrumentationLibrary::builder("component").build(); SpanData { @@ -169,7 +164,6 @@ fn get_span(trace_id: u128, parent_span_id: u64, span_id: u64, rng: &mut ThreadR events, links, status: Status::Ok, - resource: Cow::Owned(resource), instrumentation_lib, } } diff --git a/opentelemetry-datadog/examples/agent_sampling.rs b/opentelemetry-datadog/examples/agent_sampling.rs index 4b0b6ea0..8e5667c3 100644 --- a/opentelemetry-datadog/examples/agent_sampling.rs +++ b/opentelemetry-datadog/examples/agent_sampling.rs @@ -54,7 +54,7 @@ fn main() -> Result<(), Box> { .with_service_name("agent-sampling-demo") .with_api_version(ApiVersion::Version05) .with_trace_config( - trace::config() + trace::Config::default() .with_sampler(AgentBasedSampler) .with_id_generator(RandomIdGenerator::default()), ) diff --git a/opentelemetry-datadog/src/exporter/mod.rs b/opentelemetry-datadog/src/exporter/mod.rs index 001008c2..97b1ff42 100644 --- a/opentelemetry-datadog/src/exporter/mod.rs +++ b/opentelemetry-datadog/src/exporter/mod.rs @@ -68,6 +68,7 @@ pub struct DatadogExporter { api_version: ApiVersion, mapping: Mapping, unified_tags: UnifiedTags, + resource: Option, } impl DatadogExporter { @@ -86,6 +87,7 @@ impl DatadogExporter { api_version, mapping, unified_tags, + resource: None, } } @@ -100,6 +102,7 @@ impl DatadogExporter { traces, &self.mapping, &self.unified_tags, + self.resource.as_ref(), )?; let req = Request::builder() .method(Method::POST) @@ -219,10 +222,9 @@ impl DatadogPipelineBuilder { )); cfg } else { - Config { - resource: Cow::Owned(Resource::empty()), - ..Default::default() - } + let mut cfg = Config::default(); + cfg.resource = Cow::Owned(Resource::empty()); + cfg }; (config, service_name) } else { @@ -231,14 +233,10 @@ impl DatadogPipelineBuilder { .get(semcov::resource::SERVICE_NAME.into()) .unwrap() .to_string(); - ( - Config { - // use a empty resource to prevent TracerProvider to assign a service name. - resource: Cow::Owned(Resource::empty()), - ..Default::default() - }, - service_name, - ) + let mut cfg = Config::default(); + // use a empty resource to prevent TracerProvider to assign a service name. + cfg.resource = Cow::Owned(Resource::empty()); + (cfg, service_name) } } @@ -438,6 +436,9 @@ impl SpanExporter for DatadogExporter { let client = self.client.clone(); Box::pin(send_request(client, request)) } + fn set_resource(&mut self, resource: &Resource) { + self.resource = Some(resource.clone()); + } } /// Helper struct to custom the mapping between Opentelemetry spans and datadog spans. diff --git a/opentelemetry-datadog/src/exporter/model/mod.rs b/opentelemetry-datadog/src/exporter/model/mod.rs index 715580b5..aeabc453 100644 --- a/opentelemetry-datadog/src/exporter/model/mod.rs +++ b/opentelemetry-datadog/src/exporter/model/mod.rs @@ -1,8 +1,11 @@ use crate::exporter::ModelConfig; use http::uri; -use opentelemetry_sdk::export::{ - trace::{self, SpanData}, - ExportError, +use opentelemetry_sdk::{ + export::{ + trace::{self, SpanData}, + ExportError, + }, + Resource, }; use std::fmt::Debug; use url::ParseError; @@ -150,6 +153,7 @@ impl ApiVersion { traces: Vec<&[trace::SpanData]>, mapping: &Mapping, unified_tags: &UnifiedTags, + resource: Option<&Resource>, ) -> Result, Error> { match self { Self::Version03 => v03::encode( @@ -167,6 +171,7 @@ impl ApiVersion { Some(f) => f(span, config), None => default_resource_mapping(span, config), }, + resource, ), Self::Version05 => v05::encode( model_config, @@ -184,6 +189,7 @@ impl ApiVersion { None => default_resource_mapping(span, config), }, unified_tags, + resource, ), } } @@ -199,9 +205,8 @@ pub(crate) mod tests { use opentelemetry_sdk::{ self, trace::{SpanEvents, SpanLinks}, - InstrumentationLibrary, Resource, + InstrumentationLibrary, }; - use std::borrow::Cow; use std::time::{Duration, SystemTime}; fn get_traces() -> Vec> { @@ -223,7 +228,6 @@ pub(crate) mod tests { let attributes = vec![KeyValue::new("span.type", "web")]; let events = SpanEvents::default(); let links = SpanLinks::default(); - let resource = Resource::new(vec![KeyValue::new("host.name", "test")]); let instrumentation_lib = InstrumentationLibrary::builder("component").build(); trace::SpanData { @@ -238,7 +242,6 @@ pub(crate) mod tests { events, links, status: Status::Ok, - resource: Cow::Owned(resource), instrumentation_lib, } } @@ -250,11 +253,13 @@ pub(crate) mod tests { service_name: "service_name".to_string(), ..Default::default() }; + let resource = Resource::new(vec![KeyValue::new("host.name", "test")]); let encoded = base64::encode(ApiVersion::Version03.encode( &model_config, traces.iter().map(|x| &x[..]).collect(), &Mapping::empty(), &UnifiedTags::new(), + Some(&resource), )?); assert_eq!(encoded.as_str(), "kZGMpHR5cGWjd2Vip3NlcnZpY2Wsc2VydmljZV9uYW1lpG5hbWWpY29tcG9uZW\ @@ -272,6 +277,7 @@ pub(crate) mod tests { service_name: "service_name".to_string(), ..Default::default() }; + let resource = Resource::new(vec![KeyValue::new("host.name", "test")]); let mut unified_tags = UnifiedTags::new(); unified_tags.set_env(Some(String::from("test-env"))); @@ -283,6 +289,7 @@ pub(crate) mod tests { traces.iter().map(|x| &x[..]).collect(), &Mapping::empty(), &unified_tags, + Some(&resource), )?); // TODO: Need someone to generate the expected result or instructions to do so. diff --git a/opentelemetry-datadog/src/exporter/model/v03.rs b/opentelemetry-datadog/src/exporter/model/v03.rs index 5def2ef8..0cbba9c1 100644 --- a/opentelemetry-datadog/src/exporter/model/v03.rs +++ b/opentelemetry-datadog/src/exporter/model/v03.rs @@ -2,6 +2,7 @@ use crate::exporter::model::{Error, SAMPLING_PRIORITY_KEY}; use crate::exporter::ModelConfig; use opentelemetry::trace::Status; use opentelemetry_sdk::export::trace::SpanData; +use opentelemetry_sdk::Resource; use std::time::SystemTime; pub(crate) fn encode( @@ -10,6 +11,7 @@ pub(crate) fn encode( get_service_name: S, get_name: N, get_resource: R, + resource: Option<&Resource>, ) -> Result, Error> where for<'a> S: Fn(&'a SpanData, &'a ModelConfig) -> &'a str, @@ -97,11 +99,13 @@ where rmp::encode::write_str(&mut encoded, "meta")?; rmp::encode::write_map_len( &mut encoded, - (span.attributes.len() + span.resource.len()) as u32, + (span.attributes.len() + resource.map(|r| r.len()).unwrap_or(0)) as u32, )?; - for (key, value) in span.resource.iter() { - rmp::encode::write_str(&mut encoded, key.as_str())?; - rmp::encode::write_str(&mut encoded, value.as_str().as_ref())?; + if let Some(resource) = resource { + for (key, value) in resource.iter() { + rmp::encode::write_str(&mut encoded, key.as_str())?; + rmp::encode::write_str(&mut encoded, value.as_str().as_ref())?; + } } for kv in span.attributes.iter() { rmp::encode::write_str(&mut encoded, kv.key.as_str())?; diff --git a/opentelemetry-datadog/src/exporter/model/v05.rs b/opentelemetry-datadog/src/exporter/model/v05.rs index 68b603cd..ef3080a5 100644 --- a/opentelemetry-datadog/src/exporter/model/v05.rs +++ b/opentelemetry-datadog/src/exporter/model/v05.rs @@ -4,6 +4,7 @@ use crate::exporter::{Error, ModelConfig}; use crate::propagator::DatadogTraceState; use opentelemetry::trace::Status; use opentelemetry_sdk::export::trace::SpanData; +use opentelemetry_sdk::Resource; use std::time::SystemTime; use super::unified_tags::{UnifiedTagField, UnifiedTags}; @@ -74,6 +75,7 @@ pub(crate) fn encode( get_name: N, get_resource: R, unified_tags: &UnifiedTags, + resource: Option<&Resource>, ) -> Result, Error> where for<'a> S: Fn(&'a SpanData, &'a ModelConfig) -> &'a str, @@ -89,6 +91,7 @@ where get_resource, &traces, unified_tags, + resource, )?; let mut payload = Vec::with_capacity(traces.len() * 512); @@ -146,6 +149,7 @@ fn get_measuring(span: &SpanData) -> f64 { } } +#[allow(clippy::too_many_arguments)] fn encode_traces<'interner, S, N, R>( interner: &mut StringInterner<'interner>, model_config: &'interner ModelConfig, @@ -154,6 +158,7 @@ fn encode_traces<'interner, S, N, R>( get_resource: R, traces: &'interner [&[SpanData]], unified_tags: &'interner UnifiedTags, + resource: Option<&'interner Resource>, ) -> Result, Error> where for<'a> S: Fn(&'a SpanData, &'a ModelConfig) -> &'a str, @@ -223,13 +228,15 @@ where rmp::encode::write_map_len( &mut encoded, - (span.attributes.len() + span.resource.len()) as u32 + (span.attributes.len() + resource.map(|r| r.len()).unwrap_or(0)) as u32 + unified_tags.compute_attribute_size() + GIT_META_TAGS_COUNT, )?; - for (key, value) in span.resource.iter() { - rmp::encode::write_u32(&mut encoded, interner.intern(key.as_str()))?; - rmp::encode::write_u32(&mut encoded, interner.intern_value(value))?; + if let Some(resource) = resource { + for (key, value) in resource.iter() { + rmp::encode::write_u32(&mut encoded, interner.intern(key.as_str()))?; + rmp::encode::write_u32(&mut encoded, interner.intern_value(value))?; + } } write_unified_tags(&mut encoded, interner, unified_tags)?; diff --git a/opentelemetry-datadog/src/lib.rs b/opentelemetry-datadog/src/lib.rs index e3a42cb0..1d472ed4 100644 --- a/opentelemetry-datadog/src/lib.rs +++ b/opentelemetry-datadog/src/lib.rs @@ -90,25 +90,27 @@ //! use bytes::Bytes; //! use futures_util::io::AsyncReadExt as _; //! use http::{Request, Response}; +//! use http_body_util::BodyExt; //! use std::convert::TryInto as _; //! //! // `reqwest` and `surf` are supported through features, if you prefer an //! // alternate http client you can add support by implementing `HttpClient` as //! // shown here. //! #[derive(Debug)] -//! struct IsahcClient(isahc::HttpClient); +//! struct HyperClient(hyper_util::client::legacy::Client>); //! //! #[async_trait] -//! impl HttpClient for IsahcClient { +//! impl HttpClient for HyperClient { //! async fn send(&self, request: Request>) -> Result, HttpError> { -//! let mut response = self.0.send_async(request).await?; +//! let (parts, body) = request.into_parts(); +//! let request = hyper::Request::from_parts(parts, body.into()); +//! let mut response = self.0.request(request).await?; //! let status = response.status(); -//! let mut bytes = Vec::with_capacity(response.body().len().unwrap_or(0).try_into()?); -//! isahc::AsyncReadResponseExt::copy_to(&mut response, &mut bytes).await?; //! +//! let body = response.into_body().collect().await?; //! Ok(Response::builder() -//! .status(response.status()) -//! .body(bytes.into())?) +//! .status(status) +//! .body(body.to_bytes().into())?) //! } //! } //! diff --git a/opentelemetry-etw-logs/src/logs/exporter.rs b/opentelemetry-etw-logs/src/logs/exporter.rs index 777c9ac1..ab14a052 100644 --- a/opentelemetry-etw-logs/src/logs/exporter.rs +++ b/opentelemetry-etw-logs/src/logs/exporter.rs @@ -397,7 +397,7 @@ fn add_attribute_to_event(event: &mut tld::EventBuilder, key: &Key, value: &AnyV AnyValue::ListAny(l) => { event.add_str8( key.as_str(), - &l.as_json_value().to_string(), + l.as_json_value().to_string(), tld::OutType::Json, 0, ); @@ -405,7 +405,7 @@ fn add_attribute_to_event(event: &mut tld::EventBuilder, key: &Key, value: &AnyV AnyValue::Map(m) => { event.add_str8( key.as_str(), - &m.as_json_value().to_string(), + m.as_json_value().to_string(), tld::OutType::Json, 0, ); diff --git a/opentelemetry-resource-detectors/src/process.rs b/opentelemetry-resource-detectors/src/process.rs index 52d78804..496ba403 100644 --- a/opentelemetry-resource-detectors/src/process.rs +++ b/opentelemetry-resource-detectors/src/process.rs @@ -14,7 +14,7 @@ use std::time::Duration; /// This resource detector returns the following information: /// /// - process command line arguments(`process.command_args`), the full command arguments of this -/// application. +/// application. /// - OS assigned process id(`process.pid`). pub struct ProcessResourceDetector; diff --git a/opentelemetry-stackdriver/src/lib.rs b/opentelemetry-stackdriver/src/lib.rs index 08c9682a..7569cc6a 100644 --- a/opentelemetry-stackdriver/src/lib.rs +++ b/opentelemetry-stackdriver/src/lib.rs @@ -4,6 +4,7 @@ // When this PR is merged we should be able to remove this attribute: // https://github.com/danburkert/prost/pull/291 #![allow( + clippy::doc_lazy_continuation, deprecated, rustdoc::bare_urls, rustdoc::broken_intra_doc_links, diff --git a/opentelemetry-user-events-logs/src/logs/exporter.rs b/opentelemetry-user-events-logs/src/logs/exporter.rs index 1e7f5861..cb0eafda 100644 --- a/opentelemetry-user-events-logs/src/logs/exporter.rs +++ b/opentelemetry-user-events-logs/src/logs/exporter.rs @@ -119,7 +119,7 @@ impl UserEventsExporter { eb.add_value(field_name, f, FieldFormat::Float, 0); } AnyValue::String(s) => { - eb.add_str(field_name, &s.to_string(), FieldFormat::Default, 0); + eb.add_str(field_name, s.to_string(), FieldFormat::Default, 0); } _ => (), }