diff --git a/opentelemetry-sdk/CHANGELOG.md b/opentelemetry-sdk/CHANGELOG.md index aa67505013..f0f5f3ed8a 100644 --- a/opentelemetry-sdk/CHANGELOG.md +++ b/opentelemetry-sdk/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## to be released + +### Changed + +- *BREAKING* `struct`s which implement `ShouldSample` a.k.a Custom Samplers must now + implement `Clone`. This enables (#833) + ## v0.1.0 - SDK split from `opentelemetry` crate diff --git a/opentelemetry-sdk/src/trace/sampler.rs b/opentelemetry-sdk/src/trace/sampler.rs index 53a8707889..e936920f9e 100644 --- a/opentelemetry-sdk/src/trace/sampler.rs +++ b/opentelemetry-sdk/src/trace/sampler.rs @@ -66,7 +66,7 @@ use opentelemetry_http::HttpClient; /// [`SpanProcessor`]: crate::trace::SpanProcessor /// [`Span`]: opentelemetry_api::trace::Span /// [`Span::is_recording()`]: opentelemetry_api::trace::Span#tymethod.is_recording -pub trait ShouldSample: Send + Sync + std::fmt::Debug { +pub trait ShouldSample: CloneShouldSample + Send + Sync + std::fmt::Debug { /// Returns the [`SamplingDecision`] for a [`Span`] to be created. /// /// The [`should_sample`] function can use any of the information provided to it in order to @@ -88,6 +88,26 @@ pub trait ShouldSample: Send + Sync + std::fmt::Debug { ) -> SamplingResult; } +/// This trait should not be used directly instead users should use [`ShouldSample`]. +pub trait CloneShouldSample { + fn box_clone(&self) -> Box; +} + +impl CloneShouldSample for T +where + T: ShouldSample + Clone + 'static, +{ + fn box_clone(&self) -> Box { + Box::new(self.clone()) + } +} + +impl Clone for Box { + fn clone(&self) -> Self { + self.box_clone() + } +} + /// Default Sampling options /// /// The [built-in samplers] allow for simple decisions. For more complex scenarios consider @@ -102,7 +122,7 @@ pub enum Sampler { /// Never sample the trace AlwaysOff, /// Respects the parent span's sampling decision or delegates a delegate sampler for root spans. - ParentBased(Box), + ParentBased(Box), /// Sample a given fraction of traces. Fractions >= 1 will always sample. If the parent span is /// sampled, then it's child spans will automatically be sampled. Fractions < 0 are treated as /// zero, but spans may still be sampled if their parent is. @@ -357,6 +377,36 @@ mod tests { ); } } + #[test] + fn clone_a_parent_sampler() { + let sampler = Sampler::ParentBased(Box::new(Sampler::AlwaysOn)); + let cloned_sampler = sampler.clone(); + + let cx = Context::current_with_value("some_value"); + let instrumentation_library = InstrumentationLibrary::default(); + + let result = sampler.should_sample( + Some(&cx), + TraceId::from_u128(1), + "should sample", + &SpanKind::Internal, + &Default::default(), + &[], + &instrumentation_library, + ); + + let cloned_result = cloned_sampler.should_sample( + Some(&cx), + TraceId::from_u128(1), + "should sample", + &SpanKind::Internal, + &Default::default(), + &[], + &instrumentation_library, + ); + + assert_eq!(result, cloned_result); + } #[test] fn filter_parent_sampler_for_active_spans() { diff --git a/opentelemetry-sdk/src/trace/tracer.rs b/opentelemetry-sdk/src/trace/tracer.rs index 2852d621d7..92f9b1fb7d 100644 --- a/opentelemetry-sdk/src/trace/tracer.rs +++ b/opentelemetry-sdk/src/trace/tracer.rs @@ -306,7 +306,7 @@ mod tests { Context, Key, Value, }; - #[derive(Debug)] + #[derive(Clone, Debug)] struct TestSampler {} impl ShouldSample for TestSampler {