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