From 7150bbae796541e8f68423cf0a6a5ac80e73a3c8 Mon Sep 17 00:00:00 2001 From: Adam Chalmers Date: Mon, 19 Sep 2022 17:32:36 -0500 Subject: [PATCH] feature: Impl TypedMetric for WithExemplar types, so a metric can use both families and exemplars Fixes issue #95. Signed-off-by: Adam Chalmers --- CHANGELOG.md | 2 ++ src/metrics/exemplar.rs | 70 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a554904b..0532a102 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 set from a family. See [PR 85]. - Added a `clear` method to `Family` to allow the removal of all label sets from a family. See [PR 85]. +- Impl `TypedMetric` for `CounterWithExemplar` and `HistogramWithExemplar`, so that they can be used with `Family`. See [PR 96]. ### Changed @@ -19,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [PR 83]: https://github.com/prometheus/client_rust/pull/83 [PR 85]: https://github.com/prometheus/client_rust/pull/85 +[PR 96]: https://github.com/prometheus/client_rust/pull/96 ## [0.18.0] diff --git a/src/metrics/exemplar.rs b/src/metrics/exemplar.rs index 84462003..a2cffc03 100644 --- a/src/metrics/exemplar.rs +++ b/src/metrics/exemplar.rs @@ -4,6 +4,7 @@ use super::counter::{self, Counter}; use super::histogram::Histogram; +use super::{MetricType, TypedMetric}; use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard}; use std::collections::HashMap; #[cfg(any(target_arch = "mips", target_arch = "powerpc"))] @@ -31,12 +32,45 @@ pub struct Exemplar { /// counter_with_exemplar.inc_by(1, Some(vec![("user_id".to_string(), "42".to_string())])); /// let _value: (u64, _) = counter_with_exemplar.get(); /// ``` +/// You can also use exemplars with families. Just wrap the exemplar in a Family. +/// ``` +/// # use prometheus_client::metrics::exemplar::CounterWithExemplar; +/// # use prometheus_client::metrics::histogram::exponential_buckets; +/// # use prometheus_client::metrics::family::Family; +/// # use prometheus_client_derive_encode::Encode; +/// #[derive(Clone, Hash, PartialEq, Eq, Encode, Debug, Default)] +/// pub struct ResultLabel { +/// pub result: String, +/// } +/// +/// #[derive(Clone, Hash, PartialEq, Eq, Encode, Debug, Default)] +/// pub struct TraceLabel { +/// pub trace_id: String, +/// } +/// +/// let latency: Family> = Family::default(); +/// +/// latency +/// .get_or_create(&ResultLabel { +/// result: "success".to_owned(), +/// }) +/// .inc_by( +/// 1, +/// Some(TraceLabel { +/// trace_id: "3a2f90c9f80b894f".to_owned(), +/// }), +/// ); +/// ``` #[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] #[derive(Debug)] pub struct CounterWithExemplar { pub(crate) inner: Arc>>, } +impl TypedMetric for CounterWithExemplar { + const TYPE: MetricType = MetricType::Counter; +} + /// Open Metrics [`Counter`] with an [`Exemplar`] to both measure discrete /// events and track references to data outside of the metric set. #[cfg(any(target_arch = "mips", target_arch = "powerpc"))] @@ -122,12 +156,48 @@ impl> CounterWithExemplar { /// let histogram = HistogramWithExemplars::new(exponential_buckets(1.0, 2.0, 10)); /// histogram.observe(4.2, Some(vec![("user_id".to_string(), "42".to_string())])); /// ``` +/// You can also use exemplars with families. Just wrap the exemplar in a Family. +/// ``` +/// # use prometheus_client::metrics::exemplar::HistogramWithExemplars; +/// # use prometheus_client::metrics::histogram::exponential_buckets; +/// # use prometheus_client::metrics::family::Family; +/// # use prometheus_client_derive_encode::Encode; +/// #[derive(Clone, Hash, PartialEq, Eq, Encode, Debug, Default)] +/// pub struct ResultLabel { +/// pub result: String, +/// } +/// +/// #[derive(Clone, Hash, PartialEq, Eq, Encode, Debug, Default)] +/// pub struct TraceLabel { +/// pub trace_id: String, +/// } +/// +/// let latency: Family> = +/// Family::new_with_constructor(|| { +/// HistogramWithExemplars::new(exponential_buckets(1.0, 2.0, 10)) +/// }); +/// +/// latency +/// .get_or_create(&ResultLabel { +/// result: "success".to_owned(), +/// }) +/// .observe( +/// 0.001345422, +/// Some(TraceLabel { +/// trace_id: "3a2f90c9f80b894f".to_owned(), +/// }), +/// ); +/// ``` #[derive(Debug)] pub struct HistogramWithExemplars { // TODO: Not ideal, as Histogram has a Mutex as well. pub(crate) inner: Arc>>, } +impl TypedMetric for HistogramWithExemplars { + const TYPE: MetricType = MetricType::Histogram; +} + impl Clone for HistogramWithExemplars { fn clone(&self) -> Self { Self {