Skip to content

Commit

Permalink
Implement Atomic<u64> for AtomicU64 for gauges
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
bobrik committed Sep 21, 2024
1 parent ad05f0f commit 8b3b539
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,16 @@ impl EncodeGaugeValue for i64 {
}
}

impl EncodeGaugeValue for u64 {
fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error> {
if *self == u64::MAX {
return Err(std::fmt::Error);
}

encoder.encode_i64(*self as i64)
}
}

impl EncodeGaugeValue for f64 {
fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error> {
encoder.encode_f64(*self)
Expand Down
37 changes: 37 additions & 0 deletions src/encoding/protobuf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,7 @@ mod tests {
use std::borrow::Cow;
use std::collections::HashSet;
use std::sync::atomic::AtomicI64;
use std::sync::atomic::AtomicU64;

#[test]
fn encode_counter_int() {
Expand Down Expand Up @@ -600,6 +601,42 @@ mod tests {
}
}

#[test]
fn encode_gauge_u64_normal() {
let mut registry = Registry::default();
let gauge = Gauge::<u64, AtomicU64>::default();
registry.register("my_gauge", "My gauge", gauge.clone());
gauge.set(12345);

let metric_set = encode(&registry).unwrap();
let family = metric_set.metric_families.first().unwrap();
assert_eq!("my_gauge", family.name);
assert_eq!("My gauge.", family.help);

assert_eq!(
openmetrics_data_model::MetricType::Gauge as i32,
extract_metric_type(&metric_set)
);

match extract_metric_point_value(&metric_set) {
openmetrics_data_model::metric_point::Value::GaugeValue(value) => {
let expected = openmetrics_data_model::gauge_value::Value::IntValue(12345);
assert_eq!(Some(expected), value.value);
}
_ => panic!("wrong value type"),
}
}

#[test]
fn encode_gauge_u64_max() {
let mut registry = Registry::default();
let gauge = Gauge::<u64, AtomicU64>::default();
registry.register("my_gauge", "My gauge", gauge.clone());
gauge.set(u64::MAX);

assert!(encode(&registry).is_err());
}

#[test]
fn encode_counter_family() {
let mut registry = Registry::default();
Expand Down
27 changes: 27 additions & 0 deletions src/metrics/gauge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,33 @@ impl Atomic<i64> for AtomicI64 {
}
}

#[cfg(target_has_atomic = "64")]
impl Atomic<u64> for AtomicU64 {
fn inc(&self) -> u64 {
self.inc_by(1)
}

fn inc_by(&self, v: u64) -> u64 {
self.fetch_add(v, Ordering::Relaxed)
}

fn dec(&self) -> u64 {
self.dec_by(1)
}

fn dec_by(&self, v: u64) -> u64 {
self.fetch_sub(v, Ordering::Relaxed)
}

fn set(&self, v: u64) -> u64 {
self.swap(v, Ordering::Relaxed)
}

fn get(&self) -> u64 {
self.load(Ordering::Relaxed)
}
}

#[cfg(target_has_atomic = "64")]
impl Atomic<f64> for AtomicU64 {
fn inc(&self) -> f64 {
Expand Down

0 comments on commit 8b3b539

Please sign in to comment.