fastmetrics/metrics/types/
unknown.rs

1//! [Open Metrics Unknown](https://github.com/prometheus/OpenMetrics/blob/main/specification/OpenMetrics.md#unknown) metric type.
2
3use std::fmt;
4
5use crate::{
6    encoder::{EncodeMetric, EncodeUnknownValue, MetricEncoder},
7    raw::{MetricType, Number, TypedMetric},
8};
9
10/// A marker trait for **unknown** metric value.
11pub trait UnknownValue: Number {}
12
13impl UnknownValue for i32 {}
14impl UnknownValue for i64 {}
15impl UnknownValue for isize {}
16impl UnknownValue for u32 {}
17impl UnknownValue for f32 {}
18impl UnknownValue for f64 {}
19
20/// Open Metrics [`Unknown`] metric, which **SHOULD NOT** be used. It **MAY** be used only when
21/// it's impossible to determine the types of individual metrics from 3rd party systems.
22///
23/// # NOTE
24///
25/// A point in a metric with the [`Unknown`] type **MUST** have a single value.
26#[derive(Clone, Debug)]
27pub struct Unknown<T> {
28    value: T,
29}
30
31impl<T: UnknownValue> Unknown<T> {
32    /// Create an [`Unknown`] metric with the given unknown value.
33    pub const fn new(value: T) -> Self {
34        Self { value }
35    }
36
37    /// Get the unknown value of the [`Unknown`] metric.
38    pub fn get(&self) -> &T {
39        &self.value
40    }
41}
42
43impl<T: UnknownValue> TypedMetric for Unknown<T> {
44    const TYPE: MetricType = MetricType::Unknown;
45    const WITH_TIMESTAMP: bool = false;
46}
47
48impl<T: EncodeUnknownValue + UnknownValue> EncodeMetric for Unknown<T> {
49    fn encode(&self, encoder: &mut dyn MetricEncoder) -> fmt::Result {
50        encoder.encode_unknown(self.get())
51    }
52
53    fn metric_type(&self) -> MetricType {
54        MetricType::Unknown
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61    use crate::metrics::check_text_encoding;
62
63    #[test]
64    fn test_text_encoding() {
65        check_text_encoding(
66            |registry| {
67                let unknown = Unknown::new(1);
68                registry.register("my_unknown", "My unknown help", unknown.clone()).unwrap();
69            },
70            |output| {
71                let expected = indoc::indoc! {r#"
72                    # TYPE my_unknown unknown
73                    # HELP my_unknown My unknown help
74                    my_unknown 1
75                    # EOF
76                "#};
77                assert_eq!(output, expected);
78            },
79        );
80    }
81}