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::Glean;
11use crate::{CommonMetricData, TestGetValue};
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 #[doc(hidden)]
141 pub fn get_value<'a, S: Into<Option<&'a str>>>(
142 &self,
143 glean: &Glean,
144 ping_name: S,
145 ) -> Option<Rate> {
146 let queried_ping_name = ping_name
147 .into()
148 .unwrap_or_else(|| &self.meta().inner.send_in_pings[0]);
149
150 match StorageManager.snapshot_metric_for_test(
151 glean.storage(),
152 queried_ping_name,
153 &self.meta.identifier(glean),
154 self.meta.inner.lifetime,
155 ) {
156 Some(Metric::Rate(n, d)) => Some((n, d).into()),
157 _ => None,
158 }
159 }
160
161 pub fn test_get_num_recorded_errors(&self, error: ErrorType) -> i32 {
173 crate::block_on_dispatcher();
174
175 crate::core::with_glean(|glean| {
176 test_get_num_recorded_errors(glean, self.meta(), error).unwrap_or(0)
177 })
178 }
179}
180
181impl TestGetValue<Rate> for RateMetric {
182 fn test_get_value(&self, ping_name: Option<String>) -> Option<Rate> {
197 crate::block_on_dispatcher();
198 crate::core::with_glean(|glean| self.get_value(glean, ping_name.as_deref()))
199 }
200}