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::Glean;
12use crate::{CommonMetricData, TestGetValue};
13
14#[derive(Clone, Debug)]
22pub struct DenominatorMetric {
23 counter: CounterMetric,
24 numerators: Vec<RateMetric>,
25}
26
27impl MetricType for DenominatorMetric {
28 fn meta(&self) -> &CommonMetricDataInternal {
29 self.counter.meta()
30 }
31}
32
33impl DenominatorMetric {
34 pub fn new(meta: CommonMetricData, numerators: Vec<CommonMetricData>) -> Self {
36 Self {
37 counter: CounterMetric::new(meta),
38 numerators: numerators.into_iter().map(RateMetric::new).collect(),
39 }
40 }
41
42 pub fn add(&self, amount: i32) {
53 let metric = self.clone();
54 crate::launch_with_glean(move |glean| metric.add_sync(glean, amount))
55 }
56
57 #[doc(hidden)]
58 pub fn add_sync(&self, glean: &Glean, amount: i32) {
59 if !self.should_record(glean) {
60 return;
61 }
62
63 if amount <= 0 {
64 record_error(
65 glean,
66 self.meta(),
67 ErrorType::InvalidValue,
68 format!("Added negative or zero value {}", amount),
69 None,
70 );
71 return;
72 }
73
74 for num in &self.numerators {
75 num.add_to_denominator_sync(glean, amount);
76 }
77
78 glean
79 .storage()
80 .record_with(glean, self.counter.meta(), |old_value| match old_value {
81 Some(Metric::Counter(old_value)) => {
82 Metric::Counter(old_value.saturating_add(amount))
83 }
84 _ => Metric::Counter(amount),
85 })
86 }
87
88 #[doc(hidden)]
89 pub fn get_value<'a, S: Into<Option<&'a str>>>(
90 &self,
91 glean: &Glean,
92 ping_name: S,
93 ) -> Option<i32> {
94 let queried_ping_name = ping_name
95 .into()
96 .unwrap_or_else(|| &self.meta().inner.send_in_pings[0]);
97
98 match glean.storage().get_metric(self.meta(), queried_ping_name) {
99 Some(Metric::Counter(i)) => Some(i),
100 _ => None,
101 }
102 }
103
104 pub fn test_get_num_recorded_errors(&self, error: ErrorType) -> i32 {
116 crate::block_on_dispatcher();
117
118 crate::core::with_glean(|glean| {
119 test_get_num_recorded_errors(glean, self.meta(), error).unwrap_or(0)
120 })
121 }
122}
123
124impl TestGetValue for DenominatorMetric {
125 type Output = i32;
126
127 fn test_get_value(&self, ping_name: Option<String>) -> Option<i32> {
142 crate::block_on_dispatcher();
143 crate::core::with_glean(|glean| self.get_value(glean, ping_name.as_deref()))
144 }
145}