Skip to content

Commit 8b3b539

Browse files
committed
Implement Atomic<u64> for AtomicU64 for gauges
Between forcing end users to do endless `as i64` for things that are clearly `u64` and having one error case for rarely used protobuf when a gauge is set to `u64::MAX`, the latter seems like the right choice. Signed-off-by: Ivan Babrou <[email protected]>
1 parent ad05f0f commit 8b3b539

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

src/encoding.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,16 @@ impl EncodeGaugeValue for i64 {
568568
}
569569
}
570570

571+
impl EncodeGaugeValue for u64 {
572+
fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error> {
573+
if *self == u64::MAX {
574+
return Err(std::fmt::Error);
575+
}
576+
577+
encoder.encode_i64(*self as i64)
578+
}
579+
}
580+
571581
impl EncodeGaugeValue for f64 {
572582
fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error> {
573583
encoder.encode_f64(*self)

src/encoding/protobuf.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,7 @@ mod tests {
453453
use std::borrow::Cow;
454454
use std::collections::HashSet;
455455
use std::sync::atomic::AtomicI64;
456+
use std::sync::atomic::AtomicU64;
456457

457458
#[test]
458459
fn encode_counter_int() {
@@ -600,6 +601,42 @@ mod tests {
600601
}
601602
}
602603

604+
#[test]
605+
fn encode_gauge_u64_normal() {
606+
let mut registry = Registry::default();
607+
let gauge = Gauge::<u64, AtomicU64>::default();
608+
registry.register("my_gauge", "My gauge", gauge.clone());
609+
gauge.set(12345);
610+
611+
let metric_set = encode(&registry).unwrap();
612+
let family = metric_set.metric_families.first().unwrap();
613+
assert_eq!("my_gauge", family.name);
614+
assert_eq!("My gauge.", family.help);
615+
616+
assert_eq!(
617+
openmetrics_data_model::MetricType::Gauge as i32,
618+
extract_metric_type(&metric_set)
619+
);
620+
621+
match extract_metric_point_value(&metric_set) {
622+
openmetrics_data_model::metric_point::Value::GaugeValue(value) => {
623+
let expected = openmetrics_data_model::gauge_value::Value::IntValue(12345);
624+
assert_eq!(Some(expected), value.value);
625+
}
626+
_ => panic!("wrong value type"),
627+
}
628+
}
629+
630+
#[test]
631+
fn encode_gauge_u64_max() {
632+
let mut registry = Registry::default();
633+
let gauge = Gauge::<u64, AtomicU64>::default();
634+
registry.register("my_gauge", "My gauge", gauge.clone());
635+
gauge.set(u64::MAX);
636+
637+
assert!(encode(&registry).is_err());
638+
}
639+
603640
#[test]
604641
fn encode_counter_family() {
605642
let mut registry = Registry::default();

src/metrics/gauge.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,33 @@ impl Atomic<i64> for AtomicI64 {
213213
}
214214
}
215215

216+
#[cfg(target_has_atomic = "64")]
217+
impl Atomic<u64> for AtomicU64 {
218+
fn inc(&self) -> u64 {
219+
self.inc_by(1)
220+
}
221+
222+
fn inc_by(&self, v: u64) -> u64 {
223+
self.fetch_add(v, Ordering::Relaxed)
224+
}
225+
226+
fn dec(&self) -> u64 {
227+
self.dec_by(1)
228+
}
229+
230+
fn dec_by(&self, v: u64) -> u64 {
231+
self.fetch_sub(v, Ordering::Relaxed)
232+
}
233+
234+
fn set(&self, v: u64) -> u64 {
235+
self.swap(v, Ordering::Relaxed)
236+
}
237+
238+
fn get(&self) -> u64 {
239+
self.load(Ordering::Relaxed)
240+
}
241+
}
242+
216243
#[cfg(target_has_atomic = "64")]
217244
impl Atomic<f64> for AtomicU64 {
218245
fn inc(&self) -> f64 {

0 commit comments

Comments
 (0)