glean_core/
common_metric_data.rs1use std::ops::Deref;
6use std::sync::atomic::{AtomicU8, Ordering};
7
8use malloc_size_of_derive::MallocSizeOf;
9
10use crate::error::{Error, ErrorKind};
11use crate::metrics::dual_labeled_counter::validate_dynamic_key_and_or_category;
12use crate::metrics::labeled::validate_dynamic_label;
13use crate::Glean;
14use serde::{Deserialize, Serialize};
15
16#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default, MallocSizeOf)]
20#[repr(i32)] #[serde(rename_all = "lowercase")]
22pub enum Lifetime {
23 #[default]
25 Ping,
26 Application,
28 User,
30}
31
32impl Lifetime {
33 pub fn as_str(self) -> &'static str {
35 match self {
36 Lifetime::Ping => "ping",
37 Lifetime::Application => "app",
38 Lifetime::User => "user",
39 }
40 }
41}
42
43impl TryFrom<i32> for Lifetime {
44 type Error = Error;
45
46 fn try_from(value: i32) -> Result<Lifetime, Self::Error> {
47 match value {
48 0 => Ok(Lifetime::Ping),
49 1 => Ok(Lifetime::Application),
50 2 => Ok(Lifetime::User),
51 e => Err(ErrorKind::Lifetime(e).into()),
52 }
53 }
54}
55
56#[derive(Default, Debug, Clone, Deserialize, Serialize, MallocSizeOf)]
58pub struct CommonMetricData {
59 pub name: String,
61 pub category: String,
63 pub send_in_pings: Vec<String>,
65 pub lifetime: Lifetime,
67 pub disabled: bool,
71 pub dynamic_label: Option<DynamicLabelType>,
78}
79
80#[derive(Debug, Clone, Deserialize, Serialize, MallocSizeOf, uniffi::Enum)]
83pub enum DynamicLabelType {
84 Label(String),
86 KeyOnly(String),
88 CategoryOnly(String),
90 KeyAndCategory(String),
92}
93
94impl Default for DynamicLabelType {
95 fn default() -> Self {
96 Self::Label(String::new())
97 }
98}
99
100impl Deref for DynamicLabelType {
101 type Target = str;
102
103 fn deref(&self) -> &Self::Target {
104 match self {
105 DynamicLabelType::Label(label) => label,
106 DynamicLabelType::KeyOnly(key) => key,
107 DynamicLabelType::CategoryOnly(category) => category,
108 DynamicLabelType::KeyAndCategory(key_and_category) => key_and_category,
109 }
110 }
111}
112
113#[derive(Default, Debug, MallocSizeOf)]
114pub struct CommonMetricDataInternal {
115 pub inner: CommonMetricData,
116 pub disabled: AtomicU8,
117}
118
119impl Clone for CommonMetricDataInternal {
120 fn clone(&self) -> Self {
121 Self {
122 inner: self.inner.clone(),
123 disabled: AtomicU8::new(self.disabled.load(Ordering::Relaxed)),
124 }
125 }
126}
127
128impl From<CommonMetricData> for CommonMetricDataInternal {
129 fn from(input_data: CommonMetricData) -> Self {
130 let disabled = input_data.disabled;
131 Self {
132 inner: input_data,
133 disabled: AtomicU8::new(u8::from(disabled)),
134 }
135 }
136}
137
138impl CommonMetricDataInternal {
139 pub fn new<A: Into<String>, B: Into<String>, C: Into<String>>(
141 category: A,
142 name: B,
143 ping_name: C,
144 ) -> CommonMetricDataInternal {
145 CommonMetricDataInternal {
146 inner: CommonMetricData {
147 name: name.into(),
148 category: category.into(),
149 send_in_pings: vec![ping_name.into()],
150 ..Default::default()
151 },
152 disabled: AtomicU8::new(0),
153 }
154 }
155
156 pub(crate) fn base_identifier(&self) -> String {
161 if self.inner.category.is_empty() {
162 self.inner.name.clone()
163 } else {
164 format!("{}.{}", self.inner.category, self.inner.name)
165 }
166 }
167
168 pub(crate) fn identifier(&self, glean: &Glean) -> String {
173 let base_identifier = self.base_identifier();
174
175 if let Some(label) = &self.inner.dynamic_label {
176 match label {
177 DynamicLabelType::Label(label) => {
178 validate_dynamic_label(glean, self, &base_identifier, label)
179 }
180 _ => validate_dynamic_key_and_or_category(
181 glean,
182 self,
183 &base_identifier,
184 label.clone(),
185 ),
186 }
187 } else {
188 base_identifier
189 }
190 }
191
192 pub fn storage_names(&self) -> &[String] {
194 &self.inner.send_in_pings
195 }
196}