glean_core/metrics/
rate.rs1use crate::common_metric_data::CommonMetricDataInternal;
6use crate::error_recording::{record_error, test_get_num_recorded_errors, ErrorType};
7use crate::metrics::Metric;
8use crate::metrics::MetricType;
9use crate::storage::StorageManager;
10use crate::CommonMetricData;
11use crate::Glean;
12
13#[derive(Debug, Clone, Eq, PartialEq)]
15pub struct Rate {
16 pub numerator: i32,
18 pub denominator: i32,
20}
21
22impl From<(i32, i32)> for Rate {
23 fn from((num, den): (i32, i32)) -> Self {
24 Self {
25 numerator: num,
26 denominator: den,
27 }
28 }
29}
30
31#[derive(Clone, Debug)]
39pub struct RateMetric {
40 meta: CommonMetricDataInternal,
41}
42
43impl MetricType for RateMetric {
44 fn meta(&self) -> &CommonMetricDataInternal {
45 &self.meta
46 }
47}
48
49impl RateMetric {
54 pub fn new(meta: CommonMetricData) -> Self {
56 Self { meta: meta.into() }
57 }
58
59 pub fn add_to_numerator(&self, amount: i32) {
70 let metric = self.clone();
71 crate::launch_with_glean(move |glean| metric.add_to_numerator_sync(glean, amount))
72 }
73
74 #[doc(hidden)]
75 pub fn add_to_numerator_sync(&self, glean: &Glean, amount: i32) {
76 if !self.should_record(glean) {
77 return;
78 }
79
80 if amount < 0 {
81 record_error(
82 glean,
83 &self.meta,
84 ErrorType::InvalidValue,
85 format!("Added negative value {} to numerator", amount),
86 None,
87 );
88 return;
89 }
90
91 glean
92 .storage()
93 .record_with(glean, &self.meta, |old_value| match old_value {
94 Some(Metric::Rate(num, den)) => Metric::Rate(num.saturating_add(amount), den),
95 _ => Metric::Rate(amount, 0), });
97 }
98
99 pub fn add_to_denominator(&self, amount: i32) {
110 let metric = self.clone();
111 crate::launch_with_glean(move |glean| metric.add_to_denominator_sync(glean, amount))
112 }
113
114 #[doc(hidden)]
115 pub fn add_to_denominator_sync(&self, glean: &Glean, amount: i32) {
116 if !self.should_record(glean) {
117 return;
118 }
119
120 if amount < 0 {
121 record_error(
122 glean,
123 &self.meta,
124 ErrorType::InvalidValue,
125 format!("Added negative value {} to denominator", amount),
126 None,
127 );
128 return;
129 }
130
131 glean
132 .storage()
133 .record_with(glean, &self.meta, |old_value| match old_value {
134 Some(Metric::Rate(num, den)) => Metric::Rate(num, den.saturating_add(amount)),
135 _ => Metric::Rate(0, amount),
136 });
137 }
138
139 pub fn test_get_value(&self, ping_name: Option<String>) -> Option<Rate> {
154 crate::block_on_dispatcher();
155 crate::core::with_glean(|glean| self.get_value(glean, ping_name.as_deref()))
156 }
157
158 #[doc(hidden)]
160 pub fn get_value<'a, S: Into<Option<&'a str>>>(
161 &self,
162 glean: &Glean,
163 ping_name: S,
164 ) -> Option<Rate> {
165 let queried_ping_name = ping_name
166 .into()
167 .unwrap_or_else(|| &self.meta().inner.send_in_pings[0]);
168
169 match StorageManager.snapshot_metric_for_test(
170 glean.storage(),
171 queried_ping_name,
172 &self.meta.identifier(glean),
173 self.meta.inner.lifetime,
174 ) {
175 Some(Metric::Rate(n, d)) => Some((n, d).into()),
176 _ => None,
177 }
178 }
179
180 pub fn test_get_num_recorded_errors(&self, error: ErrorType) -> i32 {
192 crate::block_on_dispatcher();
193
194 crate::core::with_glean(|glean| {
195 test_get_num_recorded_errors(glean, self.meta(), error).unwrap_or(0)
196 })
197 }
198}