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
102
103
104
105
106
107
108
109
110
use crate::{
    metrics::{
        sync_instrument::{SyncBoundInstrument, SyncInstrument},
        Descriptor, InstrumentKind, Measurement, Meter, Number, NumberKind, Result, Unit,
    },
    KeyValue,
};
use std::marker;

/// A metric that accumulates values.
#[derive(Clone, Debug)]
pub struct Counter<T>(SyncInstrument<T>);

impl<T> Counter<T>
where
    T: Into<Number>,
{
    /// Creates a bound instrument for this counter. The labels are associated with
    /// values recorded via subsequent calls to record.
    pub fn bind<'a>(&self, labels: &'a [KeyValue]) -> BoundCounter<'a, T> {
        let bound_instrument = self.0.bind(labels);

        BoundCounter {
            labels,
            bound_instrument,
        }
    }

    /// Increment this counter by a given T
    pub fn add(&self, value: T, labels: &[KeyValue]) {
        self.0.direct_record(value.into(), labels)
    }

    /// Creates a Measurement for use with batch recording.
    pub fn measurement(&self, value: T) -> Measurement {
        Measurement::new(value.into(), self.0.instrument().clone())
    }
}

/// BoundCounter is a bound instrument for counters.
#[derive(Clone, Debug)]
pub struct BoundCounter<'a, T> {
    labels: &'a [KeyValue],
    bound_instrument: SyncBoundInstrument<T>,
}

impl<'a, T> BoundCounter<'a, T>
where
    T: Into<Number>,
{
    /// Increment this counter by a given T
    pub fn add(&self, value: T) {
        self.bound_instrument.direct_record(value.into())
    }
}

/// Configuration for building a counter.
#[derive(Debug)]
pub struct CounterBuilder<'a, T> {
    meter: &'a Meter,
    descriptor: Descriptor,
    _marker: marker::PhantomData<T>,
}

impl<'a, T> CounterBuilder<'a, T> {
    /// Create a new counter builder
    pub(crate) fn new(meter: &'a Meter, name: String, number_kind: NumberKind) -> Self {
        CounterBuilder {
            meter,
            descriptor: Descriptor::new(
                name,
                meter.instrumentation_library().name,
                meter.instrumentation_library().version,
                InstrumentKind::Counter,
                number_kind,
            ),
            _marker: marker::PhantomData,
        }
    }

    /// Set the description for this counter
    pub fn with_description<S: Into<String>>(mut self, description: S) -> Self {
        self.descriptor.set_description(description.into());
        self
    }

    /// Set the unit for this counter.
    pub fn with_unit(mut self, unit: Unit) -> Self {
        self.descriptor.config.unit = Some(unit);
        self
    }

    /// Creates a new counter instrument.
    pub fn try_init(self) -> Result<Counter<T>> {
        let instrument = self.meter.new_sync_instrument(self.descriptor)?;
        Ok(Counter(SyncInstrument::new(instrument)))
    }

    /// Creates a new counter instrument.
    ///
    /// # Panics
    ///
    /// This function panics if the instrument cannot be created. Use try_init if you want to
    /// handle errors.
    pub fn init(self) -> Counter<T> {
        Counter(SyncInstrument::new(
            self.meter.new_sync_instrument(self.descriptor).unwrap(),
        ))
    }
}