1use crate::span::CandidateSpan;
3use crate::{ErrorKind, Result};
4use std::fmt::Debug;
5
6pub trait Sampler<T>: Debug {
8 fn is_sampled(&self, span: &CandidateSpan<T>) -> bool;
10
11 fn or<U>(self, other: U) -> OrSampler<Self, U>
13 where
14 Self: Sized,
15 U: Sampler<T>,
16 {
17 OrSampler(self, other)
18 }
19
20 fn and<U>(self, other: U) -> AndSampler<Self, U>
22 where
23 Self: Sized,
24 U: Sampler<T>,
25 {
26 AndSampler(self, other)
27 }
28
29 fn boxed(self) -> BoxSampler<T>
31 where
32 Self: Sized + Send + Sync + 'static,
33 {
34 Box::new(self)
35 }
36}
37impl<T> Sampler<T> for BoxSampler<T> {
38 fn is_sampled(&self, span: &CandidateSpan<T>) -> bool {
39 (**self).is_sampled(span)
40 }
41 fn boxed(self) -> BoxSampler<T>
42 where
43 Self: Sized + Send + 'static,
44 {
45 self
46 }
47}
48
49pub type BoxSampler<T> = Box<dyn Sampler<T> + Send + Sync + 'static>;
51
52#[derive(Debug, Clone)]
54pub struct ProbabilisticSampler {
55 sampling_rate: f64,
56}
57impl ProbabilisticSampler {
58 pub fn new(sampling_rate: f64) -> Result<Self> {
65 track_assert!(0.0 <= sampling_rate, ErrorKind::InvalidInput);
66 track_assert!(sampling_rate <= 1.0, ErrorKind::InvalidInput);
67 Ok(ProbabilisticSampler { sampling_rate })
68 }
69}
70impl<T> Sampler<T> for ProbabilisticSampler {
71 fn is_sampled(&self, _span: &CandidateSpan<T>) -> bool {
72 rand::random_range(0.0..1.0) < self.sampling_rate
73 }
74}
75
76#[derive(Debug, Clone)]
78pub struct PassiveSampler;
79impl<T> Sampler<T> for PassiveSampler {
80 fn is_sampled(&self, span: &CandidateSpan<T>) -> bool {
81 !span.references().is_empty()
82 }
83}
84
85#[derive(Debug, Clone)]
87pub struct NullSampler;
88impl<T> Sampler<T> for NullSampler {
89 fn is_sampled(&self, _span: &CandidateSpan<T>) -> bool {
90 false
91 }
92}
93
94#[derive(Debug, Clone)]
96pub struct AllSampler;
97impl<T> Sampler<T> for AllSampler {
98 fn is_sampled(&self, _span: &CandidateSpan<T>) -> bool {
99 true
100 }
101}
102
103#[derive(Debug, Clone)]
105pub struct OrSampler<A, B>(A, B);
106impl<A, B, T> Sampler<T> for OrSampler<A, B>
107where
108 A: Sampler<T>,
109 B: Sampler<T>,
110{
111 fn is_sampled(&self, span: &CandidateSpan<T>) -> bool {
112 self.0.is_sampled(span) || self.1.is_sampled(span)
113 }
114}
115
116#[derive(Debug, Clone)]
118pub struct AndSampler<A, B>(A, B);
119impl<A, B, T> Sampler<T> for AndSampler<A, B>
120where
121 A: Sampler<T>,
122 B: Sampler<T>,
123{
124 fn is_sampled(&self, span: &CandidateSpan<T>) -> bool {
125 self.0.is_sampled(span) && self.1.is_sampled(span)
126 }
127}