Skip to content

Commit 384adf9

Browse files
committed
fix: insert metric automatically if it does not exist
1 parent 4fc8fa1 commit 384adf9

File tree

1 file changed

+48
-8
lines changed

1 file changed

+48
-8
lines changed

packages/primitives/src/metrics/metric_collection.rs

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use super::counter::Counter;
77
use super::gauge::Gauge;
88
use super::label_set::LabelSet;
99
use super::metric::Metric;
10+
use super::sample::Sample;
1011
use super::MetricName;
1112
use crate::metrics::sample_collection::SampleCollection;
1213
use crate::DurationSinceUnixEpoch;
@@ -182,13 +183,30 @@ impl<T> MetricKindCollection<T> {
182183
}
183184

184185
impl MetricKindCollection<Counter> {
186+
/// # Panics
187+
///
188+
/// Panics if the metric name already exists in the collection.
185189
pub fn increment(&mut self, name: &MetricName, labels: &LabelSet, time: DurationSinceUnixEpoch) {
186-
if let Some(metric) = self.metrics.get_mut(name) {
187-
if let Some(sample) = metric.samples.get_mut(labels) {
188-
sample.value.increment(1);
189-
sample.update_at = time;
190-
}
190+
// Create the metric if it doesn't exist
191+
if !self.metrics.contains_key(name) {
192+
let new_metric = Metric {
193+
name: name.clone(),
194+
samples: SampleCollection { samples: HashMap::new() },
195+
};
196+
self.metrics.insert(name.clone(), new_metric);
191197
}
198+
199+
let metric = self.metrics.get_mut(name).unwrap();
200+
201+
// Use entry API to handle existing or new sample
202+
let sample = metric.samples.samples.entry(labels.clone()).or_insert_with(|| Sample {
203+
value: Counter::new(0),
204+
update_at: time,
205+
labels: labels.clone(),
206+
});
207+
208+
sample.value.increment(1);
209+
sample.update_at = time;
192210
}
193211

194212
#[must_use]
@@ -201,13 +219,35 @@ impl MetricKindCollection<Counter> {
201219
}
202220

203221
impl MetricKindCollection<Gauge> {
222+
/// # Panics
223+
///
224+
/// Panics if the metric name already exists in the collection.
204225
pub fn set(&mut self, name: &MetricName, labels: &LabelSet, value: f64, time: DurationSinceUnixEpoch) {
205-
if let Some(metric) = self.metrics.get_mut(name) {
206-
// Direct hashmap lookup
207-
if let Some(sample) = metric.samples.get_mut(labels) {
226+
// Create the metric if it doesn't exist
227+
if !self.metrics.contains_key(name) {
228+
let new_metric = Metric {
229+
name: name.clone(),
230+
samples: SampleCollection { samples: HashMap::new() },
231+
};
232+
self.metrics.insert(name.clone(), new_metric);
233+
}
234+
235+
let metric = self.metrics.get_mut(name).unwrap();
236+
237+
// Use entry API to handle existing or new sample
238+
match metric.samples.samples.entry(labels.clone()) {
239+
std::collections::hash_map::Entry::Occupied(mut entry) => {
240+
let sample = entry.get_mut();
208241
sample.value.set(value);
209242
sample.update_at = time;
210243
}
244+
std::collections::hash_map::Entry::Vacant(entry) => {
245+
entry.insert(Sample {
246+
value: Gauge::new(value),
247+
update_at: time,
248+
labels: labels.clone(),
249+
});
250+
}
211251
}
212252
}
213253

0 commit comments

Comments
 (0)