Skip to main content

memfaultd/metrics/
metric_value.rs

1//
2// Copyright (c) Memfault, Inc.
3// See License.txt for details
4use eyre::Result;
5use serde::{Deserialize, Serialize, Serializer};
6use std::fmt::Display;
7
8#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
9pub struct Histogram {
10    pub min: f64,
11    pub mean: f64,
12    pub max: f64,
13}
14
15impl Histogram {
16    pub fn min(&self) -> MetricValue {
17        MetricValue::Number(self.min)
18    }
19
20    pub fn avg(&self) -> MetricValue {
21        MetricValue::Number(self.mean)
22    }
23
24    pub fn max(&self) -> MetricValue {
25        MetricValue::Number(self.max)
26    }
27}
28
29pub fn construct_histogram_value(min: f64, mean: f64, max: f64) -> Histogram {
30    Histogram { min, mean, max }
31}
32
33#[derive(Clone, Debug, PartialEq, Deserialize)]
34#[serde(untagged)]
35pub enum MetricValue {
36    Number(f64),
37    String(String),
38    Histogram(Histogram),
39    Bool(bool),
40}
41
42impl Serialize for MetricValue {
43    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
44    where
45        S: Serializer,
46    {
47        match self {
48            MetricValue::Number(v) => serializer.serialize_f64(*v),
49            MetricValue::String(v) => serializer.serialize_str(v.as_str()),
50            MetricValue::Histogram(histo) => histo.serialize(serializer),
51            MetricValue::Bool(v) => serializer.serialize_bool(*v),
52        }
53    }
54}
55
56impl Display for MetricValue {
57    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58        let json_value = match self {
59            MetricValue::Number(n) => serde_json::Value::Number(
60                serde_json::Number::from_f64(*n).unwrap_or(serde_json::Number::from(0)),
61            ),
62            MetricValue::String(s) => serde_json::Value::String(s.clone()),
63            MetricValue::Bool(b) => serde_json::Value::Bool(*b),
64            MetricValue::Histogram(h) => {
65                // For histograms, show basic stats
66                serde_json::json!({
67                    "type": "histogram",
68                    "avg": h.mean,
69                    "min": h.min,
70                    "max": h.max
71                })
72            }
73        };
74        write!(f, "{}", json_value)
75    }
76}