Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

src/registry: Use dynamic dispatch and remove type parameter M #100

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- Always use dynamic dispatch on Registry, i.e. remove generic type parameter `M` from `Registry`.

- Move`Encode` trait from `prometheus_client::encoding::text` to `prometheus_client::encoding`. See [PR 83].

[PR 83]: https://github.com/prometheus/client_rust/pull/83
Expand Down
12 changes: 5 additions & 7 deletions examples/actix-web.rs
Expand Up @@ -7,13 +7,13 @@ use prometheus_client::metrics::counter::Counter;
use prometheus_client::metrics::family::Family;
use prometheus_client::registry::Registry;

#[derive(Clone, Hash, PartialEq, Eq, Encode)]
#[derive(Clone, Debug, Hash, PartialEq, Eq, Encode)]
pub enum Method {
Get,
Post,
}

#[derive(Clone, Hash, PartialEq, Eq, Encode)]
#[derive(Clone, Debug, Hash, PartialEq, Eq, Encode)]
pub struct MethodLabels {
pub method: Method,
}
Expand Down Expand Up @@ -55,11 +55,9 @@ async fn main() -> std::io::Result<()> {
let mut state = AppState {
registry: Registry::default(),
};
state.registry.register(
"requests",
"Count of requests",
Box::new(metrics.requests.clone()),
);
state
.registry
.register("requests", "Count of requests", metrics.requests.clone());
let state = web::Data::new(Mutex::new(state));

HttpServer::new(move || {
Expand Down
1 change: 1 addition & 0 deletions examples/custom-metric.rs
Expand Up @@ -7,6 +7,7 @@ use prometheus_client::registry::Registry;
/// Related to the concept of "Custom Collectors" in other implementations.
///
/// [`MyCustomMetric`] generates and encodes a random number on each scrape.
#[derive(Debug)]
struct MyCustomMetric {}

impl EncodeMetric for MyCustomMetric {
Expand Down
6 changes: 3 additions & 3 deletions examples/tide.rs
Expand Up @@ -44,21 +44,21 @@ async fn main() -> std::result::Result<(), std::io::Error> {
Ok(())
}

#[derive(Clone, Hash, PartialEq, Eq, Encode)]
#[derive(Clone, Debug, Hash, PartialEq, Eq, Encode)]
struct Labels {
method: Method,
path: String,
}

#[derive(Clone, Hash, PartialEq, Eq, Encode)]
#[derive(Clone, Debug, Hash, PartialEq, Eq, Encode)]
enum Method {
Get,
Put,
}

#[derive(Clone)]
struct State {
registry: Arc<Registry<Family<Labels, Counter>>>,
registry: Arc<Registry>,
}

#[derive(Default)]
Expand Down
12 changes: 4 additions & 8 deletions src/encoding/proto.rs
Expand Up @@ -47,7 +47,7 @@ pub use prometheus_client_derive_encode::*;

/// Encode the metrics registered with the provided [`Registry`] into MetricSet
/// using the OpenMetrics protobuf format.
pub fn encode<M>(registry: &Registry<M>) -> openmetrics_data_model::MetricSet
pub fn encode<M>(registry: &Registry) -> openmetrics_data_model::MetricSet
where
M: EncodeMetric,
{
Expand All @@ -57,7 +57,8 @@ where
let mut family = openmetrics_data_model::MetricFamily {
name: desc.name().to_string(),
r#type: {
let metric_type: openmetrics_data_model::MetricType = metric.metric_type().into();
let metric_type: openmetrics_data_model::MetricType =
EncodeMetric::metric_type(metric.as_ref()).into();
metric_type as i32
},
unit: if let Some(unit) = desc.unit() {
Expand All @@ -71,7 +72,7 @@ where

let mut labels = vec![];
desc.labels().encode(&mut labels);
metric.encode(labels, &mut family.metrics);
EncodeMetric::encode(metric.as_ref(), labels, &mut family.metrics);

metric_set.metric_families.push(family);
}
Expand Down Expand Up @@ -118,11 +119,6 @@ impl EncodeMetric for Box<dyn EncodeMetric> {
}
}

/// Trait combining [`EncodeMetric`] and [`Send`].
pub trait SendEncodeMetric: EncodeMetric + Send {}

impl<T: EncodeMetric + Send> SendEncodeMetric for T {}

/// Trait to implement its label encoding in the OpenMetrics protobuf format.
pub trait EncodeLabels {
/// Encode the given instance into Labels in the OpenMetrics protobuf
Expand Down
22 changes: 3 additions & 19 deletions src/encoding/text.rs
Expand Up @@ -40,10 +40,9 @@ use std::ops::Deref;

/// Encode the metrics registered with the provided [`Registry`] into the
/// provided [`Write`]r using the OpenMetrics text format.
pub fn encode<W, M>(writer: &mut W, registry: &Registry<M>) -> Result<(), std::io::Error>
pub fn encode<W>(writer: &mut W, registry: &Registry) -> Result<(), std::io::Error>
where
W: Write,
M: EncodeMetric,
{
for (desc, metric) in registry.iter() {
writer.write_all(b"# HELP ")?;
Expand All @@ -63,7 +62,7 @@ where
unit.encode(writer)?;
}
writer.write_all(b" ")?;
metric.metric_type().encode(writer)?;
EncodeMetric::metric_type(metric.as_ref()).encode(writer)?;
writer.write_all(b"\n")?;

if let Some(unit) = desc.unit() {
Expand All @@ -84,7 +83,7 @@ where
labels: None,
};

metric.encode(encoder)?;
EncodeMetric::encode(metric.as_ref(), encoder)?;
}

writer.write_all(b"# EOF\n")?;
Expand Down Expand Up @@ -402,21 +401,6 @@ impl EncodeMetric for Box<dyn EncodeMetric> {
}
}

/// Trait combining [`EncodeMetric`], [`Send`] and [`Sync`].
pub trait SendSyncEncodeMetric: EncodeMetric + Send + Sync {}

impl<T: EncodeMetric + Send + Sync> SendSyncEncodeMetric for T {}

impl EncodeMetric for Box<dyn SendSyncEncodeMetric> {
fn encode(&self, encoder: Encoder) -> Result<(), std::io::Error> {
self.deref().encode(encoder)
}

fn metric_type(&self) -> MetricType {
self.deref().metric_type()
}
}

/////////////////////////////////////////////////////////////////////////////////
// Counter

Expand Down
6 changes: 3 additions & 3 deletions src/lib.rs
Expand Up @@ -30,15 +30,15 @@
//! //
//! // You could as well use `(String, String)` to represent a label set,
//! // instead of the custom type below.
//! #[derive(Clone, Hash, PartialEq, Eq, Encode)]
//! #[derive(Clone, Debug, Hash, PartialEq, Eq, Encode)]
//! struct Labels {
//! // Use your own enum types to represent label values.
//! method: Method,
//! // Or just a plain string.
//! path: String,
//! };
//!
//! #[derive(Clone, Hash, PartialEq, Eq, Encode)]
//! #[derive(Clone, Debug, Hash, PartialEq, Eq, Encode)]
//! enum Method {
//! GET,
//! PUT,
Expand All @@ -54,7 +54,7 @@
//! "http_requests",
//! // And the metric help text.
//! "Number of HTTP requests received",
//! Box::new(http_requests.clone()),
//! http_requests.clone(),
//! );
//!
//! // Somewhere in your business logic record a single HTTP GET request.
Expand Down
13 changes: 10 additions & 3 deletions src/metrics/family.rs
Expand Up @@ -65,12 +65,12 @@ use std::sync::Arc;
/// # use std::io::Write;
/// #
/// # let mut registry = Registry::default();
/// #[derive(Clone, Hash, PartialEq, Eq, Encode)]
/// #[derive(Clone, Debug, Hash, PartialEq, Eq, Encode)]
/// struct Labels {
/// method: Method,
/// };
///
/// #[derive(Clone, Hash, PartialEq, Eq, Encode)]
/// #[derive(Clone, Debug, Hash, PartialEq, Eq, Encode)]
/// enum Method {
/// GET,
/// PUT,
Expand All @@ -97,7 +97,6 @@ use std::sync::Arc;
/// # assert_eq!(expected, String::from_utf8(buffer).unwrap());
/// ```
// TODO: Consider exposing hash algorithm.
#[derive(Debug)]
pub struct Family<S, M, C = fn() -> M> {
metrics: Arc<RwLock<HashMap<S, M>>>,
/// Function that when called constructs a new metric.
Expand All @@ -111,6 +110,14 @@ pub struct Family<S, M, C = fn() -> M> {
constructor: C,
}

impl<S: std::fmt::Debug, M: std::fmt::Debug, C> std::fmt::Debug for Family<S, M, C> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Family")
.field("metrics", &self.metrics)
.finish()
}
}

/// A constructor for creating new metrics in a [`Family`] when calling
/// [`Family::get_or_create`]. Such constructor is provided via
/// [`Family::new_with_constructor`].
Expand Down