glean_core/
common_metric_data.rs1use std::sync::atomic::{AtomicU8, Ordering};
6
7use crate::error::{Error, ErrorKind};
8use crate::metrics::labeled::validate_dynamic_label;
9use crate::Glean;
10use serde::{Deserialize, Serialize};
11
12#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default)]
16#[repr(i32)] #[serde(rename_all = "lowercase")]
18pub enum Lifetime {
19    #[default]
21    Ping,
22    Application,
24    User,
26}
27
28impl Lifetime {
29    pub fn as_str(self) -> &'static str {
31        match self {
32            Lifetime::Ping => "ping",
33            Lifetime::Application => "app",
34            Lifetime::User => "user",
35        }
36    }
37}
38
39impl TryFrom<i32> for Lifetime {
40    type Error = Error;
41
42    fn try_from(value: i32) -> Result<Lifetime, Self::Error> {
43        match value {
44            0 => Ok(Lifetime::Ping),
45            1 => Ok(Lifetime::Application),
46            2 => Ok(Lifetime::User),
47            e => Err(ErrorKind::Lifetime(e).into()),
48        }
49    }
50}
51
52#[derive(Default, Debug, Clone, Deserialize, Serialize)]
54pub struct CommonMetricData {
55    pub name: String,
57    pub category: String,
59    pub send_in_pings: Vec<String>,
61    pub lifetime: Lifetime,
63    pub disabled: bool,
67    pub dynamic_label: Option<String>,
74}
75
76#[derive(Default, Debug)]
77pub struct CommonMetricDataInternal {
78    pub inner: CommonMetricData,
79    pub disabled: AtomicU8,
80}
81
82impl Clone for CommonMetricDataInternal {
83    fn clone(&self) -> Self {
84        Self {
85            inner: self.inner.clone(),
86            disabled: AtomicU8::new(self.disabled.load(Ordering::Relaxed)),
87        }
88    }
89}
90
91impl From<CommonMetricData> for CommonMetricDataInternal {
92    fn from(input_data: CommonMetricData) -> Self {
93        let disabled = input_data.disabled;
94        Self {
95            inner: input_data,
96            disabled: AtomicU8::new(u8::from(disabled)),
97        }
98    }
99}
100
101impl CommonMetricDataInternal {
102    pub fn new<A: Into<String>, B: Into<String>, C: Into<String>>(
104        category: A,
105        name: B,
106        ping_name: C,
107    ) -> CommonMetricDataInternal {
108        CommonMetricDataInternal {
109            inner: CommonMetricData {
110                name: name.into(),
111                category: category.into(),
112                send_in_pings: vec![ping_name.into()],
113                ..Default::default()
114            },
115            disabled: AtomicU8::new(0),
116        }
117    }
118
119    pub(crate) fn base_identifier(&self) -> String {
124        if self.inner.category.is_empty() {
125            self.inner.name.clone()
126        } else {
127            format!("{}.{}", self.inner.category, self.inner.name)
128        }
129    }
130
131    pub(crate) fn identifier(&self, glean: &Glean) -> String {
136        let base_identifier = self.base_identifier();
137
138        if let Some(label) = &self.inner.dynamic_label {
139            validate_dynamic_label(glean, self, &base_identifier, label)
140        } else {
141            base_identifier
142        }
143    }
144
145    pub fn storage_names(&self) -> &[String] {
147        &self.inner.send_in_pings
148    }
149}