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