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

Protobuf support #47

Closed
wants to merge 77 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
6aafa61
build(deps): update dtoa requirement from 0.4 to 1.0 (#27)
dependabot[bot] Dec 19, 2021
638d84e
src/metrics/gauge: Implement Gauge::dec and Gauge::dec_by (#30)
mxinden Dec 29, 2021
132b7f4
CHANGELOG: Prepare v0.14.0
mxinden Dec 29, 2021
1ae51af
*: Rename to prometheus-client (#32)
mxinden Jan 16, 2022
4885fbe
*: Prepare v0.15.0
mxinden Jan 16, 2022
f6c4689
*: Update common Prometheus files (#33)
prombot Jan 17, 2022
55f673b
src/lib: Make imports visible in example code (#35)
56quarters Jan 19, 2022
fed1866
.github/workflows: Add cross compilation step (#39)
mxinden Jan 21, 2022
c80672d
src/encoding/text.rs: Expose Encoder methods (#41)
mxinden Feb 2, 2022
ef88152
src/metrics/: Don't use AtomicU64 on unsupported platforms (#42)
chitoku-k Feb 3, 2022
463dce9
CHANGELOG: Prepare v0.15.1 (#44)
mxinden Feb 4, 2022
1c9d81c
Rough implementation to encode Counter
ackintosh Feb 24, 2022
0537cdf
src/encoding/proto: Construct Registry with proto::EncodeMetric
mxinden Feb 28, 2022
3dcbc45
src/encoding/proto: Implement encoding for labels
ackintosh Mar 14, 2022
6fd0693
src/encoding/proto: Implement encoding for CounterWithExemplar
ackintosh Mar 14, 2022
8d89d6e
Move comment
ackintosh Mar 19, 2022
2077ed7
src/encoding/proto: Implement encoding for Gauge
ackintosh Mar 19, 2022
229a4b0
src/encoding/proto: Implement encoding for Histogram
ackintosh Mar 20, 2022
243e98a
src/encoding/proto: Tweak function name according to encoding::text
ackintosh Mar 20, 2022
1ecf2b6
src/encoding/proto: Implement encoding for HistogramWithExemplars
ackintosh Mar 20, 2022
2edf381
src/encoding/proto: Move function for readability
ackintosh Mar 20, 2022
58ef300
src/encoding/proto: Implement encoding for Info
ackintosh Mar 20, 2022
24a56ab
src/encoding/proto: Add tests for Counter
ackintosh Mar 24, 2022
e2a7310
src/encoding/proto: Add assertions for MetricType
ackintosh Mar 24, 2022
46e8e63
src/encoding/proto: DRY-ed tests with `extract_metric_point_value`
ackintosh Mar 24, 2022
0855a0a
src/encoding/proto: Assert name and help
ackintosh Mar 24, 2022
f318b65
src/encoding/proto: Refactor: use associated constants
ackintosh Mar 24, 2022
223b256
src/encoding/proto: Add assertions for counter.exemplar
ackintosh Mar 24, 2022
56da14d
src/encoding/proto: Add assertion for Unit
ackintosh Mar 24, 2022
c92e42a
src/encoding/proto: Refactoring: extract a method `Unit::as_str()`
ackintosh Mar 24, 2022
2d8e80d
src/encoding/proto: Remove superfluous comments
ackintosh Mar 24, 2022
b3dec21
src/encoding/proto: Add tests for Family
ackintosh Mar 24, 2022
d82860d
src/encoding/proto: Remove redundant test
ackintosh Mar 25, 2022
7873e28
src/encoding/proto: Add doc
ackintosh Mar 26, 2022
286e5b4
src/encoding: Remove unnecessary flatten (#50)
mxinden Mar 2, 2022
6354f92
build(deps): update pyo3 requirement from 0.15 to 0.16 (#48)
dependabot[bot] Mar 2, 2022
3dd63fb
examples/tide: Remove unnecessary Mutex (#55)
mxinden Mar 25, 2022
5c5c508
src/registry.rs: Require metrics to be Sync by default (#58)
sd2k Apr 6, 2022
fea4725
CHANGELOG.md: Prepare v0.16.0 (#59)
mxinden May 3, 2022
626e695
*: Update common Prometheus files (#60)
prombot May 8, 2022
aebc4bc
src/metrics/histogram.rs: Document no default buckets (#63)
doehyunbaek May 23, 2022
0f0f70e
*/Cargo.toml: Update to 2021 edition (#65)
doehyunbaek Jun 1, 2022
496c8ab
src/registry.rs: Remove Add trait impls (#69)
erenon Jul 11, 2022
42d1534
src/registry.rs: Add with_prefix to Registry (#70)
Victor-N-Suadicani Jul 14, 2022
20a2b4f
src/*: Add Debug impls and fix clippy warnings (#71)
Victor-N-Suadicani Jul 15, 2022
c048128
CHANGELOG: Preapre v0.17.0 (#72)
mxinden Jul 18, 2022
87143eb
Introduce `protobuf` feature
ackintosh Jul 27, 2022
fa909c2
src/encoding/proto: Refactoring for loop
ackintosh Jul 27, 2022
46309f2
Implement proc macro `EncodeProtobuf`
ackintosh Aug 8, 2022
63a127d
Add impl EncodeGaugeValue for u64
ackintosh Aug 10, 2022
fa07f15
Try Associated Type
ackintosh Jul 31, 2022
977ca7f
Fix life parameter issue
ackintosh Aug 3, 2022
05dab82
Make EncodeLabel::encode return iterator
ackintosh Aug 3, 2022
b3d49ce
src/encoding/proto: Refactor EncodeLabel and EncodeMetric
mxinden Aug 8, 2022
d55296d
Fix assertions because of changes of the order of result
ackintosh Aug 12, 2022
ff7ada0
Remove unnecessary lifetime parameter
ackintosh Aug 12, 2022
42f00e3
Rename EncodeLabel -> EncodeLabels
ackintosh Aug 12, 2022
6d4f6f6
Using `Void` to indicate the impossible case
ackintosh Aug 12, 2022
1c965d4
Changed proc macro accordingly since `encode` returns iterator
ackintosh Aug 12, 2022
9e83678
Rename the proc macro since the name was a bit redundant
ackintosh Aug 12, 2022
cbd97ab
examples/: Add actix-web binary (#76)
oriontvv Aug 1, 2022
de0f38f
.github/workflows/: Add `wasm32` as a cross-compile target (#79)
thomaseizinger Aug 10, 2022
3cff4d6
Add a test for Family (counter and histogram)
ackintosh Aug 13, 2022
3548aa4
Add benchmark code for proto encoding
ackintosh Aug 13, 2022
5af3aff
Add a test for Family, Counter and Histogram
ackintosh Aug 13, 2022
9649407
Remove `Box` to reduce allocation count
ackintosh Aug 15, 2022
680483e
Use std::iter::Once on enums as enum returns single element
ackintosh Aug 15, 2022
15ef4e0
encoding/proto: Pass metric and label vec
mxinden Aug 19, 2022
182d7b0
derive-proto-encode: Update according to the changes in encoding/proto
ackintosh Aug 23, 2022
038fc2a
*: Move to `parking_lot` and thus make `owning_ref` obsolete (#78)
mxinden Aug 16, 2022
c68c4ba
CHANGELOG.md: Prepare v0.18.0 (#80)
mxinden Aug 16, 2022
59624c5
Cargo.toml: Make `void` optional
ackintosh Aug 23, 2022
9c41272
benches: Update according to the changes in encoding/proto
ackintosh Aug 23, 2022
2d28710
encoding/proto: same implementation to slice
ackintosh Aug 23, 2022
250db46
Bump the crate version and add a changelog entry
ackintosh Aug 27, 2022
33c940a
Add --all-features
ackintosh Aug 27, 2022
2d98197
Merge branch 'master' into protobuf-support
ackintosh Aug 27, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
- uses: actions-rs/cargo@v1
with:
command: test
args: --benches
args: --benches --all-features

test:
name: Test Suite
Expand Down Expand Up @@ -73,7 +73,7 @@ jobs:
- uses: actions-rs/cargo@v1
with:
command: test
args: --all
args: --all --all-features

fmt:
name: Rustfmt
Expand Down Expand Up @@ -135,7 +135,7 @@ jobs:
RUSTDOCFLAGS: "--deny broken_intra_doc_links"
with:
command: doc
args: --verbose --workspace --no-deps --document-private-items
args: --verbose --workspace --no-deps --document-private-items --all-features

cross-compile:
name: Cross compile
Expand All @@ -159,4 +159,4 @@ jobs:
with:
use-cross: true
command: build
args: --release --target=${{ matrix.target }}
args: --release --target=${{ matrix.target }} --all-features
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ 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.18.1] - unreleased

### Added
- Added support for the OpenMetrics protobuf format. See [PR 47]

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

## [0.18.0]

### Changed
Expand Down
19 changes: 17 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "prometheus-client"
version = "0.18.0"
version = "0.18.1"
authors = ["Max Inden <mail@max-inden.de>"]
edition = "2021"
description = "Open Metrics client library allowing users to natively instrument applications."
Expand All @@ -10,14 +10,21 @@ repository = "https://github.com/prometheus/client_rust"
homepage = "https://github.com/prometheus/client_rust"
documentation = "https://docs.rs/prometheus-client"

[features]
protobuf = ["dep:prost", "dep:prost-types", "dep:prost-build", "dep:prometheus-client-derive-proto-encode", "dep:void"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think CI is currently not running with --all-features. Can you add it with this pull request to make sure your feature is being tested?

Copy link
Contributor Author

@ackintosh ackintosh Aug 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 33c940a


[workspace]
members = ["derive-text-encode"]
members = ["derive-text-encode", "derive-proto-encode"]

[dependencies]
dtoa = "1.0"
itoa = "1.0"
parking_lot = "0.12"
prometheus-client-derive-proto-encode = { version = "0.1.0", path = "derive-proto-encode", optional = true }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exploring the thought on whether we could use the same derive macro for both text and protobuf. I guess we can not feature flag the generated protobuf code via #[cfg(feature = "protobuf")] as we would not have access to the flag in the downstream user crate?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is cool if we use the same derive macro, I'll do some experiments. 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I investigated but yeah, I couldn't find a way to do that.

prometheus-client-derive-text-encode = { version = "0.3.0", path = "derive-text-encode" }
prost = { version = "0.9.0", optional = true }
prost-types = { version = "0.9.0", optional = true }
void = { version = "1.0", optional = true }

[dev-dependencies]
async-std = { version = "1", features = ["attributes"] }
Expand All @@ -29,6 +36,9 @@ rand = "0.8.4"
tide = "0.16"
actix-web = "4"

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

[[bench]]
name = "family"
harness = false
Expand All @@ -37,3 +47,8 @@ harness = false
name = "text"
path = "benches/encoding/text.rs"
harness = false

[[bench]]
name = "proto"
path = "benches/encoding/proto.rs"
harness = false
85 changes: 85 additions & 0 deletions benches/encoding/proto.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Benchmark inspired by https://github.com/tikv/rust-prometheus/blob/ab1ca7285d3463504381a5025ae1951e020d6796/benches/text_encoder.rs

use criterion::{black_box, criterion_group, criterion_main, Criterion};
use prometheus_client::encoding::proto::{encode, Encode, EncodeMetric};
use prometheus_client::metrics::counter::Counter;
use prometheus_client::metrics::family::Family;
use prometheus_client::metrics::histogram::{exponential_buckets, Histogram};
use prometheus_client::registry::Registry;
use std::fmt::{Display, Formatter};

pub fn proto(c: &mut Criterion) {
c.bench_function("encode", |b| {
#[derive(Clone, Hash, PartialEq, Eq, Encode)]
struct Labels {
path: String,
method: Method,
some_number: u64,
}

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

impl Display for Method {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Method::Get => write!(f, "Get"),
Method::Put => write!(f, "Put"),
}
}
}

#[derive(Clone, Hash, PartialEq, Eq, Encode)]
enum Region {
Africa,
#[allow(dead_code)]
Asia,
}

let mut registry = Registry::<Box<dyn EncodeMetric>>::default();

for i in 0..100 {
let counter_family = Family::<Labels, Counter>::default();
let histogram_family = Family::<Region, Histogram>::new_with_constructor(|| {
Histogram::new(exponential_buckets(1.0, 2.0, 10))
});

registry.register(
format!("my_counter{}", i),
"My counter",
Box::new(counter_family.clone()),
);
registry.register(
format!("my_histogram{}", i),
"My histogram",
Box::new(histogram_family.clone()),
);

for j in 0_u32..100 {
counter_family
.get_or_create(&Labels {
path: format!("/path/{}", i),
method: Method::Get,
some_number: j.into(),
})
.inc();

histogram_family
.get_or_create(&Region::Africa)
.observe(j.into());
}
}

b.iter(|| {
let metric_set = encode(&registry);
black_box(metric_set);
})
});
}

criterion_group!(benches, proto);
criterion_main!(benches);
11 changes: 11 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use std::io::Result;

fn main() -> Result<()> {
#[cfg(feature = "protobuf")]
prost_build::compile_protos(
&["src/encoding/proto/openmetrics_data_model.proto"],
&["src/encoding/proto/"],
)?;

Ok(())
}
23 changes: 23 additions & 0 deletions derive-proto-encode/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[package]
name = "prometheus-client-derive-proto-encode"
version = "0.1.0"
authors = ["Akihito Nakano <sora.akatsuki@gmail.com>"]
edition = "2021"
description = "Auxiliary crate to derive protobuf EncodeLabel trait from prometheus-client."
license = "Apache-2.0 OR MIT"
repository = "https://github.com/prometheus/client_rust"
homepage = "https://github.com/prometheus/client_rust"
documentation = "https://docs.rs/prometheus-client-derive-proto-encode"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
proc-macro2 = "1"
quote = "1"
syn = "1"

[dev-dependencies]
prometheus-client = { path = "../", features = ["protobuf"] }

[lib]
proc-macro = true
127 changes: 127 additions & 0 deletions derive-proto-encode/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use syn::DeriveInput;

#[proc_macro_derive(Encode)]
pub fn derive_encode(input: TokenStream) -> TokenStream {
let ast: DeriveInput = syn::parse(input).unwrap();
let name = &ast.ident;

match ast.data {
syn::Data::Struct(s) => match s.fields {
syn::Fields::Named(syn::FieldsNamed { named, .. }) => {
let push_labels: TokenStream2 = named
.into_iter()
.map(|f| {
let ident = f.ident.unwrap();
let ident_string = KEYWORD_IDENTIFIERS
.iter()
.find(|pair| ident == pair.1)
.map(|pair| pair.0.to_string())
.unwrap_or_else(|| ident.to_string());

quote! {
let mut label = prometheus_client::encoding::proto::Label::default();
label.name = #ident_string.to_string();
label.value = format!("{}", self.#ident);
labels.push(label);
}
})
.collect();

quote! {
impl prometheus_client::encoding::proto::EncodeLabels for #name {
fn encode(&self, labels: &mut Vec<prometheus_client::encoding::proto::Label>) {
#push_labels
}
}
}
}
syn::Fields::Unnamed(_) => {
panic!("Can not derive Encode for struct with unnamed fields.")
}
syn::Fields::Unit => panic!("Can not derive Encode for struct with unit field."),
},
syn::Data::Enum(syn::DataEnum { variants, .. }) => {
let match_arms: TokenStream2 = variants
.into_iter()
.map(|v| {
let ident = v.ident;
quote! {
#name::#ident => {
let mut label = prometheus_client::encoding::proto::Label::default();
label.name = stringify!(#name).to_string();
label.value = stringify!(#ident).to_string();
labels.push(label);
}
}
})
.collect();

quote! {
impl prometheus_client::encoding::proto::EncodeLabels for #name {
fn encode(&self, labels: &mut Vec<prometheus_client::encoding::proto::Label>) {
match self {
#match_arms
};
}
}
}
}
syn::Data::Union(_) => panic!("Can not derive Encode for union."),
}.into()
}

// Copied from https://github.com/djc/askama (MIT and APACHE licensed) and
// modified.
static KEYWORD_IDENTIFIERS: [(&str, &str); 48] = [
("as", "r#as"),
("break", "r#break"),
("const", "r#const"),
("continue", "r#continue"),
("crate", "r#crate"),
("else", "r#else"),
("enum", "r#enum"),
("extern", "r#extern"),
("false", "r#false"),
("fn", "r#fn"),
("for", "r#for"),
("if", "r#if"),
("impl", "r#impl"),
("in", "r#in"),
("let", "r#let"),
("loop", "r#loop"),
("match", "r#match"),
("mod", "r#mod"),
("move", "r#move"),
("mut", "r#mut"),
("pub", "r#pub"),
("ref", "r#ref"),
("return", "r#return"),
("static", "r#static"),
("struct", "r#struct"),
("trait", "r#trait"),
("true", "r#true"),
("type", "r#type"),
("unsafe", "r#unsafe"),
("use", "r#use"),
("where", "r#where"),
("while", "r#while"),
("async", "r#async"),
("await", "r#await"),
("dyn", "r#dyn"),
("abstract", "r#abstract"),
("become", "r#become"),
("box", "r#box"),
("do", "r#do"),
("final", "r#final"),
("macro", "r#macro"),
("override", "r#override"),
("priv", "r#priv"),
("typeof", "r#typeof"),
("unsized", "r#unsized"),
("virtual", "r#virtual"),
("yield", "r#yield"),
("try", "r#try"),
];
Loading