Skip to main content

prometheus_client/
encoding.rs

1//! Exposition format implementations.
2
3pub use prometheus_client_derive_encode::*;
4
5use crate::metrics::exemplar::Exemplar;
6use crate::metrics::MetricType;
7use crate::registry::{Prefix, Unit};
8use std::borrow::Cow;
9use std::collections::HashMap;
10use std::fmt::Write;
11use std::ops::Deref;
12use std::rc::Rc;
13use std::sync::Arc;
14use std::time::{SystemTime, UNIX_EPOCH};
15
16#[cfg(feature = "protobuf")]
17#[cfg_attr(docsrs, doc(cfg(feature = "protobuf")))]
18pub mod protobuf;
19pub mod text;
20
21macro_rules! for_both_mut {
22    ($self:expr, $inner:ident, $pattern:pat, $fn:expr) => {
23        match &mut $self.0 {
24            $inner::Text($pattern) => $fn,
25            #[cfg(feature = "protobuf")]
26            $inner::Protobuf($pattern) => $fn,
27        }
28    };
29}
30
31macro_rules! for_both {
32    ($self:expr, $inner:ident, $pattern:pat, $fn:expr) => {
33        match $self.0 {
34            $inner::Text($pattern) => $fn,
35            #[cfg(feature = "protobuf")]
36            $inner::Protobuf($pattern) => $fn,
37        }
38    };
39}
40
41/// Trait implemented by each metric type, e.g.
42/// [`Counter`](crate::metrics::counter::Counter), to implement its encoding in
43/// the OpenMetric text format.
44pub trait EncodeMetric {
45    /// Encode the given instance in the OpenMetrics text encoding.
46    // TODO: Lifetimes on MetricEncoder needed?
47    fn encode(&self, encoder: MetricEncoder) -> Result<(), std::fmt::Error>;
48
49    /// The OpenMetrics metric type of the instance.
50    // One can not use [`TypedMetric`] directly, as associated constants are not
51    // object safe and thus can not be used with dynamic dispatching.
52    fn metric_type(&self) -> MetricType;
53
54    /// Check if the metric is empty.
55    ///
56    /// An empty metric is a metric that has no data to encode, and thus should not have any
57    /// descriptor in the final output.
58    ///
59    /// By default, this returns `false`, ensuring the metric and its description is always
60    /// encoded.
61    fn is_empty(&self) -> bool {
62        false
63    }
64}
65
66impl EncodeMetric for Box<dyn EncodeMetric> {
67    fn encode(&self, encoder: MetricEncoder) -> Result<(), std::fmt::Error> {
68        self.deref().encode(encoder)
69    }
70
71    fn metric_type(&self) -> MetricType {
72        self.deref().metric_type()
73    }
74}
75
76/// Encoder for a Metric Descriptor.
77#[derive(Debug)]
78pub struct DescriptorEncoder<'a>(DescriptorEncoderInner<'a>);
79
80#[derive(Debug)]
81enum DescriptorEncoderInner<'a> {
82    Text(text::DescriptorEncoder<'a>),
83
84    #[cfg(feature = "protobuf")]
85    Protobuf(protobuf::DescriptorEncoder<'a>),
86}
87
88impl<'a> From<text::DescriptorEncoder<'a>> for DescriptorEncoder<'a> {
89    fn from(e: text::DescriptorEncoder<'a>) -> Self {
90        Self(DescriptorEncoderInner::Text(e))
91    }
92}
93
94#[cfg(feature = "protobuf")]
95impl<'a> From<protobuf::DescriptorEncoder<'a>> for DescriptorEncoder<'a> {
96    fn from(e: protobuf::DescriptorEncoder<'a>) -> Self {
97        Self(DescriptorEncoderInner::Protobuf(e))
98    }
99}
100
101impl DescriptorEncoder<'_> {
102    pub(crate) fn with_prefix_and_labels<'s>(
103        &'s mut self,
104        prefix: Option<&'s Prefix>,
105        labels: &'s [(Cow<'static, str>, Cow<'static, str>)],
106        // TODO: result needed?
107    ) -> DescriptorEncoder<'s> {
108        for_both_mut!(
109            self,
110            DescriptorEncoderInner,
111            e,
112            e.with_prefix_and_labels(prefix, labels).into()
113        )
114    }
115
116    /// Encode a descriptor.
117    pub fn encode_descriptor<'s>(
118        &'s mut self,
119        name: &'s str,
120        help: &str,
121        unit: Option<&'s Unit>,
122        metric_type: MetricType,
123    ) -> Result<MetricEncoder<'s>, std::fmt::Error> {
124        for_both_mut!(
125            self,
126            DescriptorEncoderInner,
127            e,
128            Ok(e.encode_descriptor(name, help, unit, metric_type)?.into())
129        )
130    }
131}
132
133/// Encoder for a metric.
134#[derive(Debug)]
135pub struct MetricEncoder<'a>(MetricEncoderInner<'a>);
136
137#[derive(Debug)]
138enum MetricEncoderInner<'a> {
139    Text(text::MetricEncoder<'a>),
140
141    #[cfg(feature = "protobuf")]
142    Protobuf(protobuf::MetricEncoder<'a>),
143}
144
145impl<'a> From<text::MetricEncoder<'a>> for MetricEncoder<'a> {
146    fn from(e: text::MetricEncoder<'a>) -> Self {
147        Self(MetricEncoderInner::Text(e))
148    }
149}
150
151#[cfg(feature = "protobuf")]
152impl<'a> From<protobuf::MetricEncoder<'a>> for MetricEncoder<'a> {
153    fn from(e: protobuf::MetricEncoder<'a>) -> Self {
154        Self(MetricEncoderInner::Protobuf(e))
155    }
156}
157
158impl MetricEncoder<'_> {
159    /// Encode a counter.
160    pub fn encode_counter<
161        S: EncodeLabelSet,
162        CounterValue: EncodeCounterValue,
163        ExemplarValue: EncodeExemplarValue,
164    >(
165        &mut self,
166        v: &CounterValue,
167        exemplar: Option<&Exemplar<S, ExemplarValue>>,
168    ) -> Result<(), std::fmt::Error> {
169        for_both_mut!(self, MetricEncoderInner, e, e.encode_counter(v, exemplar))
170    }
171
172    /// Encode a gauge.
173    pub fn encode_gauge<GaugeValue: EncodeGaugeValue>(
174        &mut self,
175        v: &GaugeValue,
176    ) -> Result<(), std::fmt::Error> {
177        for_both_mut!(self, MetricEncoderInner, e, e.encode_gauge(v))
178    }
179
180    /// Encode an info.
181    pub fn encode_info(&mut self, label_set: &impl EncodeLabelSet) -> Result<(), std::fmt::Error> {
182        for_both_mut!(self, MetricEncoderInner, e, e.encode_info(label_set))
183    }
184
185    /// Encode a histogram.
186    pub fn encode_histogram<S: EncodeLabelSet>(
187        &mut self,
188        sum: f64,
189        count: u64,
190        buckets: &[(f64, u64)],
191        exemplars: Option<&HashMap<usize, Exemplar<S, f64>>>,
192    ) -> Result<(), std::fmt::Error> {
193        for_both_mut!(
194            self,
195            MetricEncoderInner,
196            e,
197            e.encode_histogram(sum, count, buckets, exemplars)
198        )
199    }
200
201    /// Encode a metric family.
202    pub fn encode_family<'s, S: EncodeLabelSet>(
203        &'s mut self,
204        label_set: &'s S,
205    ) -> Result<MetricEncoder<'s>, std::fmt::Error> {
206        for_both_mut!(
207            self,
208            MetricEncoderInner,
209            e,
210            e.encode_family(label_set).map(Into::into)
211        )
212    }
213}
214
215/// An encodable label set.
216pub trait EncodeLabelSet {
217    /// Encode oneself into the given encoder.
218    fn encode(&self, encoder: &mut LabelSetEncoder) -> Result<(), std::fmt::Error>;
219}
220
221/// Encoder for a label set.
222#[derive(Debug)]
223pub struct LabelSetEncoder<'a>(LabelSetEncoderInner<'a>);
224
225#[derive(Debug)]
226enum LabelSetEncoderInner<'a> {
227    Text(text::LabelSetEncoder<'a>),
228    #[cfg(feature = "protobuf")]
229    Protobuf(protobuf::LabelSetEncoder<'a>),
230}
231
232impl<'a> From<text::LabelSetEncoder<'a>> for LabelSetEncoder<'a> {
233    fn from(e: text::LabelSetEncoder<'a>) -> Self {
234        Self(LabelSetEncoderInner::Text(e))
235    }
236}
237
238#[cfg(feature = "protobuf")]
239impl<'a> From<protobuf::LabelSetEncoder<'a>> for LabelSetEncoder<'a> {
240    fn from(e: protobuf::LabelSetEncoder<'a>) -> Self {
241        Self(LabelSetEncoderInner::Protobuf(e))
242    }
243}
244
245impl LabelSetEncoder<'_> {
246    /// Encode the given label.
247    pub fn encode_label(&mut self) -> LabelEncoder<'_> {
248        for_both_mut!(self, LabelSetEncoderInner, e, e.encode_label().into())
249    }
250}
251
252impl<T: EncodeLabel, const N: usize> EncodeLabelSet for [T; N] {
253    fn encode(&self, encoder: &mut LabelSetEncoder) -> Result<(), std::fmt::Error> {
254        self.as_ref().encode(encoder)
255    }
256}
257
258impl<T: EncodeLabel> EncodeLabelSet for &[T] {
259    fn encode(&self, encoder: &mut LabelSetEncoder) -> Result<(), std::fmt::Error> {
260        if self.is_empty() {
261            return Ok(());
262        }
263
264        for label in self.iter() {
265            let encoder = encoder.encode_label();
266            label.encode(encoder)?
267        }
268
269        Ok(())
270    }
271}
272
273impl<T: EncodeLabel> EncodeLabelSet for Vec<T> {
274    fn encode(&self, encoder: &mut LabelSetEncoder) -> Result<(), std::fmt::Error> {
275        self.as_slice().encode(encoder)
276    }
277}
278
279impl<A, B> EncodeLabelSet for (A, B)
280where
281    A: EncodeLabelSet,
282    B: EncodeLabelSet,
283{
284    fn encode(&self, encoder: &mut LabelSetEncoder) -> Result<(), std::fmt::Error> {
285        let (a, b) = self;
286
287        a.encode(encoder)?;
288        b.encode(encoder)?;
289
290        Ok(())
291    }
292}
293
294/// Uninhabited type to represent the lack of a label set for a metric
295#[derive(Debug)]
296pub enum NoLabelSet {}
297
298impl EncodeLabelSet for NoLabelSet {
299    fn encode(&self, _encoder: &mut LabelSetEncoder) -> Result<(), std::fmt::Error> {
300        Ok(())
301    }
302}
303
304/// An encodable label.
305pub trait EncodeLabel {
306    /// Encode oneself into the given encoder.
307    fn encode(&self, encoder: LabelEncoder) -> Result<(), std::fmt::Error>;
308}
309
310/// Encoder for a label.
311#[derive(Debug)]
312pub struct LabelEncoder<'a>(LabelEncoderInner<'a>);
313
314#[derive(Debug)]
315enum LabelEncoderInner<'a> {
316    Text(text::LabelEncoder<'a>),
317    #[cfg(feature = "protobuf")]
318    Protobuf(protobuf::LabelEncoder<'a>),
319}
320
321impl<'a> From<text::LabelEncoder<'a>> for LabelEncoder<'a> {
322    fn from(e: text::LabelEncoder<'a>) -> Self {
323        Self(LabelEncoderInner::Text(e))
324    }
325}
326
327#[cfg(feature = "protobuf")]
328impl<'a> From<protobuf::LabelEncoder<'a>> for LabelEncoder<'a> {
329    fn from(e: protobuf::LabelEncoder<'a>) -> Self {
330        Self(LabelEncoderInner::Protobuf(e))
331    }
332}
333
334impl LabelEncoder<'_> {
335    /// Encode a label.
336    pub fn encode_label_key(&mut self) -> Result<LabelKeyEncoder<'_>, std::fmt::Error> {
337        for_both_mut!(
338            self,
339            LabelEncoderInner,
340            e,
341            e.encode_label_key().map(Into::into)
342        )
343    }
344}
345
346impl<K: EncodeLabelKey, V: EncodeLabelValue> EncodeLabel for (K, V) {
347    fn encode(&self, mut encoder: LabelEncoder) -> Result<(), std::fmt::Error> {
348        let (key, value) = self;
349
350        let mut label_key_encoder = encoder.encode_label_key()?;
351        key.encode(&mut label_key_encoder)?;
352
353        let mut label_value_encoder = label_key_encoder.encode_label_value()?;
354        value.encode(&mut label_value_encoder)?;
355        label_value_encoder.finish()?;
356
357        Ok(())
358    }
359}
360
361/// An encodable label key.
362pub trait EncodeLabelKey {
363    /// Encode oneself into the given encoder.
364    fn encode(&self, encoder: &mut LabelKeyEncoder) -> Result<(), std::fmt::Error>;
365}
366
367/// Encoder for a label key.
368#[derive(Debug)]
369pub struct LabelKeyEncoder<'a>(LabelKeyEncoderInner<'a>);
370
371#[derive(Debug)]
372enum LabelKeyEncoderInner<'a> {
373    Text(text::LabelKeyEncoder<'a>),
374    #[cfg(feature = "protobuf")]
375    Protobuf(protobuf::LabelKeyEncoder<'a>),
376}
377
378impl<'a> From<text::LabelKeyEncoder<'a>> for LabelKeyEncoder<'a> {
379    fn from(e: text::LabelKeyEncoder<'a>) -> Self {
380        Self(LabelKeyEncoderInner::Text(e))
381    }
382}
383
384#[cfg(feature = "protobuf")]
385impl<'a> From<protobuf::LabelKeyEncoder<'a>> for LabelKeyEncoder<'a> {
386    fn from(e: protobuf::LabelKeyEncoder<'a>) -> Self {
387        Self(LabelKeyEncoderInner::Protobuf(e))
388    }
389}
390
391impl std::fmt::Write for LabelKeyEncoder<'_> {
392    fn write_str(&mut self, s: &str) -> std::fmt::Result {
393        for_both_mut!(self, LabelKeyEncoderInner, e, e.write_str(s))
394    }
395}
396
397impl<'a> LabelKeyEncoder<'a> {
398    /// Encode a label value.
399    pub fn encode_label_value(self) -> Result<LabelValueEncoder<'a>, std::fmt::Error> {
400        for_both!(
401            self,
402            LabelKeyEncoderInner,
403            e,
404            e.encode_label_value().map(LabelValueEncoder::from)
405        )
406    }
407}
408
409impl EncodeLabelKey for &str {
410    fn encode(&self, encoder: &mut LabelKeyEncoder) -> Result<(), std::fmt::Error> {
411        encoder.write_str(self)?;
412        Ok(())
413    }
414}
415
416impl EncodeLabelKey for String {
417    fn encode(&self, encoder: &mut LabelKeyEncoder) -> Result<(), std::fmt::Error> {
418        EncodeLabelKey::encode(&self.as_str(), encoder)
419    }
420}
421
422impl EncodeLabelKey for Cow<'_, str> {
423    fn encode(&self, encoder: &mut LabelKeyEncoder) -> Result<(), std::fmt::Error> {
424        EncodeLabelKey::encode(&self.as_ref(), encoder)
425    }
426}
427
428impl<T> EncodeLabelKey for Box<T>
429where
430    T: ?Sized,
431    for<'a> &'a T: EncodeLabelKey,
432{
433    fn encode(&self, encoder: &mut LabelKeyEncoder) -> Result<(), std::fmt::Error> {
434        EncodeLabelKey::encode(&self.as_ref(), encoder)
435    }
436}
437
438impl<T> EncodeLabelKey for Arc<T>
439where
440    T: ?Sized,
441    for<'a> &'a T: EncodeLabelKey,
442{
443    fn encode(&self, encoder: &mut LabelKeyEncoder) -> Result<(), std::fmt::Error> {
444        EncodeLabelKey::encode(&self.as_ref(), encoder)
445    }
446}
447
448impl<T> EncodeLabelKey for Rc<T>
449where
450    T: ?Sized,
451    for<'a> &'a T: EncodeLabelKey,
452{
453    fn encode(&self, encoder: &mut LabelKeyEncoder) -> Result<(), std::fmt::Error> {
454        EncodeLabelKey::encode(&self.as_ref(), encoder)
455    }
456}
457
458/// An encodable label value.
459pub trait EncodeLabelValue {
460    /// Encode oneself into the given encoder.
461    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error>;
462}
463
464/// Encoder for a label value.
465#[derive(Debug)]
466pub struct LabelValueEncoder<'a>(LabelValueEncoderInner<'a>);
467
468#[derive(Debug)]
469enum LabelValueEncoderInner<'a> {
470    Text(text::LabelValueEncoder<'a>),
471    #[cfg(feature = "protobuf")]
472    Protobuf(protobuf::LabelValueEncoder<'a>),
473}
474
475impl<'a> From<text::LabelValueEncoder<'a>> for LabelValueEncoder<'a> {
476    fn from(e: text::LabelValueEncoder<'a>) -> Self {
477        LabelValueEncoder(LabelValueEncoderInner::Text(e))
478    }
479}
480
481#[cfg(feature = "protobuf")]
482impl<'a> From<protobuf::LabelValueEncoder<'a>> for LabelValueEncoder<'a> {
483    fn from(e: protobuf::LabelValueEncoder<'a>) -> Self {
484        LabelValueEncoder(LabelValueEncoderInner::Protobuf(e))
485    }
486}
487
488impl std::fmt::Write for LabelValueEncoder<'_> {
489    fn write_str(&mut self, s: &str) -> std::fmt::Result {
490        for_both_mut!(self, LabelValueEncoderInner, e, e.write_str(s))
491    }
492}
493
494impl LabelValueEncoder<'_> {
495    /// Finish encoding the label value.
496    pub fn finish(self) -> Result<(), std::fmt::Error> {
497        for_both!(self, LabelValueEncoderInner, e, e.finish())
498    }
499}
500
501impl EncodeLabelValue for &str {
502    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
503        encoder.write_str(self)?;
504        Ok(())
505    }
506}
507
508impl EncodeLabelValue for String {
509    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
510        EncodeLabelValue::encode(&self.as_str(), encoder)
511    }
512}
513
514impl EncodeLabelValue for &String {
515    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
516        EncodeLabelValue::encode(&self.as_str(), encoder)
517    }
518}
519
520impl EncodeLabelValue for Cow<'_, str> {
521    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
522        EncodeLabelValue::encode(&self.as_ref(), encoder)
523    }
524}
525
526impl<T> EncodeLabelValue for Box<T>
527where
528    T: ?Sized,
529    for<'a> &'a T: EncodeLabelValue,
530{
531    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
532        EncodeLabelValue::encode(&self.as_ref(), encoder)
533    }
534}
535
536impl<T> EncodeLabelValue for Arc<T>
537where
538    T: ?Sized,
539    for<'a> &'a T: EncodeLabelValue,
540{
541    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
542        EncodeLabelValue::encode(&self.as_ref(), encoder)
543    }
544}
545
546impl<T> EncodeLabelValue for Rc<T>
547where
548    T: ?Sized,
549    for<'a> &'a T: EncodeLabelValue,
550{
551    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
552        EncodeLabelValue::encode(&self.as_ref(), encoder)
553    }
554}
555
556impl EncodeLabelValue for f64 {
557    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
558        encoder.write_str(dtoa::Buffer::new().format(*self))
559    }
560}
561
562impl<T> EncodeLabelValue for Option<T>
563where
564    T: EncodeLabelValue,
565{
566    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
567        match self {
568            Some(v) => EncodeLabelValue::encode(v, encoder),
569            None => EncodeLabelValue::encode(&"", encoder),
570        }
571    }
572}
573
574impl EncodeLabelValue for bool {
575    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
576        encoder.write_str(if *self { "true" } else { "false" })
577    }
578}
579
580macro_rules! impl_encode_label_value_for_integer {
581    ($($t:ident),*) => {$(
582        impl EncodeLabelValue for $t {
583            fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
584                encoder.write_str(itoa::Buffer::new().format(*self))
585            }
586        }
587    )*};
588}
589
590impl_encode_label_value_for_integer!(
591    u128, i128, u64, i64, u32, i32, u16, i16, u8, i8, usize, isize
592);
593
594/// An encodable gauge value.
595pub trait EncodeGaugeValue {
596    /// Encode the given instance in the OpenMetrics text encoding.
597    fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error>;
598}
599
600impl EncodeGaugeValue for u32 {
601    fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error> {
602        encoder.encode_u32(*self)
603    }
604}
605
606impl EncodeGaugeValue for i64 {
607    fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error> {
608        encoder.encode_i64(*self)
609    }
610}
611
612impl EncodeGaugeValue for u64 {
613    fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error> {
614        // Between forcing end users to do endless as i64 for things that are
615        // clearly valid i64 and having one error case for rarely used protobuf when
616        // a gauge is set to >i64::MAX, the latter seems like the right choice.
617        encoder.encode_i64(i64::try_from(*self).map_err(|_err| std::fmt::Error)?)
618    }
619}
620
621impl EncodeGaugeValue for isize {
622    fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error> {
623        // Is infallible for 32-bit or 64-bit platforms
624        encoder.encode_i64(i64::try_from(*self).map_err(|_err| std::fmt::Error)?)
625    }
626}
627
628impl EncodeGaugeValue for usize {
629    fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error> {
630        // For 32-bit platforms this is infallible, for 64-bit platforms the argument is the same
631        // as the one for u64 values
632        encoder.encode_i64(i64::try_from(*self).map_err(|_err| std::fmt::Error)?)
633    }
634}
635
636impl EncodeGaugeValue for f64 {
637    fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error> {
638        encoder.encode_f64(*self)
639    }
640}
641
642impl EncodeGaugeValue for i32 {
643    fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error> {
644        encoder.encode_i64(i64::from(*self))
645    }
646}
647
648impl EncodeGaugeValue for f32 {
649    fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error> {
650        encoder.encode_f64(f64::from(*self))
651    }
652}
653
654/// Encoder for a gauge value.
655#[derive(Debug)]
656pub struct GaugeValueEncoder<'a>(GaugeValueEncoderInner<'a>);
657
658#[derive(Debug)]
659enum GaugeValueEncoderInner<'a> {
660    Text(text::GaugeValueEncoder<'a>),
661    #[cfg(feature = "protobuf")]
662    Protobuf(protobuf::GaugeValueEncoder<'a>),
663}
664
665impl GaugeValueEncoder<'_> {
666    fn encode_u32(&mut self, v: u32) -> Result<(), std::fmt::Error> {
667        for_both_mut!(self, GaugeValueEncoderInner, e, e.encode_u32(v))
668    }
669
670    fn encode_i64(&mut self, v: i64) -> Result<(), std::fmt::Error> {
671        for_both_mut!(self, GaugeValueEncoderInner, e, e.encode_i64(v))
672    }
673
674    fn encode_f64(&mut self, v: f64) -> Result<(), std::fmt::Error> {
675        for_both_mut!(self, GaugeValueEncoderInner, e, e.encode_f64(v))
676    }
677}
678
679impl<'a> From<text::GaugeValueEncoder<'a>> for GaugeValueEncoder<'a> {
680    fn from(e: text::GaugeValueEncoder<'a>) -> Self {
681        GaugeValueEncoder(GaugeValueEncoderInner::Text(e))
682    }
683}
684
685#[cfg(feature = "protobuf")]
686impl<'a> From<protobuf::GaugeValueEncoder<'a>> for GaugeValueEncoder<'a> {
687    fn from(e: protobuf::GaugeValueEncoder<'a>) -> Self {
688        GaugeValueEncoder(GaugeValueEncoderInner::Protobuf(e))
689    }
690}
691
692/// An encodable counter value.
693pub trait EncodeCounterValue {
694    /// Encode the given instance in the OpenMetrics text encoding.
695    fn encode(&self, encoder: &mut CounterValueEncoder) -> Result<(), std::fmt::Error>;
696}
697
698impl EncodeCounterValue for u64 {
699    fn encode(&self, encoder: &mut CounterValueEncoder) -> Result<(), std::fmt::Error> {
700        encoder.encode_u64(*self)
701    }
702}
703
704impl EncodeCounterValue for usize {
705    fn encode(&self, encoder: &mut CounterValueEncoder) -> Result<(), std::fmt::Error> {
706        // Is infallible for 32-bit and 64-bit platforms
707        encoder.encode_u64(u64::try_from(*self).map_err(|_err| std::fmt::Error)?)
708    }
709}
710
711impl EncodeCounterValue for f64 {
712    fn encode(&self, encoder: &mut CounterValueEncoder) -> Result<(), std::fmt::Error> {
713        encoder.encode_f64(*self)
714    }
715}
716
717impl EncodeCounterValue for u32 {
718    fn encode(&self, encoder: &mut CounterValueEncoder) -> Result<(), std::fmt::Error> {
719        encoder.encode_u64(u64::from(*self))
720    }
721}
722
723impl EncodeCounterValue for f32 {
724    fn encode(&self, encoder: &mut CounterValueEncoder) -> Result<(), std::fmt::Error> {
725        encoder.encode_f64(f64::from(*self))
726    }
727}
728
729/// Encoder for a counter value.
730#[derive(Debug)]
731pub struct CounterValueEncoder<'a>(CounterValueEncoderInner<'a>);
732
733#[derive(Debug)]
734enum CounterValueEncoderInner<'a> {
735    Text(text::CounterValueEncoder<'a>),
736    #[cfg(feature = "protobuf")]
737    Protobuf(protobuf::CounterValueEncoder<'a>),
738}
739
740impl<'a> From<text::CounterValueEncoder<'a>> for CounterValueEncoder<'a> {
741    fn from(e: text::CounterValueEncoder<'a>) -> Self {
742        CounterValueEncoder(CounterValueEncoderInner::Text(e))
743    }
744}
745
746#[cfg(feature = "protobuf")]
747impl<'a> From<protobuf::CounterValueEncoder<'a>> for CounterValueEncoder<'a> {
748    fn from(e: protobuf::CounterValueEncoder<'a>) -> Self {
749        CounterValueEncoder(CounterValueEncoderInner::Protobuf(e))
750    }
751}
752
753impl CounterValueEncoder<'_> {
754    fn encode_f64(&mut self, v: f64) -> Result<(), std::fmt::Error> {
755        for_both_mut!(self, CounterValueEncoderInner, e, e.encode_f64(v))
756    }
757
758    fn encode_u64(&mut self, v: u64) -> Result<(), std::fmt::Error> {
759        for_both_mut!(self, CounterValueEncoderInner, e, e.encode_u64(v))
760    }
761}
762
763/// An encodable exemplar value.
764pub trait EncodeExemplarValue {
765    /// Encode the given instance in the OpenMetrics text encoding.
766    fn encode(&self, encoder: ExemplarValueEncoder) -> Result<(), std::fmt::Error>;
767}
768
769impl EncodeExemplarValue for f64 {
770    fn encode(&self, mut encoder: ExemplarValueEncoder) -> Result<(), std::fmt::Error> {
771        encoder.encode(*self)
772    }
773}
774
775impl EncodeExemplarValue for u64 {
776    fn encode(&self, mut encoder: ExemplarValueEncoder) -> Result<(), std::fmt::Error> {
777        encoder.encode(*self as f64)
778    }
779}
780
781impl EncodeExemplarValue for f32 {
782    fn encode(&self, mut encoder: ExemplarValueEncoder) -> Result<(), std::fmt::Error> {
783        encoder.encode(f64::from(*self))
784    }
785}
786
787impl EncodeExemplarValue for u32 {
788    fn encode(&self, mut encoder: ExemplarValueEncoder) -> Result<(), std::fmt::Error> {
789        encoder.encode(f64::from(*self))
790    }
791}
792
793/// An encodable exemplar time.
794pub trait EncodeExemplarTime {
795    /// Encode the time in the OpenMetrics text encoding.
796    fn encode(&self, encoder: ExemplarValueEncoder) -> Result<(), std::fmt::Error>;
797}
798
799impl EncodeExemplarTime for SystemTime {
800    fn encode(&self, mut encoder: ExemplarValueEncoder) -> Result<(), std::fmt::Error> {
801        encoder.encode(self.duration_since(UNIX_EPOCH).unwrap().as_secs_f64())
802    }
803}
804
805/// Encoder for an exemplar value.
806#[derive(Debug)]
807pub struct ExemplarValueEncoder<'a>(ExemplarValueEncoderInner<'a>);
808
809#[derive(Debug)]
810enum ExemplarValueEncoderInner<'a> {
811    Text(text::ExemplarValueEncoder<'a>),
812    #[cfg(feature = "protobuf")]
813    Protobuf(protobuf::ExemplarValueEncoder<'a>),
814}
815
816impl<'a> From<text::ExemplarValueEncoder<'a>> for ExemplarValueEncoder<'a> {
817    fn from(e: text::ExemplarValueEncoder<'a>) -> Self {
818        ExemplarValueEncoder(ExemplarValueEncoderInner::Text(e))
819    }
820}
821
822#[cfg(feature = "protobuf")]
823impl<'a> From<protobuf::ExemplarValueEncoder<'a>> for ExemplarValueEncoder<'a> {
824    fn from(e: protobuf::ExemplarValueEncoder<'a>) -> Self {
825        ExemplarValueEncoder(ExemplarValueEncoderInner::Protobuf(e))
826    }
827}
828
829impl ExemplarValueEncoder<'_> {
830    fn encode(&mut self, v: f64) -> Result<(), std::fmt::Error> {
831        for_both_mut!(self, ExemplarValueEncoderInner, e, e.encode(v))
832    }
833}