Skip to main content

prometheus_client/
encoding.rs

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