From c05a4b5c1fc3fd98457622660a1372e9e5b318ab Mon Sep 17 00:00:00 2001 From: Lars Strojny Date: Thu, 19 Jan 2023 00:14:13 +0100 Subject: [PATCH 1/6] Replace HashMap with BTreeMap to sort metrics deterministically Signed-off-by: Lars Strojny Signed-off-by: Jean-Baptiste Skutnik --- examples/actix-web.rs | 4 +- examples/axum.rs | 4 +- examples/tide.rs | 4 +- src/encoding/text.rs | 96 +++++++++++++++++++++++++++++++---------- src/lib.rs | 4 +- src/metrics/exemplar.rs | 8 ++-- src/metrics/family.rs | 33 ++++++-------- 7 files changed, 99 insertions(+), 54 deletions(-) diff --git a/examples/actix-web.rs b/examples/actix-web.rs index a1ce8e79..515082d0 100644 --- a/examples/actix-web.rs +++ b/examples/actix-web.rs @@ -8,13 +8,13 @@ use prometheus_client::metrics::counter::Counter; use prometheus_client::metrics::family::Family; use prometheus_client::registry::Registry; -#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelValue)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, EncodeLabelValue)] pub enum Method { Get, Post, } -#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, EncodeLabelSet)] pub struct MethodLabels { pub method: Method, } diff --git a/examples/axum.rs b/examples/axum.rs index c3e81705..490996ed 100644 --- a/examples/axum.rs +++ b/examples/axum.rs @@ -13,13 +13,13 @@ use prometheus_client_derive_encode::{EncodeLabelSet, EncodeLabelValue}; use std::sync::Arc; use tokio::sync::Mutex; -#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelValue)] +#[derive(Clone, Debug, Ord, PartialOrd, PartialEq, Eq, EncodeLabelValue)] pub enum Method { Get, Post, } -#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)] +#[derive(Clone, Debug, Ord, PartialOrd, PartialEq, Eq, EncodeLabelSet)] pub struct MethodLabels { pub method: Method, } diff --git a/examples/tide.rs b/examples/tide.rs index 68cacac6..f90f6a45 100644 --- a/examples/tide.rs +++ b/examples/tide.rs @@ -44,13 +44,13 @@ async fn main() -> std::result::Result<(), std::io::Error> { Ok(()) } -#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)] +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, EncodeLabelSet)] struct Labels { method: Method, path: String, } -#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelValue)] +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, EncodeLabelValue)] enum Method { Get, Put, diff --git a/src/encoding/text.rs b/src/encoding/text.rs index 53377cdc..dcdb3261 100644 --- a/src/encoding/text.rs +++ b/src/encoding/text.rs @@ -37,16 +37,15 @@ //! assert_eq!(expected_msg, buffer); //! ``` -use crate::encoding::{ - EncodeExemplarTime, EncodeExemplarValue, EncodeLabelSet, NativeHistogram, NoLabelSet, +use crate::{ + encoding::{ + EncodeExemplarTime, EncodeExemplarValue, EncodeLabelSet, NativeHistogram, NoLabelSet, + }, + metrics::{MetricType, exemplar::Exemplar}, + registry::{Prefix, Registry, Unit}, }; -use crate::metrics::exemplar::Exemplar; -use crate::metrics::MetricType; -use crate::registry::{Prefix, Registry, Unit}; -use std::borrow::Cow; -use std::collections::HashMap; -use std::fmt::Write; +use std::{borrow::Cow, collections::HashMap, fmt::Write}; /// Encode both the metrics registered with the provided [`Registry`] and the /// EOF marker into the provided [`Write`]r using the OpenMetrics text format. @@ -759,17 +758,21 @@ impl std::fmt::Write for LabelValueEncoder<'_> { #[cfg(test)] mod tests { use super::*; - use crate::metrics::exemplar::HistogramWithExemplars; - use crate::metrics::family::Family; - use crate::metrics::gauge::Gauge; - use crate::metrics::histogram::{exponential_buckets, Histogram, NativeHistogramConfig}; - use crate::metrics::info::Info; - use crate::metrics::{counter::Counter, exemplar::CounterWithExemplar}; + use crate::metrics::{ + counter::Counter, + exemplar::{CounterWithExemplar, HistogramWithExemplars}, + family::Family, + gauge::Gauge, + histogram::{Histogram, NativeHistogramConfig, exponential_buckets}, + info::Info, + }; use pyo3::{prelude::*, types::PyModule}; - use std::borrow::Cow; - use std::fmt::Error; - use std::sync::atomic::{AtomicI32, AtomicU32}; - use std::time::{SystemTime, UNIX_EPOCH}; + use std::{ + borrow::Cow, + fmt::Error, + sync::atomic::{AtomicI32, AtomicU32}, + time::{SystemTime, UNIX_EPOCH}, + }; #[test] fn encode_counter() { @@ -916,8 +919,7 @@ mod tests { encode(&mut encoded, ®istry).unwrap(); - let expected = "# HELP my_prefix_my_counter_family My counter family.\n" - .to_owned() + let expected = "# HELP my_prefix_my_counter_family My counter family.\n".to_owned() + "# TYPE my_prefix_my_counter_family counter\n" + "my_prefix_my_counter_family_total{my_key=\"my_value\",method=\"GET\",status=\"200\"} 1\n" + "# EOF\n"; @@ -1020,7 +1022,7 @@ mod tests { Family::new_with_constructor(|| Histogram::new(exponential_buckets(1.0, 2.0, 10))); registry.register("my_histogram", "My histogram", family.clone()); - #[derive(Eq, PartialEq, Hash, Debug, Clone)] + #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone)] struct EmptyLabels {} impl EncodeLabelSet for EmptyLabels { @@ -1210,7 +1212,7 @@ mod tests { #[test] fn label_sets_can_be_composed() { - #[derive(Clone, Debug, Eq, Hash, PartialEq)] + #[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq)] struct Color(&'static str); impl EncodeLabelSet for Color { fn encode( @@ -1225,7 +1227,7 @@ mod tests { } } - #[derive(Clone, Debug, Eq, Hash, PartialEq)] + #[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq)] struct Size(&'static str); impl EncodeLabelSet for Size { fn encode( @@ -1373,4 +1375,52 @@ def parse(input): + "# EOF\n"; assert_eq!(expected, encoded); } + + #[test] + fn metrics_are_sorted_by_registration_order() { + let mut registry = Registry::default(); + let counter: Counter = Counter::default(); + let another_counter: Counter = Counter::default(); + registry.register("my_counter", "My counter", counter); + registry.register("another_counter", "Another counter", another_counter); + + let mut encoded = String::new(); + encode(&mut encoded, ®istry).unwrap(); + + let expected = "# HELP my_counter My counter.\n".to_owned() + + "# TYPE my_counter counter\n" + + "my_counter_total 0\n" + + "# HELP another_counter Another counter.\n" + + "# TYPE another_counter counter\n" + + "another_counter_total 0\n" + + "# EOF\n"; + assert_eq!(expected, encoded); + } + + #[test] + fn metric_family_is_sorted_by_registration_order() { + let mut registry = Registry::default(); + let gauge = Family::, Gauge>::default(); + registry.register("my_gauge", "My gauge", gauge.clone()); + + { + let gauge0 = gauge.get_or_create(&vec![("label".to_string(), "0".to_string())]); + gauge0.set(0); + } + + { + let gauge1 = gauge.get_or_create(&vec![("label".to_string(), "1".to_string())]); + gauge1.set(1); + } + + let mut encoded = String::new(); + encode(&mut encoded, ®istry).unwrap(); + + let expected = "# HELP my_gauge My gauge.\n".to_owned() + + "# TYPE my_gauge gauge\n" + + "my_gauge{label=\"0\"} 0\n" + + "my_gauge{label=\"1\"} 1\n" + + "# EOF\n"; + assert_eq!(expected, encoded); + } } diff --git a/src/lib.rs b/src/lib.rs index 9aab12f0..522e5fd4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,7 +31,7 @@ //! // //! // You could as well use `(String, String)` to represent a label set, //! // instead of the custom type below. -//! #[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)] +//! #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, EncodeLabelSet)] //! struct Labels { //! // Use your own enum types to represent label values. //! method: Method, @@ -39,7 +39,7 @@ //! path: String, //! }; //! -//! #[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelValue)] +//! #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, EncodeLabelValue)] //! enum Method { //! GET, //! PUT, diff --git a/src/metrics/exemplar.rs b/src/metrics/exemplar.rs index bc46e7ea..18745b0f 100644 --- a/src/metrics/exemplar.rs +++ b/src/metrics/exemplar.rs @@ -44,12 +44,12 @@ pub struct Exemplar { /// # use prometheus_client::metrics::histogram::exponential_buckets; /// # use prometheus_client::metrics::family::Family; /// # use prometheus_client_derive_encode::EncodeLabelSet; -/// #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug, Default)] +/// #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, EncodeLabelSet, Debug, Default)] /// pub struct ResultLabel { /// pub result: String, /// } /// -/// #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug, Default)] +/// #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, EncodeLabelSet, Debug, Default)] /// pub struct TraceLabel { /// pub trace_id: String, /// } @@ -187,12 +187,12 @@ where /// # use prometheus_client::metrics::histogram::exponential_buckets; /// # use prometheus_client::metrics::family::Family; /// # use prometheus_client::encoding::EncodeLabelSet; -/// #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug, Default)] +/// #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, EncodeLabelSet, Debug, Default)] /// pub struct ResultLabel { /// pub result: String, /// } /// -/// #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug, Default)] +/// #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, EncodeLabelSet, Debug, Default)] /// pub struct TraceLabel { /// pub trace_id: String, /// } diff --git a/src/metrics/family.rs b/src/metrics/family.rs index b81d394e..e1338754 100644 --- a/src/metrics/family.rs +++ b/src/metrics/family.rs @@ -6,8 +6,7 @@ use crate::encoding::{EncodeLabelSet, EncodeMetric, MetricEncoder}; use super::{MetricType, TypedMetric}; use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard, RwLockWriteGuard}; -use std::collections::HashMap; -use std::sync::Arc; +use std::{collections::BTreeMap, sync::Arc}; /// Representation of the OpenMetrics *MetricFamily* data type. /// @@ -68,12 +67,12 @@ use std::sync::Arc; /// # use std::io::Write; /// # /// # let mut registry = Registry::default(); -/// #[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)] +/// #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, EncodeLabelSet)] /// struct Labels { /// method: Method, /// }; /// -/// #[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelValue)] +/// #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, EncodeLabelValue)] /// enum Method { /// GET, /// PUT, @@ -99,9 +98,8 @@ use std::sync::Arc; /// # "# EOF\n"; /// # assert_eq!(expected, buffer); /// ``` -// TODO: Consider exposing hash algorithm. pub struct Family M> { - metrics: Arc>>, + metrics: Arc>>, /// Function that when called constructs a new metric. /// /// For most metric types this would simply be its [`Default`] @@ -168,7 +166,7 @@ impl M> MetricConstructor for F { } } -impl Default for Family { +impl Default for Family { fn default() -> Self { Self { metrics: Arc::new(RwLock::new(Default::default())), @@ -177,7 +175,7 @@ impl Default for Family { } } -impl Family { +impl Family { /// Create a metric family using a custom constructor to construct new /// metrics. /// @@ -207,12 +205,7 @@ impl Family { } } -impl> Family -where - S: Clone + std::hash::Hash + Eq, - M: Clone, - C: MetricConstructor, -{ +impl> Family { /// Access a metric with the given label set, creating it if one does not yet exist. /// /// ``` @@ -241,7 +234,7 @@ where } } -impl> Family { +impl> Family { /// Access a metric with the given label set, creating it if one does not /// yet exist. /// @@ -391,7 +384,7 @@ impl> Family RwLockReadGuard<'_, HashMap> { + pub(crate) fn read(&self) -> RwLockReadGuard<'_, BTreeMap> { self.metrics.read() } } @@ -411,7 +404,7 @@ impl TypedMetric for Family { impl EncodeMetric for Family where - S: Clone + std::hash::Hash + Eq + EncodeLabelSet, + S: Clone + Eq + Ord + EncodeLabelSet, M: EncodeMetric + TypedMetric, C: MetricConstructor, { @@ -436,8 +429,10 @@ where #[cfg(test)] mod tests { use super::*; - use crate::metrics::counter::Counter; - use crate::metrics::histogram::{exponential_buckets, Histogram}; + use crate::metrics::{ + counter::Counter, + histogram::{Histogram, exponential_buckets}, + }; #[test] fn counter_family() { From a448b841007bacfbbd2fd2deca8971f3ffa346da Mon Sep 17 00:00:00 2001 From: Lars Strojny Date: Thu, 19 Jan 2023 00:17:24 +0100 Subject: [PATCH 2/6] Remove Hash from tide example Signed-off-by: Lars Strojny Signed-off-by: Jean-Baptiste Skutnik --- examples/tide.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/tide.rs b/examples/tide.rs index f90f6a45..ede2363f 100644 --- a/examples/tide.rs +++ b/examples/tide.rs @@ -44,13 +44,13 @@ async fn main() -> std::result::Result<(), std::io::Error> { Ok(()) } -#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, EncodeLabelSet)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, EncodeLabelSet)] struct Labels { method: Method, path: String, } -#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, EncodeLabelValue)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, EncodeLabelValue)] enum Method { Get, Put, From 0575a56f28d3ab54313174298c920e8649eeb0b7 Mon Sep 17 00:00:00 2001 From: Lars Strojny Date: Thu, 19 Jan 2023 00:27:26 +0100 Subject: [PATCH 3/6] =?UTF-8?q?Let=E2=80=99s=20not=20lie=20in=20the=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lars Strojny Signed-off-by: Jean-Baptiste Skutnik --- src/encoding/text.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/encoding/text.rs b/src/encoding/text.rs index dcdb3261..882e6c95 100644 --- a/src/encoding/text.rs +++ b/src/encoding/text.rs @@ -1398,20 +1398,20 @@ def parse(input): } #[test] - fn metric_family_is_sorted_by_registration_order() { + fn metric_family_is_sorted_lexicographically() { let mut registry = Registry::default(); let gauge = Family::, Gauge>::default(); registry.register("my_gauge", "My gauge", gauge.clone()); - { - let gauge0 = gauge.get_or_create(&vec![("label".to_string(), "0".to_string())]); - gauge0.set(0); - } - - { - let gauge1 = gauge.get_or_create(&vec![("label".to_string(), "1".to_string())]); - gauge1.set(1); - } + gauge + .get_or_create(&vec![("label".to_string(), "0".to_string())]) + .set(0); + gauge + .get_or_create(&vec![("label".to_string(), "2".to_string())]) + .set(2); + gauge + .get_or_create(&vec![("label".to_string(), "1".to_string())]) + .set(1); let mut encoded = String::new(); encode(&mut encoded, ®istry).unwrap(); @@ -1420,6 +1420,7 @@ def parse(input): + "# TYPE my_gauge gauge\n" + "my_gauge{label=\"0\"} 0\n" + "my_gauge{label=\"1\"} 1\n" + + "my_gauge{label=\"2\"} 2\n" + "# EOF\n"; assert_eq!(expected, encoded); } From cb771e1f0c561b6ff513727630f5f3dabd1815b9 Mon Sep 17 00:00:00 2001 From: Lars Strojny Date: Thu, 19 Jan 2023 09:08:46 +0100 Subject: [PATCH 4/6] Require Ord consistently Signed-off-by: Lars Strojny Signed-off-by: Jean-Baptiste Skutnik --- src/metrics/family.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/metrics/family.rs b/src/metrics/family.rs index e1338754..d5bb3d5e 100644 --- a/src/metrics/family.rs +++ b/src/metrics/family.rs @@ -166,7 +166,7 @@ impl M> MetricConstructor for F { } } -impl Default for Family { +impl Default for Family { fn default() -> Self { Self { metrics: Arc::new(RwLock::new(Default::default())), @@ -175,7 +175,7 @@ impl Default for Family { } } -impl Family { +impl Family { /// Create a metric family using a custom constructor to construct new /// metrics. /// From beafca794314823f0ea22d346a2aa0214419817b Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Skutnik Date: Mon, 11 Aug 2025 12:29:43 +0200 Subject: [PATCH 5/6] Update benches Signed-off-by: Jean-Baptiste Skutnik --- benches/encoding/text.rs | 6 +++--- benches/family.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/benches/encoding/text.rs b/benches/encoding/text.rs index 52b13f4e..31c5ced0 100644 --- a/benches/encoding/text.rs +++ b/benches/encoding/text.rs @@ -10,21 +10,21 @@ use std::fmt::Write; pub fn text(c: &mut Criterion) { c.bench_function("encode", |b| { - #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug)] + #[derive(Clone, Ord, PartialOrd, PartialEq, Eq, EncodeLabelSet, Debug)] struct Labels { method: Method, status: Status, some_number: u64, } - #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelValue, Debug)] + #[derive(Clone, Ord, PartialOrd, PartialEq, Eq, EncodeLabelValue, Debug)] enum Method { Get, #[allow(dead_code)] Put, } - #[derive(Clone, Hash, PartialEq, Eq, Debug)] + #[derive(Clone, Ord, PartialOrd, PartialEq, Eq, Debug)] enum Status { Two, #[allow(dead_code)] diff --git a/benches/family.rs b/benches/family.rs index bc08df3c..feea9a9f 100644 --- a/benches/family.rs +++ b/benches/family.rs @@ -43,20 +43,20 @@ pub fn family(c: &mut Criterion) { }); c.bench_function("counter family with custom type label set", |b| { - #[derive(Clone, Hash, PartialEq, Eq)] + #[derive(Clone, Ord, PartialOrd, PartialEq, Eq)] struct Labels { method: Method, status: Status, } - #[derive(Clone, Hash, PartialEq, Eq)] + #[derive(Clone, Ord, PartialOrd, PartialEq, Eq)] enum Method { Get, #[allow(dead_code)] Put, } - #[derive(Clone, Hash, PartialEq, Eq)] + #[derive(Clone, Ord, PartialOrd, PartialEq, Eq)] enum Status { Two, #[allow(dead_code)] From a2147a781ec50a5f6b8005d412070a3832617d21 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Skutnik Date: Thu, 9 Jul 2026 19:03:31 +0200 Subject: [PATCH 6/6] Add Ord to example --- benches/encoding/proto.rs | 24 ++++++++++++++---------- derive-encode/tests/lib.rs | 32 ++++++++++++++++---------------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/benches/encoding/proto.rs b/benches/encoding/proto.rs index 5f62eedd..ec571318 100644 --- a/benches/encoding/proto.rs +++ b/benches/encoding/proto.rs @@ -1,36 +1,40 @@ // Benchmark inspired by // https://github.com/tikv/rust-prometheus/blob/ab1ca7285d3463504381a5025ae1951e020d6796/benches/text_encoder.rs:write -use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use prometheus_client::encoding::prometheus_protobuf; -use prometheus_client::metrics::counter::Counter; -use prometheus_client::metrics::family::Family; -use prometheus_client::metrics::histogram::{exponential_buckets, Histogram}; -use prometheus_client::registry::Registry; +use criterion::{Criterion, black_box, criterion_group, criterion_main}; +use prometheus_client::{ + encoding::prometheus_protobuf, + metrics::{ + counter::Counter, + family::Family, + histogram::{Histogram, exponential_buckets}, + }, + registry::Registry, +}; use prometheus_client_derive_encode::{EncodeLabelSet, EncodeLabelValue}; pub fn proto(c: &mut Criterion) { c.bench_function("encode", |b| { - #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug)] + #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug, PartialOrd, Ord)] struct CounterLabels { path: String, method: Method, some_number: u64, } - #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelValue, Debug)] + #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelValue, Debug, PartialOrd, Ord)] enum Method { Get, #[allow(dead_code)] Put, } - #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug)] + #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug, PartialOrd, Ord)] struct HistogramLabels { region: Region, } - #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelValue, Debug)] + #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelValue, Debug, PartialOrd, Ord)] enum Region { Africa, #[allow(dead_code)] diff --git a/derive-encode/tests/lib.rs b/derive-encode/tests/lib.rs index ec30a562..5fa1320e 100644 --- a/derive-encode/tests/lib.rs +++ b/derive-encode/tests/lib.rs @@ -1,18 +1,18 @@ use std::sync::Arc; -use prometheus_client::encoding::text::encode; -use prometheus_client::encoding::{EncodeLabelSet, EncodeLabelValue}; -use prometheus_client::metrics::counter::Counter; -use prometheus_client::metrics::family::Family; -use prometheus_client::registry::Registry; +use prometheus_client::{ + encoding::{EncodeLabelSet, EncodeLabelValue, text::encode}, + metrics::{counter::Counter, family::Family}, + registry::Registry, +}; -#[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug)] +#[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug, PartialOrd, Ord)] struct Labels { method: Method, path: String, } -#[derive(Clone, Hash, PartialEq, Eq, EncodeLabelValue, Debug)] +#[derive(Clone, Hash, PartialEq, Eq, EncodeLabelValue, Debug, PartialOrd, Ord)] enum Method { Get, #[allow(dead_code)] @@ -47,11 +47,11 @@ fn basic_flow() { mod protobuf { use crate::{Labels, Method}; - use prometheus_client::encoding::prometheus_protobuf::encode; - use prometheus_client::encoding::prometheus_protobuf::prometheus_data_model; - use prometheus_client::metrics::counter::Counter; - use prometheus_client::metrics::family::Family; - use prometheus_client::registry::Registry; + use prometheus_client::{ + encoding::prometheus_protobuf::{encode, prometheus_data_model}, + metrics::{counter::Counter, family::Family}, + registry::Registry, + }; #[test] fn structs() { @@ -106,7 +106,7 @@ mod protobuf { #[test] fn remap_keyword_identifiers() { - #[derive(EncodeLabelSet, Hash, Clone, Eq, PartialEq, Debug)] + #[derive(EncodeLabelSet, Hash, Clone, Eq, PartialEq, Debug, PartialOrd, Ord)] struct Labels { // `r#type` is problematic as `r#` is not a valid OpenMetrics label name // but one needs to use keyword identifier syntax (aka. raw identifiers) @@ -137,7 +137,7 @@ fn remap_keyword_identifiers() { #[test] fn arc_string() { - #[derive(EncodeLabelSet, Hash, Clone, Eq, PartialEq, Debug)] + #[derive(EncodeLabelSet, Hash, Clone, Eq, PartialEq, Debug, PartialOrd, Ord)] struct Labels { client_id: Arc, } @@ -167,12 +167,12 @@ fn arc_string() { #[test] fn flatten() { - #[derive(EncodeLabelSet, Hash, Clone, Eq, PartialEq, Debug)] + #[derive(EncodeLabelSet, Hash, Clone, Eq, PartialEq, Debug, PartialOrd, Ord)] struct CommonLabels { a: u64, b: u64, } - #[derive(EncodeLabelSet, Hash, Clone, Eq, PartialEq, Debug)] + #[derive(EncodeLabelSet, Hash, Clone, Eq, PartialEq, Debug, PartialOrd, Ord)] struct Labels { unique: u64, #[prometheus(flatten)]