1use crate::metrics::{
6 Datetime, DatetimeMetric, QuantityMetric, StringMetric, TimeUnit, TimespanMetric,
7};
8use crate::{CommonMetricData, Lifetime};
9
10use once_cell::sync::Lazy;
11
12#[derive(Debug, Default)]
14pub struct ClientInfoMetrics {
15 pub app_build: String,
17 pub app_display_version: String,
19 pub app_build_date: Datetime,
21
22 pub architecture: String,
24 pub os_version: String,
26
27 pub channel: Option<String>,
29 pub android_sdk_version: Option<String>,
31 pub windows_build_number: Option<i64>,
33 pub device_manufacturer: Option<String>,
36 pub device_model: Option<String>,
40 pub locale: Option<String>,
43}
44
45#[derive(Clone, Debug, Default, PartialEq)]
47pub struct AttributionMetrics {
48 pub source: Option<String>,
50 pub medium: Option<String>,
52 pub campaign: Option<String>,
54 pub term: Option<String>,
56 pub content: Option<String>,
58}
59
60impl AttributionMetrics {
61 pub fn update(&mut self, other: AttributionMetrics) {
63 if let Some(source) = other.source {
64 self.source = Some(source);
65 }
66 if let Some(medium) = other.medium {
67 self.medium = Some(medium);
68 }
69 if let Some(campaign) = other.campaign {
70 self.campaign = Some(campaign);
71 }
72 if let Some(term) = other.term {
73 self.term = Some(term);
74 }
75 if let Some(content) = other.content {
76 self.content = Some(content);
77 }
78 }
79}
80
81#[derive(Clone, Debug, Default, PartialEq)]
83pub struct DistributionMetrics {
84 pub name: Option<String>,
86}
87
88impl DistributionMetrics {
89 pub fn update(&mut self, other: DistributionMetrics) {
91 if let Some(name) = other.name {
92 self.name = Some(name);
93 }
94 }
95}
96
97impl ClientInfoMetrics {
99 pub fn unknown() -> Self {
101 ClientInfoMetrics {
102 app_build: "Unknown".to_string(),
103 app_display_version: "Unknown".to_string(),
104 app_build_date: Datetime::default(),
105 architecture: "Unknown".to_string(),
106 os_version: "Unknown".to_string(),
107 channel: Some("Unknown".to_string()),
108 android_sdk_version: None,
109 windows_build_number: None,
110 device_manufacturer: None,
111 device_model: None,
112 locale: None,
113 }
114 }
115}
116
117#[allow(non_upper_case_globals)]
118pub mod internal_metrics {
119 use super::*;
120
121 pub static app_build: Lazy<StringMetric> = Lazy::new(|| {
122 StringMetric::new(CommonMetricData {
123 name: "app_build".into(),
124 category: "".into(),
125 send_in_pings: vec!["glean_client_info".into()],
126 lifetime: Lifetime::Application,
127 disabled: false,
128 ..Default::default()
129 })
130 });
131
132 pub static app_display_version: Lazy<StringMetric> = Lazy::new(|| {
133 StringMetric::new(CommonMetricData {
134 name: "app_display_version".into(),
135 category: "".into(),
136 send_in_pings: vec!["glean_client_info".into()],
137 lifetime: Lifetime::Application,
138 disabled: false,
139 ..Default::default()
140 })
141 });
142
143 pub static app_build_date: Lazy<DatetimeMetric> = Lazy::new(|| {
144 DatetimeMetric::new(
145 CommonMetricData {
146 name: "build_date".into(),
147 category: "".into(),
148 send_in_pings: vec!["glean_client_info".into()],
149 lifetime: Lifetime::Application,
150 disabled: false,
151 ..Default::default()
152 },
153 TimeUnit::Second,
154 )
155 });
156
157 pub static app_channel: Lazy<StringMetric> = Lazy::new(|| {
158 StringMetric::new(CommonMetricData {
159 name: "app_channel".into(),
160 category: "".into(),
161 send_in_pings: vec!["glean_client_info".into()],
162 lifetime: Lifetime::Application,
163 disabled: false,
164 ..Default::default()
165 })
166 });
167
168 pub static os_version: Lazy<StringMetric> = Lazy::new(|| {
169 StringMetric::new(CommonMetricData {
170 name: "os_version".into(),
171 category: "".into(),
172 send_in_pings: vec!["glean_client_info".into()],
173 lifetime: Lifetime::Application,
174 disabled: false,
175 ..Default::default()
176 })
177 });
178
179 pub static architecture: Lazy<StringMetric> = Lazy::new(|| {
180 StringMetric::new(CommonMetricData {
181 name: "architecture".into(),
182 category: "".into(),
183 send_in_pings: vec!["glean_client_info".into()],
184 lifetime: Lifetime::Application,
185 disabled: false,
186 ..Default::default()
187 })
188 });
189
190 pub static android_sdk_version: Lazy<StringMetric> = Lazy::new(|| {
191 StringMetric::new(CommonMetricData {
192 name: "android_sdk_version".into(),
193 category: "".into(),
194 send_in_pings: vec!["glean_client_info".into()],
195 lifetime: Lifetime::Application,
196 disabled: false,
197 ..Default::default()
198 })
199 });
200
201 pub static windows_build_number: Lazy<QuantityMetric> = Lazy::new(|| {
202 QuantityMetric::new(CommonMetricData {
203 name: "windows_build_number".into(),
204 category: "".into(),
205 send_in_pings: vec!["glean_client_info".into()],
206 lifetime: Lifetime::Application,
207 disabled: false,
208 ..Default::default()
209 })
210 });
211
212 pub static device_manufacturer: Lazy<StringMetric> = Lazy::new(|| {
213 StringMetric::new(CommonMetricData {
214 name: "device_manufacturer".into(),
215 category: "".into(),
216 send_in_pings: vec!["glean_client_info".into()],
217 lifetime: Lifetime::Application,
218 disabled: false,
219 ..Default::default()
220 })
221 });
222
223 pub static device_model: Lazy<StringMetric> = Lazy::new(|| {
224 StringMetric::new(CommonMetricData {
225 name: "device_model".into(),
226 category: "".into(),
227 send_in_pings: vec!["glean_client_info".into()],
228 lifetime: Lifetime::Application,
229 disabled: false,
230 ..Default::default()
231 })
232 });
233
234 pub static locale: Lazy<StringMetric> = Lazy::new(|| {
235 StringMetric::new(CommonMetricData {
236 name: "locale".into(),
237 category: "".into(),
238 send_in_pings: vec!["glean_client_info".into()],
239 lifetime: Lifetime::Application,
240 disabled: false,
241 ..Default::default()
242 })
243 });
244
245 pub static baseline_duration: Lazy<TimespanMetric> = Lazy::new(|| {
246 TimespanMetric::new(
247 CommonMetricData {
248 name: "duration".into(),
249 category: "glean.baseline".into(),
250 send_in_pings: vec!["baseline".into()],
251 lifetime: Lifetime::Ping,
252 disabled: false,
253 ..Default::default()
254 },
255 TimeUnit::Second,
256 )
257 });
258}
259
260#[cfg(test)]
261mod test {
262 use super::*;
263
264 #[test]
265 fn update_attribution() {
266 let mut attr: AttributionMetrics = Default::default();
267 let empty: AttributionMetrics = Default::default();
268
269 attr.update(empty.clone());
271 assert_eq!(None, attr.source);
272
273 attr.update(AttributionMetrics {
275 source: Some("a source".into()),
276 ..Default::default()
277 });
278 assert_eq!(Some("a source".into()), attr.source);
279
280 attr.update(empty);
282 assert_eq!(Some("a source".into()), attr.source);
283
284 attr.update(AttributionMetrics {
286 source: Some("another source".into()),
287 ..Default::default()
288 });
289 assert_eq!(Some("another source".into()), attr.source);
290 }
291
292 #[test]
293 fn update_distribution() {
294 let mut dist: DistributionMetrics = Default::default();
295 let empty: DistributionMetrics = Default::default();
296
297 dist.update(empty.clone());
299 assert_eq!(None, dist.name);
300
301 dist.update(DistributionMetrics {
303 name: Some("a name".into()),
304 });
305 assert_eq!(Some("a name".into()), dist.name);
306
307 dist.update(empty);
309 assert_eq!(Some("a name".into()), dist.name);
310
311 dist.update(DistributionMetrics {
313 name: Some("another name".into()),
314 });
315 assert_eq!(Some("another name".into()), dist.name);
316 }
317}