glean_core/metrics/
denominator.rs1use crate::common_metric_data::CommonMetricDataInternal;
6use crate::error_recording::{record_error, test_get_num_recorded_errors, ErrorType};
7use crate::metrics::CounterMetric;
8use crate::metrics::Metric;
9use crate::metrics::MetricType;
10use crate::metrics::RateMetric;
11use crate::storage::StorageManager;
12use crate::Glean;
13use crate::{CommonMetricData, TestGetValue};
14
15#[derive(Clone, Debug)]
23pub struct DenominatorMetric {
24 counter: CounterMetric,
25 numerators: Vec<RateMetric>,
26}
27
28impl MetricType for DenominatorMetric {
29 fn meta(&self) -> &CommonMetricDataInternal {
30 self.counter.meta()
31 }
32}
33
34impl DenominatorMetric {
35 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 pub fn add(&self, amount: i32) {
54 let metric = self.clone();
55 crate::launch_with_glean(move |glean| metric.add_sync(glean, amount))
56 }
57
58 #[doc(hidden)]
59 pub fn add_sync(&self, glean: &Glean, amount: i32) {
60 if !self.should_record(glean) {
61 return;
62 }
63
64 if amount <= 0 {
65 record_error(
66 glean,
67 self.meta(),
68 ErrorType::InvalidValue,
69 format!("Added negative or zero value {}", amount),
70 None,
71 );
72 return;
73 }
74
75 for num in &self.numerators {
76 num.add_to_denominator_sync(glean, amount);
77 }
78
79 glean
80 .storage()
81 .record_with(glean, self.counter.meta(), |old_value| match old_value {
82 Some(Metric::Counter(old_value)) => {
83 Metric::Counter(old_value.saturating_add(amount))
84 }
85 _ => Metric::Counter(amount),
86 })
87 }
88
89 #[doc(hidden)]
90 pub fn get_value<'a, S: Into<Option<&'a str>>>(
91 &self,
92 glean: &Glean,
93 ping_name: S,
94 ) -> Option<i32> {
95 let queried_ping_name = ping_name
96 .into()
97 .unwrap_or_else(|| &self.meta().inner.send_in_pings[0]);
98
99 match StorageManager.snapshot_metric_for_test(
100 glean.storage(),
101 queried_ping_name,
102 &self.meta().identifier(glean),
103 self.meta().inner.lifetime,
104 ) {
105 Some(Metric::Counter(i)) => Some(i),
106 _ => None,
107 }
108 }
109
110 pub fn test_get_num_recorded_errors(&self, error: ErrorType) -> i32 {
122 crate::block_on_dispatcher();
123
124 crate::core::with_glean(|glean| {
125 test_get_num_recorded_errors(glean, self.meta(), error).unwrap_or(0)
126 })
127 }
128}
129
130impl TestGetValue<i32> for DenominatorMetric {
131 fn test_get_value(&self, ping_name: Option<String>) -> Option<i32> {
146 crate::block_on_dispatcher();
147 crate::core::with_glean(|glean| self.get_value(glean, ping_name.as_deref()))
148 }
149}