8 releases
0.4.5 | Jun 23, 2024 |
---|---|
0.4.4 | Apr 20, 2024 |
0.4.3 | Nov 24, 2023 |
0.3.0 | Nov 18, 2023 |
0.2.1 | Nov 16, 2023 |
#72 in HTTP client
468 downloads per month
55KB
846 lines
Prometheus Push ⏫
prometheus_push
works as an extension to prometheus crates like prometheus or
prometheus-client to be able to push non-blocking (default) or blocking to your Prometheus
pushgateway with a less dependent setup of reqwest
(no openssl
for example) or with an implementation of your own http client or even
another prometheus
crate – this whole crate is completely generic so you are free to do whatever you want.
If you wanna use it with reqwest
, prometheus
or prometheus-client
crates you literally do not have to implement anything (see
scenarios below), as those common usages are already implemented as features within this crate.
In this crates stripped version you have to implement the Push
trait (see here) to use it with your choice of
http client or –as said– you can use the with_reqwest
or with_reqwest_blocking
features. These features already implement Push
in a
PushClient
that leverages reqwest
under the hood. Reqwest is set up without default features (minimal set) in this case so it should
not interfere with your own applications reqwest setup (e.g. rust-tls
).
Async functionality (feature non_blocking
) is considered the standard in this crate but you can enable the blocking
feature to get the
implementation without async. You can enable the corresponding blocking reqwest
implementation with the with_reqwest_blocking
feature in
which case you enable the blocking
feature of the reqwest
crate.
In terms of the underlying prometheus functionality you have to implement the ConvertMetrics
trait yourself (see here)
or you use the already implemented feature prometheus_crate
that leverages the prometheus crate or
prometheus_client_crate
that uses the prometheus-client crate.
Scenarios
1. I use reqwest
and prometheus
crates in a non-blocking fashion
In your Cargo.toml
:
[dependencies]
prometheus_push = { version = "<version>", default-features = false, features = ["with_reqwest", "prometheus_crate"] }
use prometheus::labels;
use prometheus_push::prometheus_crate::PrometheusMetricsPusher;
use reqwest::Client;
use url::Url;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let push_gateway: Url = Url::parse("<address to pushgateway>")?;
let client = Client::new();
let metrics_pusher = PrometheusMetricsPusher::from(client, &push_gateway)?;
metrics_pusher
.push_all(
"<your push jobs name>",
&labels! { "<label_name>" => "<label_value>" },
prometheus::gather(),
)
.await?;
Ok(())
}
2. I use reqwest
and prometheus
crates in a blocking fashion
In your Cargo.toml
:
[dependencies]
prometheus_push = { version = "<version>", default-features = false, features = ["with_reqwest_blocking", "prometheus_crate"] }
use prometheus::labels;
use prometheus_push::prometheus_crate::PrometheusMetricsPusherBlocking;
use reqwest::blocking::Client;
use url::Url;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let push_gateway: Url = Url::parse("<address to pushgateway>")?;
let client = Client::new();
let metrics_pusher = PrometheusMetricsPusherBlocking::from(client, &push_gateway)?;
metrics_pusher
.push_all(
"<your push jobs name>",
&labels! { "<label_name>" => "<label_value>" },
prometheus::gather(),
)?;
Ok(())
}
3. I use reqwest
and prometheus-client
crates in a non-blocking fashion
In your Cargo.toml
:
[dependencies]
prometheus_push = { version = "<version>", default-features = false, features = ["with_reqwest", "prometheus_client_crate"] }
use prometheus_client::encoding::text::encode;
use prometheus_push::prometheus_client_crate::PrometheusClientMetricsPusher;
use reqwest::Client;
use url::Url;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let push_gateway: Url = Url::parse("<address to pushgateway>")?;
let client = Client::new();
let metrics_pusher = PrometheusClientMetricsPusher::create(client, &push_gateway)?;
let grouping: HashMap<&str, &str> = HashMap::from([("<label_name>", "<label_value>")]);
let mut metrics = String::new();
encode(&mut metrics, ®istry)?;
metrics_pusher
.push_all(
"<your push jobs name>",
&grouping,
metrics,
)
.await?;
Ok(())
}
4. I use reqwest
and prometheus-client
crates in a blocking fashion
In your Cargo.toml
:
[dependencies]
prometheus_push = { version = "<version>", default-features = false, features = ["with_reqwest_blocking", "prometheus_client_crate"] }
use prometheus_client::encoding::text::encode;
use prometheus_push::prometheus_client_crate::PrometheusClientMetricsPusherBlocking;
use reqwest::blocking::Client;
use url::Url;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let push_gateway: Url = Url::parse("<address to pushgateway>")?;
let client = Client::new();
let metrics_pusher = PrometheusClientMetricsPusherBlocking::create(client, &push_gateway)?;
let grouping: HashMap<&str, &str> = HashMap::from([("<label_name>", "<label_value>")]);
let mut metrics = String::new();
encode(&mut metrics, ®istry)?;
metrics_pusher
.push_all(
"<your push jobs name>",
&grouping,
metrics,
)?;
Ok(())
}
5. I want to implement everything myself
In case you wanna implement everything yourself you can do so by implementing the Push
trait and the ConvertMetrics
trait.
Implement Push
yourself
If you are not using reqwest as an http client you are free to implement the Push
traits two methods yourself. As a guide you can use the
implementation of the with_reqwest
feature (see here).
Basically it is as simple as that.
use prometheus_push::Push;
pub struct YourPushClient;
impl Push<Vec<u8>> for YourPushClient {
async fn push_all(&self, url: &Url, body: Vec<u8>, content_type: &str) -> Result<()> {
// implement a PUT request with your client with this body and `content_type` in header
}
async fn push_add(&self, url: &Url, body: Vec<u8>, content_type: &str) -> Result<()> {
// implement a POST request with your client with this body and `content_type` in header
}
}
Implement ConvertMetrics
yourself
In case you want to use another prometheus client implementation you can implement your own type that implements
the ConvertMetrics
trait to inject it into your instance of MetricsPusher
.
impl ConvertMetrics<Vec<YourMetricFamily>, Vec<Box<dyn YourCollector>>, Vec<u8>> for YourMetricsConverter {
fn metric_families_from(
&self,
collectors: Vec<Box<dyn YourCollector>>,
) -> Result<Vec<YourMetricFamily>> {
// implement the conversion from your Collectors to your MetricsFamilies, or whatever
// your generic `MF` type stands for
}
fn create_push_details(
&self,
job: &str,
url: &Url,
grouping: &HashMap<&str, &str>,
metric_families: Vec<YourMetricFamily>,
) -> Result<(Url, Vec<u8>, String)> {
// create your push details for the `Push` methods: Url, body and content type
}
}
Features
default
: by default async functionality and no reqwest is enablednon_blocking
: this ennables the async functionalityblocking
: on top of the default feature you get the same functionality in a blocking fashionwith_reqwest
: this feature enables thenon_blocking
feature as well asreqwest
in minimal configuration and enables the alredy implementedPushClient
with_reqwest_blocking
: likewith_reqwest
but includingblocking
instead ofnon_blocking
prometheus_crate
: enables the functionality of the prometheus crateprometheus_client_crate
: enables the functionality of the prometheus-client crate
License
Dependencies
~2–13MB
~161K SLoC