prometheus_push 0.4.1

Crate to extend prometheus crates with pushgateway support
# Prometheus Push

`prometheus_push` works as an extension to prometheus crates like [prometheus](https://crates.io/crates/prometheus) to be able to push non-blocking (default)
or blocking to your Prometheus pushgateway and with a less dependent setup of `reqwest` (no `openssl` for example) or with an implementation of your
own http client.

By default you have to implement the `Push` trait to use it with your choice of http client or you can use the `with_reqwest` feature.
This feature already implements `Push` in a `PushClient` that leverages `reqwest` under the hood. Reqwest is setup 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 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 or you use the already implemented feature
`prometheus_crate` that leverages the [prometheus](https://crates.io/crates/prometheus) crate
or `prometheus_client_crate` that uses the [prometheus-client](https://crates.io/crates/prometheus-client) crate.

## Example with features `with_reqwest` and `prometheus_crate`

```rust
use prometheus::labels;
use prometheus_push::prometheus_crate::PrometheusMetricsPusher;
use reqwest::Client;
use url::Url;

let push_gateway: Url = "<address to your instance>";
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?;
```

## 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](https://github.com/maoertel/prometheus-push/blob/7fe1946dd143f4870beb80e642b0acb7854a3cb8/src/with_reqwest.rs)).
Basically it is as simple as that.

```rust
use prometheus_push::non_blocking::Push;

pub struct YourPushClient;

#[async_trait::async_trait]
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`.

```rust
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 enabled
- `non_blocking`: this ennables the async functionality
- `blocking`: on top of the default feature you get the same functionality in a blocking fashion
- `with_reqwest`: this feature enables the `non_blocking` feature as well as `reqwest` in minimal configuration and enables the alredy implemented `PushClient`
- `with_reqwest_blocking`: like `with_reqwest` but including `blocking` instead of `non_blocking`
- `prometheus_crate`: enables the functionality of the [prometheus]https://crates.io/crates/prometheus crate
- `prometheus_client_crate`: enables the functionality of the [prometheus-client]https://crates.io/crates/prometheus-client crate

Please be aware that features `with_request` & `with_reqwest_blocking` and `prometheus_crate` & `prometheus_client_crate` are mutually exclusive each.

## Integration in your `Cargo.toml`

Let's say you wanna use it with `reqwest` in an async fashion with the `prometheus` crate, you have to add the following to your `Cargo.toml`:

```toml
[dependencies]
prometheus_push = { version = "<version>", default-features = false, features = ["with_reqwest", "prometheus_crate"] }
```

## License

[MIT](./LICENSE-MIT)