tracing-prof 0.3.0

Experimental library for profiling tracing spans.
Documentation
//! Probabilistic sampling of spans.

use std::cell::UnsafeCell;

use rand::{Rng, SeedableRng, rngs::SmallRng};

use super::HeadSampler;

thread_local! {
    /// A thread-local random number generator.
    static RNG: UnsafeCell<SmallRng> = UnsafeCell::new(SmallRng::from_rng(&mut rand::rng()));
}

/// A sampler that samples root spans based on probability.
#[derive(Debug)]
#[must_use]
pub struct ProbabilisticSampler {
    /// The probability of sampling a span.
    probability: f64,
}

impl ProbabilisticSampler {
    /// Creates a new `ProbabilisticSampler` with the given probability.
    ///
    /// The probability should be between 0.0 and 1.0.
    ///
    /// # Panics
    ///
    /// Panics if the probability is not in the range [0.0, 1.0].
    pub fn new(probability: f64) -> Self {
        assert!((0.0..=1.0).contains(&probability));
        Self { probability }
    }
}

impl HeadSampler for ProbabilisticSampler {
    #[inline]
    fn should_sample<S>(&self, span: &tracing_subscriber::registry::SpanRef<S>) -> bool
    where
        S: for<'a> tracing_subscriber::registry::LookupSpan<'a>,
    {
        // Sample the root span based on the probability.
        if span.parent().is_none() {
            RNG.try_with(|rng| {
                // SAFETY: We do not keep the mutable reference around.
                unsafe { rng.get().as_mut().unwrap().random_bool(self.probability) }
            })
            .unwrap_or(false)
        } else {
            // Children of sampled spans are always sampled.
            true
        }
    }
}