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