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 crate::error_recording::{record_error, ErrorType}; 6 use crate::metrics::Metric; 7 use crate::metrics::MetricType; 8 use crate::storage::StorageManager; 9 use crate::CommonMetricData; 10 use crate::Glean; 11 12 /// A counter metric. 13 /// 14 /// Used to count things. 15 /// The value can only be incremented, not decremented. 16 #[derive(Clone, Debug)] 17 pub struct CounterMetric { 18 meta: CommonMetricData, 19 } 20 21 impl MetricType for CounterMetric { meta(&self) -> &CommonMetricData22 fn meta(&self) -> &CommonMetricData { 23 &self.meta 24 } 25 meta_mut(&mut self) -> &mut CommonMetricData26 fn meta_mut(&mut self) -> &mut CommonMetricData { 27 &mut self.meta 28 } 29 } 30 31 // IMPORTANT: 32 // 33 // When changing this implementation, make sure all the operations are 34 // also declared in the related trait in `../traits/`. 35 impl CounterMetric { 36 /// Creates a new counter metric. new(meta: CommonMetricData) -> Self37 pub fn new(meta: CommonMetricData) -> Self { 38 Self { meta } 39 } 40 41 /// Increases the counter by `amount`. 42 /// 43 /// # Arguments 44 /// 45 /// * `glean` - The Glean instance this metric belongs to. 46 /// * `amount` - The amount to increase by. Should be positive. 47 /// 48 /// ## Notes 49 /// 50 /// Logs an error if the `amount` is 0 or negative. add(&self, glean: &Glean, amount: i32)51 pub fn add(&self, glean: &Glean, amount: i32) { 52 if !self.should_record(glean) { 53 return; 54 } 55 56 if amount <= 0 { 57 record_error( 58 glean, 59 &self.meta, 60 ErrorType::InvalidValue, 61 format!("Added negative or zero value {}", amount), 62 None, 63 ); 64 return; 65 } 66 67 glean 68 .storage() 69 .record_with(glean, &self.meta, |old_value| match old_value { 70 Some(Metric::Counter(old_value)) => { 71 Metric::Counter(old_value.saturating_add(amount)) 72 } 73 _ => Metric::Counter(amount), 74 }) 75 } 76 77 /// **Test-only API (exported for FFI purposes).** 78 /// 79 /// Gets the currently stored value as an integer. 80 /// 81 /// This doesn't clear the stored value. test_get_value(&self, glean: &Glean, storage_name: &str) -> Option<i32>82 pub fn test_get_value(&self, glean: &Glean, storage_name: &str) -> Option<i32> { 83 match StorageManager.snapshot_metric_for_test( 84 glean.storage(), 85 storage_name, 86 &self.meta.identifier(glean), 87 self.meta.lifetime, 88 ) { 89 Some(Metric::Counter(i)) => Some(i), 90 _ => None, 91 } 92 } 93 } 94