1 // This Source Code Form is subject to the terms of the Mozilla Public
2 // License, v. 2.0. If a copy of the MPL was not distributed with this
3 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4 
5 use uuid::Uuid;
6 
7 use crate::error_recording::{record_error, ErrorType};
8 use crate::metrics::Metric;
9 use crate::metrics::MetricType;
10 use crate::storage::StorageManager;
11 use crate::CommonMetricData;
12 use crate::Glean;
13 
14 /// An UUID metric.
15 ///
16 /// Stores UUID v4 (randomly generated) values.
17 #[derive(Clone, Debug)]
18 pub struct UuidMetric {
19     meta: CommonMetricData,
20 }
21 
22 impl MetricType for UuidMetric {
meta(&self) -> &CommonMetricData23     fn meta(&self) -> &CommonMetricData {
24         &self.meta
25     }
26 
meta_mut(&mut self) -> &mut CommonMetricData27     fn meta_mut(&mut self) -> &mut CommonMetricData {
28         &mut self.meta
29     }
30 }
31 
32 // IMPORTANT:
33 //
34 // When changing this implementation, make sure all the operations are
35 // also declared in the related trait in `../traits/`.
36 impl UuidMetric {
37     /// Creates a new UUID metric
new(meta: CommonMetricData) -> Self38     pub fn new(meta: CommonMetricData) -> Self {
39         Self { meta }
40     }
41 
42     /// Sets to the specified value.
43     ///
44     /// # Arguments
45     ///
46     /// * `glean` - The Glean instance this metric belongs to.
47     /// * `value` - The [`Uuid`] to set the metric to.
set(&self, glean: &Glean, value: Uuid)48     pub fn set(&self, glean: &Glean, value: Uuid) {
49         if !self.should_record(glean) {
50             return;
51         }
52 
53         let s = value.to_string();
54         let value = Metric::Uuid(s);
55         glean.storage().record(glean, &self.meta, &value)
56     }
57 
58     /// Sets to the specified value, from a string.
59     ///
60     /// This should only be used from FFI. When calling directly from Rust, it
61     /// is better to use [`set`](UuidMetric::set).
62     ///
63     /// # Arguments
64     ///
65     /// * `glean` - The Glean instance this metric belongs to.
66     /// * `value` - The [`Uuid`] to set the metric to.
set_from_str(&self, glean: &Glean, value: &str)67     pub fn set_from_str(&self, glean: &Glean, value: &str) {
68         if !self.should_record(glean) {
69             return;
70         }
71 
72         if let Ok(uuid) = uuid::Uuid::parse_str(&value) {
73             self.set(glean, uuid);
74         } else {
75             let msg = format!("Unexpected UUID value '{}'", value);
76             record_error(glean, &self.meta, ErrorType::InvalidValue, msg, None);
77         }
78     }
79 
80     /// Generates a new random [`Uuid`'] and sets the metric to it.
81     ///
82     /// # Arguments
83     ///
84     /// * `glean` - The Glean instance this metric belongs to.
generate_and_set(&self, storage: &Glean) -> Uuid85     pub fn generate_and_set(&self, storage: &Glean) -> Uuid {
86         let uuid = Uuid::new_v4();
87         self.set(storage, uuid);
88         uuid
89     }
90 
91     /// Gets the stored Uuid value.
92     ///
93     /// # Arguments
94     ///
95     /// * `glean` - the Glean instance this metric belongs to.
96     /// * `storage_name` - the storage name to look into.
97     ///
98     /// # Returns
99     ///
100     /// The stored value or `None` if nothing stored.
get_value(&self, glean: &Glean, storage_name: &str) -> Option<Uuid>101     pub(crate) fn get_value(&self, glean: &Glean, storage_name: &str) -> Option<Uuid> {
102         match StorageManager.snapshot_metric(
103             glean.storage(),
104             storage_name,
105             &self.meta().identifier(glean),
106             self.meta.lifetime,
107         ) {
108             Some(Metric::Uuid(uuid)) => Uuid::parse_str(&uuid).ok(),
109             _ => None,
110         }
111     }
112 
113     /// **Test-only API (exported for FFI purposes).**
114     ///
115     /// Gets the currently stored value as a string.
116     ///
117     /// This doesn't clear the stored value.
test_get_value(&self, glean: &Glean, storage_name: &str) -> Option<Uuid>118     pub fn test_get_value(&self, glean: &Glean, storage_name: &str) -> Option<Uuid> {
119         self.get_value(glean, storage_name)
120     }
121 }
122