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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
use crate::{
    metrics::{AsyncInstrument, AsyncInstrumentBuilder, InstrumentBuilder, MetricsError},
    KeyValue,
};
use core::fmt;
use std::any::Any;
use std::sync::Arc;

/// An SDK implemented instrument that records independent values
pub trait SyncGauge<T> {
    /// Records an independent value.
    fn record(&self, value: T, attributes: &[KeyValue]);
}

/// An instrument that records independent values
#[derive(Clone)]
pub struct Gauge<T>(Arc<dyn SyncGauge<T> + Send + Sync>);

impl<T> fmt::Debug for Gauge<T>
where
    T: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_fmt(format_args!("Gauge<{}>", std::any::type_name::<T>()))
    }
}

impl<T> Gauge<T> {
    /// Create a new gauge.
    pub fn new(inner: Arc<dyn SyncGauge<T> + Send + Sync>) -> Self {
        Gauge(inner)
    }

    /// Records an independent value.
    pub fn record(&self, value: T, attributes: &[KeyValue]) {
        self.0.record(value, attributes)
    }
}

impl TryFrom<InstrumentBuilder<'_, Gauge<u64>>> for Gauge<u64> {
    type Error = MetricsError;

    fn try_from(builder: InstrumentBuilder<'_, Gauge<u64>>) -> Result<Self, Self::Error> {
        builder
            .instrument_provider
            .u64_gauge(builder.name, builder.description, builder.unit)
    }
}

impl TryFrom<InstrumentBuilder<'_, Gauge<f64>>> for Gauge<f64> {
    type Error = MetricsError;

    fn try_from(builder: InstrumentBuilder<'_, Gauge<f64>>) -> Result<Self, Self::Error> {
        builder
            .instrument_provider
            .f64_gauge(builder.name, builder.description, builder.unit)
    }
}

impl TryFrom<InstrumentBuilder<'_, Gauge<i64>>> for Gauge<i64> {
    type Error = MetricsError;

    fn try_from(builder: InstrumentBuilder<'_, Gauge<i64>>) -> Result<Self, Self::Error> {
        builder
            .instrument_provider
            .i64_gauge(builder.name, builder.description, builder.unit)
    }
}

/// An async instrument that records independent readings.
#[derive(Clone)]
pub struct ObservableGauge<T>(Arc<dyn AsyncInstrument<T>>);

impl<T> fmt::Debug for ObservableGauge<T>
where
    T: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_fmt(format_args!(
            "ObservableGauge<{}>",
            std::any::type_name::<T>()
        ))
    }
}

impl<T> ObservableGauge<T> {
    /// Records the state of the instrument.
    ///
    /// It is only valid to call this within a callback. If called outside of the
    /// registered callback it should have no effect on the instrument, and an
    /// error will be reported via the error handler.
    pub fn observe(&self, measurement: T, attributes: &[KeyValue]) {
        self.0.observe(measurement, attributes)
    }

    /// Used by SDKs to downcast instruments in callbacks.
    pub fn as_any(&self) -> Arc<dyn Any> {
        self.0.as_any()
    }
}

impl<M> AsyncInstrument<M> for ObservableGauge<M> {
    fn observe(&self, measurement: M, attributes: &[KeyValue]) {
        self.observe(measurement, attributes)
    }

    fn as_any(&self) -> Arc<dyn Any> {
        self.0.as_any()
    }
}

impl<T> ObservableGauge<T> {
    /// Create a new gauge
    pub fn new(inner: Arc<dyn AsyncInstrument<T>>) -> Self {
        ObservableGauge(inner)
    }
}

impl TryFrom<AsyncInstrumentBuilder<'_, ObservableGauge<u64>, u64>> for ObservableGauge<u64> {
    type Error = MetricsError;

    fn try_from(
        builder: AsyncInstrumentBuilder<'_, ObservableGauge<u64>, u64>,
    ) -> Result<Self, Self::Error> {
        builder.meter.instrument_provider.u64_observable_gauge(
            builder.name,
            builder.description,
            builder.unit,
            builder.callbacks,
        )
    }
}

impl TryFrom<AsyncInstrumentBuilder<'_, ObservableGauge<f64>, f64>> for ObservableGauge<f64> {
    type Error = MetricsError;

    fn try_from(
        builder: AsyncInstrumentBuilder<'_, ObservableGauge<f64>, f64>,
    ) -> Result<Self, Self::Error> {
        builder.meter.instrument_provider.f64_observable_gauge(
            builder.name,
            builder.description,
            builder.unit,
            builder.callbacks,
        )
    }
}

impl TryFrom<AsyncInstrumentBuilder<'_, ObservableGauge<i64>, i64>> for ObservableGauge<i64> {
    type Error = MetricsError;

    fn try_from(
        builder: AsyncInstrumentBuilder<'_, ObservableGauge<i64>, i64>,
    ) -> Result<Self, Self::Error> {
        builder.meter.instrument_provider.i64_observable_gauge(
            builder.name,
            builder.description,
            builder.unit,
            builder.callbacks,
        )
    }
}