Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: koushiro-contrib/client_rust
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: prometheus/client_rust
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Able to merge. These branches can be automatically merged.
Loading
98 changes: 98 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -4,6 +4,104 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.24.0] - unreleased

### Added

- `EncodeLabelSet` is now implemented for tuples `(A: EncodeLabelSet, B: EncodeLabelSet)`.
See [PR 257].

- `Family::get_or_create_owned` can access a metric in a labeled family. This
method avoids the risk of runtime deadlocks at the expense of creating an
owned type. See [PR 244].

[PR 244]: https://github.com/prometheus/client_rust/pull/244
[PR 257]: https://github.com/prometheus/client_rust/pull/257

### Changed

- `EncodeLabelSet::encode()` now accepts a mutable reference to its encoder parameter.

## [0.23.1]

### Changed

- `Histogram::new` now accepts an `IntoIterator` argument, rather than an `Iterator`.
See [PR 243].

[PR 243]: https://github.com/prometheus/client_rust/pull/243

## [0.23.0]

### Changed

- `ConstCounter::new` now requires specifying the type of literal arguments, like this: `ConstCounter::new(42u64);`.
See [PR 173].

- Update `prost` dependencies to `v0.12`.
See [PR 198].

- Implement `Atomic<u64>` for `AtomicU64` for gauges.
See [PR 226].

- Implement `EnableLabelValue` for `bool`.
See [PR 237]

[PR 173]: https://github.com/prometheus/client_rust/pull/173
[PR 198]: https://github.com/prometheus/client_rust/pull/198
[PR 226]: https://github.com/prometheus/client_rust/pull/226
[PR 237]: https://github.com/prometheus/client_rust/pull/237

### Added

- Support `i32`/`f32` for `Gauge` and `u32`/`f32` for `Counter`/`CounterWithExemplar`.
See [PR 173] and [PR 216].

- Supoort `Arc<String>` for `EncodeLabelValue`.
See [PR 217].

- Add `histogram::exponential_buckets_range`.
See [PR 233].

- Added `get` method to `Family`.
See [PR 234].

[PR 173]: https://github.com/prometheus/client_rust/pull/173
[PR 216]: https://github.com/prometheus/client_rust/pull/216
[PR 217]: https://github.com/prometheus/client_rust/pull/217
[PR 233]: https://github.com/prometheus/client_rust/pull/233
[PR 234]: https://github.com/prometheus/client_rust/pull/234

### Fixed

- Don't prepend `,` when encoding empty family label set.
See [PR 175].

[PR 175]: https://github.com/prometheus/client_rust/pull/175

## [0.22.3]

### Added

- Added `encode_registry` and `encode_eof` functions to `text` module.
See [PR 205].

[PR 205]: https://github.com/prometheus/client_rust/pull/205

- Support all platforms with 32 bit atomics lacking 64 bit atomics.
See [PR 203].

[PR 203]: https://github.com/prometheus/client_rust/pull/203

## [0.22.2]

### Added

- Added `Gauge<u32, AtomicU32>` implementation.
See [PR 191].

[PR 191]: https://github.com/prometheus/client_rust/pull/191

## [0.22.1]

### Added
26 changes: 26 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Contributing

## Protocol Buffers

The `build.rs` script in this library depends upon the
[Protocol Buffers compiler][protoc]. Be sure that `protoc` is installed and
available within your `PATH`.

[protoc]: https://docs.rs/prost-build/latest/prost_build/#sourcing-protoc

## Python Dependencies

This repository uses the [`prometheus-client`][client-python] Python client
library in its test suite.

You may create and activate a virtual environment with this dependency
installed by running the following shell commands from the root of this
repository:

```shell
python -m venv ./venv
source venv/bin/activate
pip install prometheus-client
```

[client-python]: https://github.com/prometheus/client_python
23 changes: 16 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "prometheus-client"
version = "0.22.1"
version = "0.24.0"
authors = ["Max Inden <mail@max-inden.de>"]
edition = "2021"
description = "Open Metrics client library allowing users to natively instrument applications."
@@ -21,24 +21,28 @@ members = ["derive-encode"]
dtoa = "1.0"
itoa = "1.0"
parking_lot = "0.12"
prometheus-client-derive-encode = { version = "0.4.1", path = "derive-encode" }
prost = { version = "0.11.0", optional = true }
prost-types = { version = "0.11.0", optional = true }
prometheus-client-derive-encode = { version = "0.5.0", path = "derive-encode" }
prost = { version = "0.12.0", optional = true }
prost-types = { version = "0.12.0", optional = true }

[dev-dependencies]
async-std = { version = "1", features = ["attributes"] }
axum = "0.7"
criterion = "0.5"
futures = "0.3"
http-types = "2"
pyo3 = "0.20"
pyo3 = "0.22"
quickcheck = "1"
rand = "0.8.4"
tide = "0.16"
actix-web = "4"
tokio = { version = "1", features = ["rt-multi-thread", "net", "macros", "signal"] }
hyper = { version = "0.14.16", features = ["server", "http1", "tcp"] }
hyper = { version = "1.3.1", features = ["server", "http1"] }
hyper-util = { version = "0.1.3", features = ["tokio"] }
http-body-util = "0.1.1"

[build-dependencies]
prost-build = { version = "0.11.0", optional = true }
prost-build = { version = "0.12.0", optional = true }

[[bench]]
name = "baseline"
@@ -59,3 +63,8 @@ name = "proto"
path = "benches/encoding/proto.rs"
harness = false
required-features = ["protobuf"]

# Passing arguments to the docsrs builder in order to properly document cfg's.
# More information: https://docs.rs/about/builds#cross-compiling
[package.metadata.docs.rs]
all-features = true
2 changes: 1 addition & 1 deletion derive-encode/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "prometheus-client-derive-encode"
version = "0.4.2"
version = "0.5.0"
authors = ["Max Inden <mail@max-inden.de>"]
edition = "2021"
description = "Auxiliary crate to derive Encode trait from prometheus-client."
2 changes: 1 addition & 1 deletion derive-encode/src/lib.rs
Original file line number Diff line number Diff line change
@@ -72,7 +72,7 @@ pub fn derive_encode_label_set(input: TokenStream) -> TokenStream {

let gen = quote! {
impl prometheus_client::encoding::EncodeLabelSet for #name {
fn encode(&self, mut encoder: prometheus_client::encoding::LabelSetEncoder) -> std::result::Result<(), std::fmt::Error> {
fn encode(&self, encoder: &mut prometheus_client::encoding::LabelSetEncoder) -> std::result::Result<(), std::fmt::Error> {
use prometheus_client::encoding::EncodeLabel;
use prometheus_client::encoding::EncodeLabelKey;
use prometheus_client::encoding::EncodeLabelValue;
32 changes: 32 additions & 0 deletions derive-encode/tests/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::sync::Arc;

use prometheus_client::encoding::text::encode;
use prometheus_client::encoding::{EncodeLabelSet, EncodeLabelValue};
use prometheus_client::metrics::counter::Counter;
@@ -137,6 +139,36 @@ fn remap_keyword_identifiers() {
assert_eq!(expected, buffer);
}

#[test]
fn arc_string() {
#[derive(EncodeLabelSet, Hash, Clone, Eq, PartialEq, Debug)]
struct Labels {
client_id: Arc<String>,
}

let mut registry = Registry::default();
let family = Family::<Labels, Counter>::default();
registry.register("my_counter", "This is my counter", family.clone());

// Record a single HTTP GET request.
let client_id = Arc::new("client_id".to_string());
family
.get_or_create(&Labels {
client_id: client_id.clone(),
})
.inc();

// Encode all metrics in the registry in the text format.
let mut buffer = String::new();
encode(&mut buffer, &registry).unwrap();

let expected = "# HELP my_counter This is my counter.\n".to_owned()
+ "# TYPE my_counter counter\n"
+ "my_counter_total{client_id=\"client_id\"} 1\n"
+ "# EOF\n";
assert_eq!(expected, buffer);
}

#[test]
fn flatten() {
#[derive(EncodeLabelSet, Hash, Clone, Eq, PartialEq, Debug)]
2 changes: 2 additions & 0 deletions examples/actix-web.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::sync::Mutex;

use actix_web::middleware::Compress;
use actix_web::{web, App, HttpResponse, HttpServer, Responder, Result};
use prometheus_client::encoding::text::encode;
use prometheus_client::encoding::{EncodeLabelSet, EncodeLabelValue};
@@ -61,6 +62,7 @@ async fn main() -> std::io::Result<()> {

HttpServer::new(move || {
App::new()
.wrap(Compress::default())
.app_data(metrics.clone())
.app_data(state.clone())
.service(web::resource("/metrics").route(web::get().to(metrics_handler)))
88 changes: 88 additions & 0 deletions examples/axum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use axum::body::Body;
use axum::extract::State;
use axum::http::header::CONTENT_TYPE;
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use axum::routing::get;
use axum::Router;
use prometheus_client::encoding::text::encode;
use prometheus_client::metrics::counter::Counter;
use prometheus_client::metrics::family::Family;
use prometheus_client::registry::Registry;
use prometheus_client_derive_encode::{EncodeLabelSet, EncodeLabelValue};
use std::sync::Arc;
use tokio::sync::Mutex;

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

#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)]
pub struct MethodLabels {
pub method: Method,
}

#[derive(Debug)]
pub struct Metrics {
requests: Family<MethodLabels, Counter>,
}

impl Metrics {
pub fn inc_requests(&self, method: Method) {
self.requests.get_or_create(&MethodLabels { method }).inc();
}
}

#[derive(Debug)]
pub struct AppState {
pub registry: Registry,
}

pub async fn metrics_handler(State(state): State<Arc<Mutex<AppState>>>) -> impl IntoResponse {
let state = state.lock().await;
let mut buffer = String::new();
encode(&mut buffer, &state.registry).unwrap();

Response::builder()
.status(StatusCode::OK)
.header(
CONTENT_TYPE,
"application/openmetrics-text; version=1.0.0; charset=utf-8",
)
.body(Body::from(buffer))
.unwrap()
}

pub async fn some_handler(State(metrics): State<Arc<Mutex<Metrics>>>) -> impl IntoResponse {
metrics.lock().await.inc_requests(Method::Get);
"okay".to_string()
}

#[tokio::main]
async fn main() {
let metrics = Metrics {
requests: Family::default(),
};
let mut state = AppState {
registry: Registry::default(),
};
state
.registry
.register("requests", "Count of requests", metrics.requests.clone());
let metrics = Arc::new(Mutex::new(metrics));
let state = Arc::new(Mutex::new(state));

let router = Router::new()
.route("/metrics", get(metrics_handler))
.with_state(state)
.route("/handler", get(some_handler))
.with_state(metrics);
let port = 8080;
let listener = tokio::net::TcpListener::bind(format!("0.0.0.0:{}", port))
.await
.unwrap();

axum::serve(listener, router).await.unwrap();
}
4 changes: 2 additions & 2 deletions examples/custom-metric.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use prometheus_client::encoding::{text::encode, EncodeMetric, MetricEncoder};
use prometheus_client::encoding::{text::encode, EncodeMetric, MetricEncoder, NoLabelSet};
use prometheus_client::metrics::MetricType;
use prometheus_client::registry::Registry;

@@ -20,7 +20,7 @@ impl EncodeMetric for MyCustomMetric {
// E.g. every CPU cycle spend in this method delays the response send to
// the Prometheus server.

encoder.encode_counter::<(), _, u64>(&rand::random::<u64>(), None)
encoder.encode_counter::<NoLabelSet, _, u64>(&rand::random::<u64>(), None)
}

fn metric_type(&self) -> prometheus_client::metrics::MetricType {
Loading