From 10fc3736c483f2521d8b512b31de39fe7d958eae Mon Sep 17 00:00:00 2001 From: kilpatty Date: Tue, 27 Oct 2020 14:53:57 -0500 Subject: [PATCH 1/5] metrics-exporter-prometheus: split off tokio and hyper functionality to another (default) feature --- metrics-exporter-prometheus/Cargo.toml | 14 +++++++++---- metrics-exporter-prometheus/src/lib.rs | 29 ++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/metrics-exporter-prometheus/Cargo.toml b/metrics-exporter-prometheus/Cargo.toml index 74f25a8..f1717c1 100644 --- a/metrics-exporter-prometheus/Cargo.toml +++ b/metrics-exporter-prometheus/Cargo.toml @@ -15,15 +15,21 @@ readme = "README.md" categories = ["development-tools::debugging"] keywords = ["metrics", "telemetry", "prometheus"] +[features] +default = ["tokio-exporter"] +tokio-exporter = ["hyper", "tokio"] + [dependencies] -metrics = { version = "0.13.0-alpha.1", path = "../metrics" } -metrics-util = { version = "0.4.0-alpha.1", path = "../metrics-util"} +metrics = { version = "0.13.0-alpha.1", path="../metrics" } +metrics-util = { version = "0.4.0-alpha.1", path="../metrics-util" } hdrhistogram = "7.1" -hyper = { version = "0.13", default-features = false, features = ["tcp"] } -tokio = { version = "0.2", features = ["rt-core", "tcp", "time", "macros"] } parking_lot = "0.11" thiserror = "1.0" +# Optional +hyper = { version = "0.13", default-features = false, features = ["tcp"], optional = true } +tokio = { version = "0.2", features = ["rt-core", "tcp", "time", "macros"], optional = true } + [dev-dependencies] quanta = "0.6" tracing = "0.1" diff --git a/metrics-exporter-prometheus/src/lib.rs b/metrics-exporter-prometheus/src/lib.rs index b374d54..ea4723b 100644 --- a/metrics-exporter-prometheus/src/lib.rs +++ b/metrics-exporter-prometheus/src/lib.rs @@ -2,6 +2,7 @@ #![deny(missing_docs)] use std::future::Future; +#[cfg(feature = "tokio-exporter")] use hyper::{ service::{make_service_fn, service_fn}, {Body, Error as HyperError, Response, Server}, @@ -15,9 +16,11 @@ use std::io; use std::iter::FromIterator; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::sync::Arc; +#[cfg(feature = "tokio-exporter")] use std::thread; use std::{collections::HashMap, time::SystemTime}; use thiserror::Error as ThisError; +#[cfg(feature = "tokio-exporter")] use tokio::{pin, runtime, select}; type PrometheusRegistry = Registry; @@ -31,6 +34,7 @@ pub enum Error { Io(#[from] io::Error), /// Binding/listening to the given address did not succeed. + #[cfg(feature = "tokio-exporter")] #[error("failed to bind to given listen address: {0}")] Hyper(#[from] HyperError), @@ -330,6 +334,11 @@ pub struct PrometheusRecorder { } impl PrometheusRecorder { + /// Renders the Prometheus metrics in string format. + pub fn render(&self) -> String { + self.inner.render() + } + fn add_description_if_missing(&self, key: &Key, description: Option<&'static str>) { if let Some(description) = description { let mut descriptions = self.inner.descriptions.write(); @@ -414,6 +423,7 @@ impl PrometheusBuilder { /// /// An error will be returned if there's an issue with creating the HTTP server or with /// installing the recorder as the global recorder. + #[cfg(feature = "tokio-exporter")] pub fn install(self) -> Result<(), Error> { let (recorder, exporter) = self.build()?; metrics::set_boxed_recorder(Box::new(recorder))?; @@ -439,12 +449,31 @@ impl PrometheusBuilder { Ok(()) } + /// Builds the recorder and returns it. + /// This function is only enabled when default features are not set. + #[cfg(not(feature = "tokio-exporter"))] + pub fn build(self) -> Result { + let inner = Arc::new(Inner { + registry: Registry::new(), + distributions: RwLock::new(HashMap::new()), + quantiles: self.quantiles.clone(), + buckets: self.buckets.clone(), + buckets_by_name: self.buckets_by_name, + descriptions: RwLock::new(HashMap::new()), + }); + + let recorder = PrometheusRecorder { inner }; + + Ok(recorder) + } + /// Builds the recorder and exporter and returns them both. /// /// In most cases, users should prefer to use [`PrometheusBuilder::install`] to create and /// install the recorder and exporter automatically for them. If a caller is combining /// recorders, or needs to schedule the exporter to run in a particular way, this method /// provides the flexibility to do so. + #[cfg(feature = "tokio-exporter")] pub fn build( self, ) -> Result< From 1b852b32a4c124459d3d2e95c3119c6bcb34e79c Mon Sep 17 00:00:00 2001 From: kilpatty Date: Thu, 29 Oct 2020 16:18:13 -0500 Subject: [PATCH 2/5] metrics-exporter-prometheus: switch methods to gain access to the inner data of the recorder (using a type alias) --- metrics-exporter-prometheus/Cargo.toml | 4 ++-- metrics-exporter-prometheus/src/lib.rs | 14 ++++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/metrics-exporter-prometheus/Cargo.toml b/metrics-exporter-prometheus/Cargo.toml index f1717c1..a18079c 100644 --- a/metrics-exporter-prometheus/Cargo.toml +++ b/metrics-exporter-prometheus/Cargo.toml @@ -20,8 +20,8 @@ default = ["tokio-exporter"] tokio-exporter = ["hyper", "tokio"] [dependencies] -metrics = { version = "0.13.0-alpha.1", path="../metrics" } -metrics-util = { version = "0.4.0-alpha.1", path="../metrics-util" } +metrics = { version = "0.13.0-alpha.1", path = "../metrics" } +metrics-util = { version = "0.4.0-alpha.1", path = "../metrics-util" } hdrhistogram = "7.1" parking_lot = "0.11" thiserror = "1.0" diff --git a/metrics-exporter-prometheus/src/lib.rs b/metrics-exporter-prometheus/src/lib.rs index ea4723b..ffeeda7 100644 --- a/metrics-exporter-prometheus/src/lib.rs +++ b/metrics-exporter-prometheus/src/lib.rs @@ -26,6 +26,9 @@ use tokio::{pin, runtime, select}; type PrometheusRegistry = Registry; type HdrHistogram = hdrhistogram::Histogram; +/// A type wrapper around the Inner struct of the Prometheus recorder. +pub type PrometheusHandle = Arc; + /// Errors that could occur while installing a Prometheus recorder/exporter. #[derive(ThisError, Debug)] pub enum Error { @@ -65,7 +68,8 @@ struct Snapshot { pub distributions: HashMap, Distribution>>, } -struct Inner { +/// Inner contains all of the data stored by the Prometheus Recorder. +pub struct Inner { registry: PrometheusRegistry, distributions: RwLock, Distribution>>>, quantiles: Vec, @@ -75,6 +79,7 @@ struct Inner { } impl Inner { + /// Returns a reference to the [`PrometheusRegistry`] this struct uses. pub fn registry(&self) -> &PrometheusRegistry { &self.registry } @@ -165,6 +170,7 @@ impl Inner { } } + /// Returns the metrics in Prometheus accepted String format. pub fn render(&self) -> String { let mut sorted_overrides = self .buckets_by_name @@ -334,9 +340,9 @@ pub struct PrometheusRecorder { } impl PrometheusRecorder { - /// Renders the Prometheus metrics in string format. - pub fn render(&self) -> String { - self.inner.render() + ///Returns a [`PrometheusHandle`] from the inner struct of this recorder. + pub fn handle(&self) -> PrometheusHandle { + self.inner.clone() } fn add_description_if_missing(&self, key: &Key, description: Option<&'static str>) { From e2ba57bfa63a08ec07a8c94f6fa2d994604a64e9 Mon Sep 17 00:00:00 2001 From: kilpatty Date: Fri, 30 Oct 2020 08:49:48 -0500 Subject: [PATCH 3/5] metrics-exporter-prometheus: move PrometheusHandle to struct. Eliminate now useless pub function doc comments --- metrics-exporter-prometheus/src/lib.rs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/metrics-exporter-prometheus/src/lib.rs b/metrics-exporter-prometheus/src/lib.rs index ffeeda7..22811bc 100644 --- a/metrics-exporter-prometheus/src/lib.rs +++ b/metrics-exporter-prometheus/src/lib.rs @@ -26,9 +26,6 @@ use tokio::{pin, runtime, select}; type PrometheusRegistry = Registry; type HdrHistogram = hdrhistogram::Histogram; -/// A type wrapper around the Inner struct of the Prometheus recorder. -pub type PrometheusHandle = Arc; - /// Errors that could occur while installing a Prometheus recorder/exporter. #[derive(ThisError, Debug)] pub enum Error { @@ -68,8 +65,7 @@ struct Snapshot { pub distributions: HashMap, Distribution>>, } -/// Inner contains all of the data stored by the Prometheus Recorder. -pub struct Inner { +struct Inner { registry: PrometheusRegistry, distributions: RwLock, Distribution>>>, quantiles: Vec, @@ -79,7 +75,6 @@ pub struct Inner { } impl Inner { - /// Returns a reference to the [`PrometheusRegistry`] this struct uses. pub fn registry(&self) -> &PrometheusRegistry { &self.registry } @@ -170,7 +165,6 @@ impl Inner { } } - /// Returns the metrics in Prometheus accepted String format. pub fn render(&self) -> String { let mut sorted_overrides = self .buckets_by_name @@ -342,7 +336,9 @@ pub struct PrometheusRecorder { impl PrometheusRecorder { ///Returns a [`PrometheusHandle`] from the inner struct of this recorder. pub fn handle(&self) -> PrometheusHandle { - self.inner.clone() + PrometheusHandle { + inner: self.inner.clone(), + } } fn add_description_if_missing(&self, key: &Key, description: Option<&'static str>) { @@ -355,6 +351,18 @@ impl PrometheusRecorder { } } +/// A wrapper around the Inner struct of the Prometheus recorder. +pub struct PrometheusHandle { + inner: Arc, +} + +impl PrometheusHandle { + /// Returns the metrics in Prometheus accepted String format. + pub fn render(&self) -> String { + self.inner.render() + } +} + /// Builder for creating and installing a Prometheus recorder/exporter. pub struct PrometheusBuilder { listen_address: SocketAddr, From 6e61eb493b0551fdef3222d6ec81b7518d864039 Mon Sep 17 00:00:00 2001 From: Sean Kilgarriff Date: Mon, 2 Nov 2020 07:17:47 -0600 Subject: [PATCH 4/5] Update metrics-exporter-prometheus/src/lib.rs Co-authored-by: Toby Lawrence --- metrics-exporter-prometheus/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metrics-exporter-prometheus/src/lib.rs b/metrics-exporter-prometheus/src/lib.rs index 22811bc..18d0243 100644 --- a/metrics-exporter-prometheus/src/lib.rs +++ b/metrics-exporter-prometheus/src/lib.rs @@ -439,7 +439,7 @@ impl PrometheusBuilder { /// installing the recorder as the global recorder. #[cfg(feature = "tokio-exporter")] pub fn install(self) -> Result<(), Error> { - let (recorder, exporter) = self.build()?; + let (recorder, exporter) = self.build_with_exporter()?; metrics::set_boxed_recorder(Box::new(recorder))?; let mut runtime = runtime::Builder::new() From 274ca273c47136653749db354f4afa4647d8c6d7 Mon Sep 17 00:00:00 2001 From: kilpatty Date: Mon, 2 Nov 2020 07:20:55 -0600 Subject: [PATCH 5/5] metrics-exporter-prometheus: drop feature gate on build, rename other build to build_with_exporter, and fix doc comments --- metrics-exporter-prometheus/src/lib.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/metrics-exporter-prometheus/src/lib.rs b/metrics-exporter-prometheus/src/lib.rs index 18d0243..51cc77c 100644 --- a/metrics-exporter-prometheus/src/lib.rs +++ b/metrics-exporter-prometheus/src/lib.rs @@ -334,7 +334,7 @@ pub struct PrometheusRecorder { } impl PrometheusRecorder { - ///Returns a [`PrometheusHandle`] from the inner struct of this recorder. + /// Gets a [`PrometheusHandle`] to this recorder. pub fn handle(&self) -> PrometheusHandle { PrometheusHandle { inner: self.inner.clone(), @@ -351,7 +351,9 @@ impl PrometheusRecorder { } } -/// A wrapper around the Inner struct of the Prometheus recorder. +/// Handle to [`PrometheusRecorder`]. +/// +/// Useful for exposing a scrape endpoint on an existing HTTP/HTTPS server. pub struct PrometheusHandle { inner: Arc, } @@ -465,7 +467,6 @@ impl PrometheusBuilder { /// Builds the recorder and returns it. /// This function is only enabled when default features are not set. - #[cfg(not(feature = "tokio-exporter"))] pub fn build(self) -> Result { let inner = Arc::new(Inner { registry: Registry::new(), @@ -488,7 +489,7 @@ impl PrometheusBuilder { /// recorders, or needs to schedule the exporter to run in a particular way, this method /// provides the flexibility to do so. #[cfg(feature = "tokio-exporter")] - pub fn build( + pub fn build_with_exporter( self, ) -> Result< (