1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
use crate::{group, EventGroup, Histogram, SpanGroup, TimingSubscriber};
use std::hash::Hash;

/// Builder for [`TimingSubscriber`] instances.
///
/// This type implements the [builder pattern]. It lets you easily configure and construct a new
/// [`TimingSubscriber`] subscriber. See the individual methods for details. To start, use
/// [`Builder::from`]:
///
/// ```rust
/// use tracing_timing::{Builder, Histogram};
/// let builder = Builder::from(|| Histogram::new(3).unwrap());
/// let subscriber = builder.build();
/// ```
///
/// See the various `new_*` methods on [`Histogram`] for how to construct an appropriate histogram
/// in the first place. All samples recorded by the subscriber returned from [`Builder::build`]
/// will be recorded into histograms as returned by the provided constructor.
///
///   [builder pattern]: https://rust-lang-nursery.github.io/api-guidelines/type-safety.html#c-builder
pub struct Builder<NH, S = group::ByName, E = group::ByMessage> {
    span_group: S,
    event_group: E,
    time: quanta::Clock,
    new_histogram: NH,
}

impl<NH> From<NH> for Builder<NH, group::ByName, group::ByMessage> {
    fn from(new_histogram: NH) -> Self {
        Builder {
            span_group: Default::default(),
            event_group: Default::default(),
            time: quanta::Clock::new(),
            new_histogram,
        }
    }
}

impl<NH, S, E> Builder<NH, S, E> {
    /// Set the mechanism used to divide spans into groups.
    ///
    /// See [`SpanGroup`] and the [`group`] module for details.
    pub fn spans<S2>(self, span_group: S2) -> Builder<NH, S2, E> {
        Builder {
            span_group,
            event_group: self.event_group,
            time: self.time,
            new_histogram: self.new_histogram,
        }
    }

    /// Set the mechanism used to divide events into per-span groups.
    ///
    /// See [`EventGroup`] and the [`group`] module for details.
    pub fn events<E2>(self, event_group: E2) -> Builder<NH, S, E2> {
        Builder {
            span_group: self.span_group,
            event_group,
            time: self.time,
            new_histogram: self.new_histogram,
        }
    }

    /// Set the time source to use for time measurements.
    pub fn time(mut self, time: quanta::Clock) -> Builder<NH, S, E> {
        self.time = time;
        self
    }

    /// Construct a [`TimingSubscriber`] as configured.
    pub fn build(self) -> TimingSubscriber<NH, S, E>
    where
        S: SpanGroup,
        E: EventGroup,
        S::Id: Hash + Eq,
        E::Id: Hash + Eq,
        NH: FnMut() -> Histogram<u64>,
    {
        let (tx, rx) = crossbeam::channel::unbounded();
        TimingSubscriber {
            span_group: self.span_group,
            event_group: self.event_group,
            time: self.time,
            reader: super::ReaderState {
                created: rx,
                histograms: Default::default(),
            }
            .into(),
            writers: super::WriterState {
                last_event: Default::default(),
                refcount: Default::default(),
                spans: Default::default(),
                tls: Default::default(),
                idle_recorders: Default::default(),
                new_histogram: self.new_histogram,
                created: tx,
            }
            .into(),
        }
    }
}