prometheus-client-0.22.2/.cargo_vcs_info.json0000644000000001360000000000100145660ustar { "git": { "sha1": "de2723402f9f7604e1d4a7419ae11c3f14e9803d" }, "path_in_vcs": "" }prometheus-client-0.22.2/.github/dependabot.yml000064400000000000000000000001541046102023000175460ustar 00000000000000version: 2 updates: - package-ecosystem: "cargo" directory: "/" schedule: interval: "daily" prometheus-client-0.22.2/.github/workflows/rust.yml000064400000000000000000000112641046102023000204770ustar 00000000000000on: [push, pull_request] name: Continuous integration jobs: check: name: Check runs-on: ubuntu-latest steps: - name: Install Protoc uses: arduino/setup-protoc@v1 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true # Install prometheus_client python library. - uses: actions/setup-python@v2 with: python-version: '3.x' - run: pip3 install prometheus_client # Caching - name: Cache cargo registry uses: actions/cache@v1 with: path: ~/.cargo/registry key: cargo-registry-${{ hashFiles('Cargo.toml') }} - name: Cache cargo index uses: actions/cache@v1 with: path: ~/.cargo/git key: cargo-index-${{ hashFiles('Cargo.toml') }} - uses: actions-rs/cargo@v1 with: command: check - uses: actions-rs/cargo@v1 with: command: test args: --benches --all-features test: name: Test Suite runs-on: ubuntu-latest steps: - name: Install Protoc uses: arduino/setup-protoc@v1 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true # Install prometheus_client python library. - uses: actions/setup-python@v2 with: python-version: '3.x' - run: pip3 install prometheus_client # Caching - name: Cache cargo registry uses: actions/cache@v1 with: path: ~/.cargo/registry key: cargo-registry-${{ hashFiles('Cargo.toml') }} - name: Cache cargo index uses: actions/cache@v1 with: path: ~/.cargo/git key: cargo-index-${{ hashFiles('Cargo.toml') }} - uses: actions-rs/cargo@v1 with: command: test args: --all --all-features fmt: name: Rustfmt runs-on: ubuntu-latest steps: - name: Install Protoc uses: arduino/setup-protoc@v1 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true - run: rustup component add rustfmt - uses: actions-rs/cargo@v1 with: command: fmt args: --all -- --check clippy: name: Clippy runs-on: ubuntu-latest steps: - name: Install Protoc uses: arduino/setup-protoc@v1 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true - run: rustup component add clippy # Caching - name: Cache cargo registry uses: actions/cache@v1 with: path: ~/.cargo/registry key: cargo-registry-${{ hashFiles('Cargo.toml') }} - name: Cache cargo index uses: actions/cache@v1 with: path: ~/.cargo/git key: cargo-index-${{ hashFiles('Cargo.toml') }} - uses: actions-rs/cargo@v1 with: command: clippy args: --workspace --all-targets -- -D warnings check-rustdoc-links: name: Check rustdoc intra-doc links runs-on: ubuntu-latest steps: - name: Install Protoc uses: arduino/setup-protoc@v1 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true - uses: actions-rs/cargo@v1 env: RUSTDOCFLAGS: "--deny broken_intra_doc_links" with: command: doc args: --verbose --workspace --no-deps --document-private-items --all-features cross-compile: name: Cross compile runs-on: ubuntu-latest strategy: matrix: target: - armv7-unknown-linux-gnueabihf - powerpc-unknown-linux-gnu - powerpc64-unknown-linux-gnu - wasm32-unknown-unknown steps: - uses: actions/checkout@v2 - uses: dtolnay/rust-toolchain@stable with: target: ${{ matrix.target }} # Note that this does not test the `protobuf` feature (for now). See reasoning in https://github.com/prometheus/client_rust/pull/98/. - run: cargo check --target=${{ matrix.target }} prometheus-client-0.22.2/.gitignore000064400000000000000000000000231046102023000153410ustar 00000000000000/target Cargo.lock prometheus-client-0.22.2/CHANGELOG.md000064400000000000000000000214661046102023000152000ustar 00000000000000# Changelog 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.22.2] ### Added - Added `Gauge` implementation. See [PR 191]. [PR 191]: https://github.com/prometheus/client_rust/pull/191 ## [0.22.1] ### Added - Added `EncodeLabelValue` and `EncodeLabelKey` implementations for `Arc`, `Rc`, and `Box`. See [PR 188]. [PR 188]: https://github.com/prometheus/client_rust/pull/188 ## [0.22.0] ### Changed - Simplify `Collector` `trait` by enabling `Collector::collect` to encode metrics directly with a `DescriptorEncoder`. See [PR 149] for details. [PR 149]: https://github.com/prometheus/client_rust/pull/149 ## [0.21.2] ### Added - Added `sub_registry_with_labels` method to `Registry`. See [PR 145]. - Added `with_labels` and `with_prefix_and_labels` constructors to `Registry`. See [PR 147]. [PR 145]: https://github.com/prometheus/client_rust/pull/145 [PR 147]: https://github.com/prometheus/client_rust/pull/147 ## [0.21.1] ### Added - Implement `EncodeLabelValue` for `Option`. See [PR 137]. [PR 137]: https://github.com/prometheus/client_rust/pull/137 ## [0.21.0] ### Changed - Replace `impl EncodeMetric for RefCell` with a new type `ConstFamily` implementing `EncodeMetric`. ## [0.20.0] ### Added - Introduce `Collector` abstraction allowing users to provide additional metrics and their description on each scrape. See [PR 82]. - Introduce a `#[prometheus(flatten)]` attribute which can be used when deriving `EncodeLabelSet`, allowing a nested struct to be flattened during encoding. See [PR 118]. For example: ```rust #[derive(EncodeLabelSet, Hash, Clone, Eq, PartialEq, Debug)] struct CommonLabels { a: u64, b: u64, } #[derive(EncodeLabelSet, Hash, Clone, Eq, PartialEq, Debug)] struct Labels { unique: u64, #[prometheus(flatten)] common: CommonLabels, } ``` Would be encoded as: ``` my_metric{a="42",b="42",unique="42"} 42 ``` ### Fixed - Fix label encoding in protobuf feature. See [PR 123]. [PR 82]: https://github.com/prometheus/client_rust/pull/82 [PR 118]: https://github.com/prometheus/client_rust/pull/118 [PR 123]: https://github.com/prometheus/client_rust/pull/123 ## [0.19.0] This is a large release including multiple breaking changes. Major user-facing improvement of this release is support for the OpenMetrics Protobuf format. ### Upgrade guide: - Don't box before registering. ```diff registry.register( "my_metric", "This is my metric", - Box::new(my_metric.clone()), + my_metric.clone(), ); ``` - Gauge uses `i64` instead of `u64`. ```diff my_gauge - .set(42u64); + .set(42i64); ``` - Derive `EncodeLabelSet` for `struct` and `EncodeLabelValue` for `enum` instead of just `Encode` for all and require `Debug`. ```diff - #[derive(Clone, Hash, PartialEq, Eq, Encode)] + #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug)] struct Labels { path: String, method: Method, some_number: u64, } - #[derive(Clone, Hash, PartialEq, Eq, Encode)] + #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelValue, Debug)] enum Method { Get, #[allow(dead_code)] Put, } ``` - Encode as utf-8 and not as `[u8]`. ```diff - let mut buffer = vec![]; + let mut buffer = String::new(); encode(&mut buffer, ®istry).unwrap(); ``` For details on each of these, see changelog entries below. ### Added - Added support for the OpenMetrics protobuf format. See [PR 83]. - Added a `remove` method to `Family` to allow the removal of a specified label set from a family. See [PR 85]. - Added a `clear` method to `Family` to allow the removal of all label sets from a family. See [PR 85]. - Impl `TypedMetric` for `CounterWithExemplar` and `HistogramWithExemplar`, so that they can be used with `Family`. See [PR 96]. ### Changed - Always use dynamic dispatch on `Registry`, i.e. remove generic type parameter `M` from `Registry`. See [PR 105]. - Refactor encoding. See [PR 105]. - Introducing separate traits to encode - value (e.g. `EncodeCounterValue`) - label set (`EncodeLabelSet`), derivable for structs via `prometheus-client-derive-encode` - label (`EncodeLabel`) - label key (`EncodeLabelKey`) - label value (`EncodeLabelValue`), derivable for enums via `prometheus-client-derive-encode` - Encode as UTF-8 strings, not bytes. I.e. use `std::fmt::Write` instead of `std::io::Write`. - Use signed integers for `Gauge` for compliance with OpenMetrics protobuf format. See [PR 105]. [PR 83]: https://github.com/prometheus/client_rust/pull/83 [PR 85]: https://github.com/prometheus/client_rust/pull/85 [PR 96]: https://github.com/prometheus/client_rust/pull/96 [PR 105]: https://github.com/prometheus/client_rust/pull/105 ## [0.18.1] ### Fixed - Fix race condition in `Family::get_or_create`. See [PR 102]. [PR 102]: https://github.com/prometheus/client_rust/pull/102 ## [0.18.0] ### Changed - Use `parking_lot` instead of `std::sync::*`. Before `proemtheus-client` would use the `owning_ref` crate to map the target of a `std::sync::RwLockReadGuard`. `owning_ref` has multiple unsoundness issues, see https://rustsec.org/advisories/RUSTSEC-2022-0040.html. Instead of replacing `owning_ref` with a similar crate, we switch to locking via `parking_lot` which supports the above mapping natively. See [PR 78] and [issue 77]. [PR 78]: https://github.com/prometheus/client_rust/pull/78 [issue 77]: https://github.com/prometheus/client_rust/issues/77 ## [0.17.0] ### Changed - Updates to Rust 2021 Edition. See [PR 65]. ### Added - Added a `with_prefix` method to `Registry` to allow initializing a registry with a prefix. See [PR 70]. - Added `Debug` implementations on most public types that were missing them. See [PR 71]. - Added example for actix-web framework. See [PR 76]. ### Removed - Remove `Add` trait implementation for a private type which lead to compile time conflicts with existing `Add` implementations e.g. on `String`. See [PR 69]. [PR 65]: https://github.com/prometheus/client_rust/pull/65 [PR 69]: https://github.com/prometheus/client_rust/pull/69 [PR 70]: https://github.com/prometheus/client_rust/pull/70 [PR 71]: https://github.com/prometheus/client_rust/pull/71 [PR 76]: https://github.com/prometheus/client_rust/pull/76 ## [0.16.0] ### Changed - Require `Registry` default generic type `SendEncodeMetric` to be `Sync`. See [PR 58]. [PR 58]: https://github.com/prometheus/client_rust/pull/58 ## [0.15.1] - 2022-02-04 ### Added - Expose `Encoder` methods. See [PR 41]. ### Changed - Use `AtomicU32` on platforms that don't support `AtomicU64`. See [PR 42]. [PR 41]: https://github.com/prometheus/client_rust/pull/41 [PR 42]: https://github.com/prometheus/client_rust/pull/42 ## [0.15.0] - 2022-01-16 ### Changed - Release as `prometheus-client` and `prometheus-client-derive-text-encode`. ## [0.14.0] - 2021-12-29 ### Changed - Update to `itoa` `v1`. See [PR 28]. - Update to `dtoa` `v1`. See [PR 27]. ### Added - Implement `Gauge::dec` and `Gauge::dec_by`. See [PR 30]. [PR 28]: https://github.com/prometheus/client_rust/pull/28 [PR 27]: https://github.com/prometheus/client_rust/pull/27 [PR 30]: https://github.com/prometheus/client_rust/pull/30 ## [0.13.0] - 2021-11-21 _Note: This was initially released as `v0.12.1` but later on yanked due to it including a breaking change. See [PR 24] for details._ ### Added - Allow family to use constructors that do not coerce to function pointers. See [PR 21]. [PR 21]: https://github.com/prometheus/client_rust/pull/21 [PR 24]: https://github.com/prometheus/client_rust/pull/24 ## [0.12.0] - 2021-08-07 ### Added - Add `Registry::sub_registry_with_label`. See [PR 20]. ### Changed - Rename `Registry::sub_registry` to `Registry::sub_registry_with_prefix`. See [PR 20]. [PR 20]: https://github.com/prometheus/client_rust/pull/20 ## [0.11.2] - 2021-06-09 ### Fixed - Do not separate labels with spaces. ## [0.11.1] - 2021-06-08 ### Fixed - Encode Info metric labels. ## [0.11.0] - 2021-06-08 ### Added - Add support for OpenMetrics Info metrics (see [PR 18]). [PR 18]: https://github.com/prometheus/client_rust/pull/18 ## [0.10.1] - 2021-05-31 ### Added - Implement `Encode` for `u32`. ### Fixed - Update to prometheus-client-derive-text-encode v0.1.1 which handles keyword identifiers aka raw identifiers https://github.com/prometheus/client_rust/pull/16 ## [0.10.0] - 2021-04-29 ### Added - Added `metrics::histogram::linear_buckets`. https://github.com/prometheus/client_rust/issues/13 ### Changed - Renamed `metrics::histogram::exponential_series` to `metrics::histogram::exponential_buckets`. https://github.com/prometheus/client_rust/issues/13 prometheus-client-0.22.2/CODE_OF_CONDUCT.md000064400000000000000000000002301046102023000161500ustar 00000000000000# Prometheus Community Code of Conduct Prometheus follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md). prometheus-client-0.22.2/Cargo.lock0000644000002376000000000000100125510ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "actix-codec" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57a7559404a7f3573127aab53c08ce37a6c6a315c374a31070f3c91cd1b4a7fe" dependencies = [ "bitflags", "bytes", "futures-core", "futures-sink", "log", "memchr", "pin-project-lite 0.2.9", "tokio", "tokio-util", ] [[package]] name = "actix-http" version = "3.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c83abf9903e1f0ad9973cc4f7b9767fd5a03a583f51a5b7a339e07987cd2724" dependencies = [ "actix-codec", "actix-rt", "actix-service", "actix-utils", "ahash", "base64 0.13.1", "bitflags", "brotli", "bytes", "bytestring", "derive_more", "encoding_rs", "flate2", "futures-core", "h2", "http", "httparse", "httpdate", "itoa", "language-tags", "local-channel", "mime", "percent-encoding", "pin-project-lite 0.2.9", "rand 0.8.5", "sha1 0.10.5", "smallvec", "tracing", "zstd", ] [[package]] name = "actix-macros" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6" dependencies = [ "quote", "syn 1.0.103", ] [[package]] name = "actix-router" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66ff4d247d2b160861fa2866457e85706833527840e4133f8f49aa423a38799" dependencies = [ "bytestring", "http", "regex", "serde", "tracing", ] [[package]] name = "actix-rt" version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ea16c295198e958ef31930a6ef37d0fb64e9ca3b6116e6b93a8bdae96ee1000" dependencies = [ "futures-core", "tokio", ] [[package]] name = "actix-server" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0da34f8e659ea1b077bb4637948b815cd3768ad5a188fdcd74ff4d84240cd824" dependencies = [ "actix-rt", "actix-service", "actix-utils", "futures-core", "futures-util", "mio", "num_cpus", "socket2", "tokio", "tracing", ] [[package]] name = "actix-service" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" dependencies = [ "futures-core", "paste", "pin-project-lite 0.2.9", ] [[package]] name = "actix-utils" version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" dependencies = [ "local-waker", "pin-project-lite 0.2.9", ] [[package]] name = "actix-web" version = "4.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d48f7b6534e06c7bfc72ee91db7917d4af6afe23e7d223b51e68fffbb21e96b9" dependencies = [ "actix-codec", "actix-http", "actix-macros", "actix-router", "actix-rt", "actix-server", "actix-service", "actix-utils", "actix-web-codegen", "ahash", "bytes", "bytestring", "cfg-if 1.0.0", "cookie 0.16.1", "derive_more", "encoding_rs", "futures-core", "futures-util", "http", "itoa", "language-tags", "log", "mime", "once_cell", "pin-project-lite 0.2.9", "regex", "serde", "serde_json", "serde_urlencoded", "smallvec", "socket2", "time 0.3.17", "url", ] [[package]] name = "actix-web-codegen" version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa9362663c8643d67b2d5eafba49e4cb2c8a053a29ed00a0bea121f17c76b13" dependencies = [ "actix-router", "proc-macro2", "quote", "syn 1.0.103", ] [[package]] name = "adler" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aead" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331" dependencies = [ "generic-array", ] [[package]] name = "aes" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561" dependencies = [ "aes-soft", "aesni", "cipher", ] [[package]] name = "aes-gcm" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5278b5fabbb9bd46e24aa69b2fdea62c99088e0a950a9be40e3e0101298f88da" dependencies = [ "aead", "aes", "cipher", "ctr", "ghash", "subtle", ] [[package]] name = "aes-soft" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072" dependencies = [ "cipher", "opaque-debug", ] [[package]] name = "aesni" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce" dependencies = [ "cipher", "opaque-debug", ] [[package]] name = "ahash" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ "getrandom 0.2.8", "once_cell", "version_check", ] [[package]] name = "aho-corasick" version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] [[package]] name = "alloc-no-stdlib" version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" [[package]] name = "alloc-stdlib" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" dependencies = [ "alloc-no-stdlib", ] [[package]] name = "android_system_properties" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ "libc", ] [[package]] name = "anes" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstyle" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" [[package]] name = "anyhow" version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" [[package]] name = "arrayref" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" [[package]] name = "arrayvec" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "async-attributes" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" dependencies = [ "quote", "syn 1.0.103", ] [[package]] name = "async-channel" version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28" dependencies = [ "concurrent-queue 1.2.4", "event-listener", "futures-core", ] [[package]] name = "async-dup" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7427a12b8dc09291528cfb1da2447059adb4a257388c2acd6497a79d55cf6f7c" dependencies = [ "futures-io", "simple-mutex", ] [[package]] name = "async-executor" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" dependencies = [ "async-lock", "async-task", "concurrent-queue 2.0.0", "fastrand", "futures-lite", "slab", ] [[package]] name = "async-global-executor" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" dependencies = [ "async-channel", "async-executor", "async-io", "async-lock", "blocking", "futures-lite", "once_cell", ] [[package]] name = "async-h1" version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8101020758a4fc3a7c326cb42aa99e9fa77cbfb76987c128ad956406fe1f70a7" dependencies = [ "async-channel", "async-dup", "async-std", "futures-core", "http-types", "httparse", "log", "pin-project", ] [[package]] name = "async-io" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" dependencies = [ "async-lock", "autocfg", "concurrent-queue 2.0.0", "futures-lite", "libc", "log", "parking", "polling", "slab", "socket2", "waker-fn", "windows-sys 0.42.0", ] [[package]] name = "async-lock" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" dependencies = [ "event-listener", "futures-lite", ] [[package]] name = "async-process" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6381ead98388605d0d9ff86371043b5aa922a3905824244de40dc263a14fcba4" dependencies = [ "async-io", "async-lock", "autocfg", "blocking", "cfg-if 1.0.0", "event-listener", "futures-lite", "libc", "signal-hook", "windows-sys 0.42.0", ] [[package]] name = "async-session" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "345022a2eed092cd105cc1b26fd61c341e100bd5fcbbd792df4baf31c2cc631f" dependencies = [ "anyhow", "async-std", "async-trait", "base64 0.12.3", "bincode", "blake3", "chrono", "hmac 0.8.1", "kv-log-macro", "rand 0.7.3", "serde", "serde_json", "sha2", ] [[package]] name = "async-sse" version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53bba003996b8fd22245cd0c59b869ba764188ed435392cf2796d03b805ade10" dependencies = [ "async-channel", "async-std", "http-types", "log", "memchr", "pin-project-lite 0.1.12", ] [[package]] name = "async-std" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" dependencies = [ "async-attributes", "async-channel", "async-global-executor", "async-io", "async-lock", "async-process", "crossbeam-utils", "futures-channel", "futures-core", "futures-io", "futures-lite", "gloo-timers", "kv-log-macro", "log", "memchr", "once_cell", "pin-project-lite 0.2.9", "pin-utils", "slab", "wasm-bindgen-futures", ] [[package]] name = "async-task" version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" [[package]] name = "async-trait" version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" dependencies = [ "proc-macro2", "quote", "syn 1.0.103", ] [[package]] name = "atomic-waker" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base-x" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" [[package]] name = "base64" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" [[package]] name = "base64" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "bincode" version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" dependencies = [ "serde", ] [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "blake3" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b64485778c4f16a6a5a9d335e80d449ac6c70cdd6a06d2af18a6f6f775a125b3" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if 0.1.10", "constant_time_eq", "crypto-mac 0.8.0", "digest 0.9.0", ] [[package]] name = "block-buffer" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ "generic-array", ] [[package]] name = "block-buffer" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ "generic-array", ] [[package]] name = "blocking" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c67b173a56acffd6d2326fb7ab938ba0b00a71480e14902b2591c87bc5741e8" dependencies = [ "async-channel", "async-lock", "async-task", "atomic-waker", "fastrand", "futures-lite", ] [[package]] name = "brotli" version = "3.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", "brotli-decompressor", ] [[package]] name = "brotli-decompressor" version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59ad2d4653bf5ca36ae797b1f4bb4dbddb60ce49ca4aed8a2ce4829f60425b80" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", ] [[package]] name = "bumpalo" version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" [[package]] name = "bytes" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" [[package]] name = "bytestring" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7f83e57d9154148e355404702e2694463241880b939570d7c97c014da7a69a1" dependencies = [ "bytes", ] [[package]] name = "cache-padded" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" [[package]] name = "cast" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" version = "1.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" dependencies = [ "jobserver", ] [[package]] name = "cfg-if" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" dependencies = [ "iana-time-zone", "js-sys", "num-integer", "num-traits", "serde", "time 0.1.45", "wasm-bindgen", "winapi", ] [[package]] name = "ciborium" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f" dependencies = [ "ciborium-io", "ciborium-ll", "serde", ] [[package]] name = "ciborium-io" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369" [[package]] name = "ciborium-ll" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b" dependencies = [ "ciborium-io", "half", ] [[package]] name = "cipher" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" dependencies = [ "generic-array", ] [[package]] name = "clap" version = "4.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ed2379f8603fa2b7509891660e802b88c70a79a6427a70abb5968054de2c28" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" version = "4.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72394f3339a76daf211e57d4bcb374410f3965dcc606dd0e03738c7888766980" dependencies = [ "anstyle", "bitflags", "clap_lex", ] [[package]] name = "clap_lex" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" [[package]] name = "codespan-reporting" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" dependencies = [ "termcolor", "unicode-width", ] [[package]] name = "concurrent-queue" version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c" dependencies = [ "cache-padded", ] [[package]] name = "concurrent-queue" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd7bef69dc86e3c610e4e7aed41035e2a7ed12e72dd7530f61327a6579a4390b" dependencies = [ "crossbeam-utils", ] [[package]] name = "const_fn" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935" [[package]] name = "constant_time_eq" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "convert_case" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "cookie" version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03a5d7b21829bc7b4bf4754a978a241ae54ea55a40f92bb20216e54096f4b951" dependencies = [ "aes-gcm", "base64 0.13.1", "hkdf", "hmac 0.10.1", "percent-encoding", "rand 0.8.5", "sha2", "time 0.2.27", "version_check", ] [[package]] name = "cookie" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "344adc371239ef32293cb1c4fe519592fcf21206c79c02854320afcdf3ab4917" dependencies = [ "percent-encoding", "time 0.3.17", "version_check", ] [[package]] name = "core-foundation-sys" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "cpufeatures" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" dependencies = [ "libc", ] [[package]] name = "cpuid-bool" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba" [[package]] name = "crc32fast" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "criterion" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" dependencies = [ "anes", "cast", "ciborium", "clap", "criterion-plot", "is-terminal", "itertools", "num-traits", "once_cell", "oorandom", "plotters", "rayon", "regex", "serde", "serde_derive", "serde_json", "tinytemplate", "walkdir", ] [[package]] name = "criterion-plot" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", "itertools", ] [[package]] name = "crossbeam-channel" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" dependencies = [ "cfg-if 1.0.0", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" dependencies = [ "autocfg", "cfg-if 1.0.0", "crossbeam-utils", "memoffset 0.7.1", "scopeguard", ] [[package]] name = "crossbeam-utils" version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "crypto-common" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", "typenum", ] [[package]] name = "crypto-mac" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ "generic-array", "subtle", ] [[package]] name = "crypto-mac" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a" dependencies = [ "generic-array", "subtle", ] [[package]] name = "ctor" version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ "quote", "syn 1.0.103", ] [[package]] name = "ctr" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f" dependencies = [ "cipher", ] [[package]] name = "cxx" version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4a41a86530d0fe7f5d9ea779916b7cadd2d4f9add748b99c2c029cbbdfaf453" dependencies = [ "cc", "cxxbridge-flags", "cxxbridge-macro", "link-cplusplus", ] [[package]] name = "cxx-build" version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06416d667ff3e3ad2df1cd8cd8afae5da26cf9cec4d0825040f88b5ca659a2f0" dependencies = [ "cc", "codespan-reporting", "once_cell", "proc-macro2", "quote", "scratch", "syn 1.0.103", ] [[package]] name = "cxxbridge-flags" version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "820a9a2af1669deeef27cb271f476ffd196a2c4b6731336011e0ba63e2c7cf71" [[package]] name = "cxxbridge-macro" version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470" dependencies = [ "proc-macro2", "quote", "syn 1.0.103", ] [[package]] name = "derive_more" version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version 0.4.0", "syn 1.0.103", ] [[package]] name = "digest" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ "generic-array", ] [[package]] name = "digest" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer 0.10.3", "crypto-common", ] [[package]] name = "discard" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" [[package]] name = "dtoa" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8a6eee2d5d0d113f015688310da018bd1d864d86bd567c8fca9c266889e1bfa" [[package]] name = "either" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "encoding_rs" version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "env_logger" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" dependencies = [ "log", "regex", ] [[package]] name = "erased-serde" version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54558e0ba96fbe24280072642eceb9d7d442e32c7ec0ea9e7ecd7b4ea2cf4e11" dependencies = [ "serde", ] [[package]] name = "errno" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", "libc", "windows-sys 0.48.0", ] [[package]] name = "errno-dragonfly" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" dependencies = [ "cc", "libc", ] [[package]] name = "event-listener" version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "fastrand" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ "instant", ] [[package]] name = "femme" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc04871e5ae3aa2952d552dae6b291b3099723bf779a8054281c1366a54613ef" dependencies = [ "cfg-if 1.0.0", "js-sys", "log", "serde", "serde_derive", "serde_json", "wasm-bindgen", "web-sys", ] [[package]] name = "fixedbitset" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ "crc32fast", "miniz_oxide", ] [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ "percent-encoding", ] [[package]] name = "futures-channel" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" dependencies = [ "futures-core", ] [[package]] name = "futures-core" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" [[package]] name = "futures-io" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" [[package]] name = "futures-lite" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" dependencies = [ "fastrand", "futures-core", "futures-io", "memchr", "parking", "pin-project-lite 0.2.9", "waker-fn", ] [[package]] name = "futures-macro" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" dependencies = [ "proc-macro2", "quote", "syn 1.0.103", ] [[package]] name = "futures-sink" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" [[package]] name = "futures-task" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" [[package]] name = "futures-util" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" dependencies = [ "futures-core", "futures-macro", "futures-task", "pin-project-lite 0.2.9", "pin-utils", "slab", ] [[package]] name = "generic-array" version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", "version_check", ] [[package]] name = "getrandom" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ "cfg-if 1.0.0", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] [[package]] name = "getrandom" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if 1.0.0", "libc", "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] name = "ghash" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97304e4cd182c3846f7575ced3890c53012ce534ad9114046b0a9e00bb30a375" dependencies = [ "opaque-debug", "polyval", ] [[package]] name = "gloo-timers" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9" dependencies = [ "futures-channel", "futures-core", "js-sys", "wasm-bindgen", ] [[package]] name = "h2" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", "http", "indexmap", "slab", "tokio", "tokio-util", "tracing", ] [[package]] name = "half" version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "heck" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" [[package]] name = "hermit-abi" version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ "libc", ] [[package]] name = "hermit-abi" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" [[package]] name = "hkdf" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f" dependencies = [ "digest 0.9.0", "hmac 0.10.1", ] [[package]] name = "hmac" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" dependencies = [ "crypto-mac 0.8.0", "digest 0.9.0", ] [[package]] name = "hmac" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" dependencies = [ "crypto-mac 0.10.1", "digest 0.9.0", ] [[package]] name = "http" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes", "fnv", "itoa", ] [[package]] name = "http-body" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes", "http", "pin-project-lite 0.2.9", ] [[package]] name = "http-client" version = "6.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1947510dc91e2bf586ea5ffb412caad7673264e14bb39fb9078da114a94ce1a5" dependencies = [ "async-trait", "cfg-if 1.0.0", "http-types", "log", ] [[package]] name = "http-types" version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e9b187a72d63adbfba487f48095306ac823049cb504ee195541e91c7775f5ad" dependencies = [ "anyhow", "async-channel", "async-std", "base64 0.13.1", "cookie 0.14.4", "futures-lite", "infer", "pin-project-lite 0.2.9", "rand 0.7.3", "serde", "serde_json", "serde_qs", "serde_urlencoded", "url", ] [[package]] name = "httparse" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" version = "0.14.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", "http", "http-body", "httparse", "httpdate", "itoa", "pin-project-lite 0.2.9", "socket2", "tokio", "tower-service", "tracing", "want", ] [[package]] name = "iana-time-zone" version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", "winapi", ] [[package]] name = "iana-time-zone-haiku" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" dependencies = [ "cxx", "cxx-build", ] [[package]] name = "idna" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ "unicode-bidi", "unicode-normalization", ] [[package]] name = "indexmap" version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", "hashbrown", ] [[package]] name = "indoc" version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" [[package]] name = "infer" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" [[package]] name = "instant" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "io-lifetimes" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ "hermit-abi 0.3.1", "libc", "windows-sys 0.48.0", ] [[package]] name = "is-terminal" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ "hermit-abi 0.3.1", "io-lifetimes", "rustix", "windows-sys 0.48.0", ] [[package]] name = "itertools" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] [[package]] name = "itoa" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] name = "jobserver" version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" dependencies = [ "libc", ] [[package]] name = "js-sys" version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] [[package]] name = "kv-log-macro" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" dependencies = [ "log", ] [[package]] name = "language-tags" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" version = "0.2.144" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" [[package]] name = "link-cplusplus" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" dependencies = [ "cc", ] [[package]] name = "linux-raw-sys" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "local-channel" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f303ec0e94c6c54447f84f3b0ef7af769858a9c4ef56ef2a986d3dcd4c3fc9c" dependencies = [ "futures-core", "futures-sink", "futures-util", "local-waker", ] [[package]] name = "local-waker" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e34f76eb3611940e0e7d53a9aaa4e6a3151f69541a282fd0dad5571420c53ff1" [[package]] name = "lock_api" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", ] [[package]] name = "log" version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if 1.0.0", "serde", "value-bag", ] [[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" dependencies = [ "autocfg", ] [[package]] name = "memoffset" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] [[package]] name = "mime" version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "miniz_oxide" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" dependencies = [ "adler", ] [[package]] name = "mio" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.42.0", ] [[package]] name = "multimap" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] name = "num-integer" version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg", "num-traits", ] [[package]] name = "num-traits" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" dependencies = [ "hermit-abi 0.1.19", "libc", ] [[package]] name = "once_cell" version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" [[package]] name = "oorandom" version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "opaque-debug" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "parking" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" [[package]] name = "parking_lot" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", "parking_lot_core", ] [[package]] name = "parking_lot_core" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", "windows-sys 0.42.0", ] [[package]] name = "paste" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" [[package]] name = "percent-encoding" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "petgraph" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" dependencies = [ "fixedbitset", "indexmap", ] [[package]] name = "pin-project" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", "syn 1.0.103", ] [[package]] name = "pin-project-lite" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "plotters" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" dependencies = [ "num-traits", "plotters-backend", "plotters-svg", "wasm-bindgen", "web-sys", ] [[package]] name = "plotters-backend" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" [[package]] name = "plotters-svg" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" dependencies = [ "plotters-backend", ] [[package]] name = "polling" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7d73f1eaed1ca1fb37b54dcc9b38e3b17d6c7b8ecb7abfffcac8d0351f17d4" dependencies = [ "autocfg", "cfg-if 1.0.0", "libc", "log", "wepoll-ffi", "windows-sys 0.42.0", ] [[package]] name = "polyval" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eebcc4aa140b9abd2bc40d9c3f7ccec842679cd79045ac3a7ac698c1a064b7cd" dependencies = [ "cpuid-bool", "opaque-debug", "universal-hash", ] [[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "prettyplease" version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c142c0e46b57171fe0c528bee8c5b7569e80f0c17e377cd0e30ea57dbc11bb51" dependencies = [ "proc-macro2", "syn 1.0.103", ] [[package]] name = "proc-macro-hack" version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] [[package]] name = "prometheus-client" version = "0.22.2" dependencies = [ "actix-web", "async-std", "criterion", "dtoa", "http-types", "hyper", "itoa", "parking_lot", "prometheus-client-derive-encode", "prost", "prost-build", "prost-types", "pyo3", "quickcheck", "rand 0.8.5", "tide", "tokio", ] [[package]] name = "prometheus-client-derive-encode" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", "syn 2.0.28", ] [[package]] name = "prost" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0841812012b2d4a6145fae9a6af1534873c32aa67fff26bd09f8fa42c83f95a" dependencies = [ "bytes", "prost-derive", ] [[package]] name = "prost-build" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d8b442418ea0822409d9e7d047cbf1e7e9e1760b172bf9982cf29d517c93511" dependencies = [ "bytes", "heck", "itertools", "lazy_static", "log", "multimap", "petgraph", "prettyplease", "prost", "prost-types", "regex", "syn 1.0.103", "tempfile", "which", ] [[package]] name = "prost-derive" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "164ae68b6587001ca506d3bf7f1000bfa248d0e1217b618108fba4ec1d0cc306" dependencies = [ "anyhow", "itertools", "proc-macro2", "quote", "syn 1.0.103", ] [[package]] name = "prost-types" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "747761bc3dc48f9a34553bf65605cf6cb6288ba219f3450b4275dbd81539551a" dependencies = [ "bytes", "prost", ] [[package]] name = "pyo3" version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a89dc7a5850d0e983be1ec2a463a171d20990487c3cfcd68b5363f1ee3d6fe0" dependencies = [ "cfg-if 1.0.0", "indoc", "libc", "memoffset 0.9.0", "parking_lot", "pyo3-build-config", "pyo3-ffi", "pyo3-macros", "unindent", ] [[package]] name = "pyo3-build-config" version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07426f0d8fe5a601f26293f300afd1a7b1ed5e78b2a705870c5f30893c5163be" dependencies = [ "once_cell", "target-lexicon", ] [[package]] name = "pyo3-ffi" version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbb7dec17e17766b46bca4f1a4215a85006b4c2ecde122076c562dd058da6cf1" dependencies = [ "libc", "pyo3-build-config", ] [[package]] name = "pyo3-macros" version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f738b4e40d50b5711957f142878cfa0f28e054aa0ebdfc3fd137a843f74ed3" dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", "syn 2.0.28", ] [[package]] name = "pyo3-macros-backend" version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fc910d4851847827daf9d6cdd4a823fbdaab5b8818325c5e97a86da79e8881f" dependencies = [ "heck", "proc-macro2", "quote", "syn 2.0.28", ] [[package]] name = "quickcheck" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" dependencies = [ "env_logger", "log", "rand 0.8.5", ] [[package]] name = "quote" version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] [[package]] name = "rand" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ "getrandom 0.1.16", "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", "rand_hc", ] [[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", ] [[package]] name = "rand_chacha" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" dependencies = [ "ppv-lite86", "rand_core 0.5.1", ] [[package]] name = "rand_chacha" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core 0.6.4", ] [[package]] name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ "getrandom 0.1.16", ] [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom 0.2.8", ] [[package]] name = "rand_hc" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ "rand_core 0.5.1", ] [[package]] name = "rayon" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b" dependencies = [ "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" dependencies = [ "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", "num_cpus", ] [[package]] name = "redox_syscall" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] [[package]] name = "regex" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" dependencies = [ "winapi", ] [[package]] name = "route-recognizer" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56770675ebc04927ded3e60633437841581c285dc6236109ea25fbf3beb7b59e" [[package]] name = "rustc_version" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ "semver 0.9.0", ] [[package]] name = "rustc_version" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ "semver 1.0.14", ] [[package]] name = "rustix" version = "0.37.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" dependencies = [ "bitflags", "errno", "io-lifetimes", "libc", "linux-raw-sys", "windows-sys 0.48.0", ] [[package]] name = "ryu" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "same-file" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ "winapi-util", ] [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "scratch" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" [[package]] name = "semver" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ "semver-parser", ] [[package]] name = "semver" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" [[package]] name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" dependencies = [ "proc-macro2", "quote", "syn 1.0.103", ] [[package]] name = "serde_fmt" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2963a69a2b3918c1dc75a45a18bd3fcd1120e31d3f59deb1b2f9b5d5ffb8baa4" dependencies = [ "serde", ] [[package]] name = "serde_json" version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" dependencies = [ "itoa", "ryu", "serde", ] [[package]] name = "serde_qs" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7715380eec75f029a4ef7de39a9200e0a63823176b759d055b613f5a87df6a6" dependencies = [ "percent-encoding", "serde", "thiserror", ] [[package]] name = "serde_urlencoded" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", "itoa", "ryu", "serde", ] [[package]] name = "sha1" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" dependencies = [ "sha1_smol", ] [[package]] name = "sha1" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if 1.0.0", "cpufeatures", "digest 0.10.6", ] [[package]] name = "sha1_smol" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" [[package]] name = "sha2" version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer 0.9.0", "cfg-if 1.0.0", "cpufeatures", "digest 0.9.0", "opaque-debug", ] [[package]] name = "signal-hook" version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" dependencies = [ "libc", "signal-hook-registry", ] [[package]] name = "signal-hook-registry" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" dependencies = [ "libc", ] [[package]] name = "simple-mutex" version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38aabbeafa6f6dead8cebf246fe9fae1f9215c8d29b3a69f93bd62a9e4a3dcd6" dependencies = [ "event-listener", ] [[package]] name = "slab" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" dependencies = [ "autocfg", ] [[package]] name = "smallvec" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "socket2" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ "libc", "winapi", ] [[package]] name = "standback" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff" dependencies = [ "version_check", ] [[package]] name = "stdweb" version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" dependencies = [ "discard", "rustc_version 0.2.3", "stdweb-derive", "stdweb-internal-macros", "stdweb-internal-runtime", "wasm-bindgen", ] [[package]] name = "stdweb-derive" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" dependencies = [ "proc-macro2", "quote", "serde", "serde_derive", "syn 1.0.103", ] [[package]] name = "stdweb-internal-macros" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" dependencies = [ "base-x", "proc-macro2", "quote", "serde", "serde_derive", "serde_json", "sha1 0.6.1", "syn 1.0.103", ] [[package]] name = "stdweb-internal-runtime" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" [[package]] name = "subtle" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "sval" version = "1.0.0-alpha.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45f6ee7c7b87caf59549e9fe45d6a69c75c8019e79e212a835c5da0e92f0ba08" dependencies = [ "serde", ] [[package]] name = "syn" version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "syn" version = "2.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "target-lexicon" version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d" [[package]] name = "tempfile" version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ "cfg-if 1.0.0", "fastrand", "libc", "redox_syscall", "remove_dir_all", "winapi", ] [[package]] name = "termcolor" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] [[package]] name = "thiserror" version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ "proc-macro2", "quote", "syn 1.0.103", ] [[package]] name = "tide" version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c459573f0dd2cc734b539047f57489ea875af8ee950860ded20cf93a79a1dee0" dependencies = [ "async-h1", "async-session", "async-sse", "async-std", "async-trait", "femme", "futures-util", "http-client", "http-types", "kv-log-macro", "log", "pin-project-lite 0.2.9", "route-recognizer", "serde", "serde_json", ] [[package]] name = "time" version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" dependencies = [ "libc", "wasi 0.10.0+wasi-snapshot-preview1", "winapi", ] [[package]] name = "time" version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242" dependencies = [ "const_fn", "libc", "standback", "stdweb", "time-macros 0.1.1", "version_check", "winapi", ] [[package]] name = "time" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" dependencies = [ "itoa", "serde", "time-core", "time-macros 0.2.6", ] [[package]] name = "time-core" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" [[package]] name = "time-macros" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" dependencies = [ "proc-macro-hack", "time-macros-impl", ] [[package]] name = "time-macros" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" dependencies = [ "time-core", ] [[package]] name = "time-macros-impl" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" dependencies = [ "proc-macro-hack", "proc-macro2", "quote", "standback", "syn 1.0.103", ] [[package]] name = "tinytemplate" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" dependencies = [ "serde", "serde_json", ] [[package]] name = "tinyvec" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] [[package]] name = "tinyvec_macros" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3" dependencies = [ "autocfg", "bytes", "libc", "memchr", "mio", "num_cpus", "parking_lot", "pin-project-lite 0.2.9", "signal-hook-registry", "socket2", "tokio-macros", "winapi", ] [[package]] name = "tokio-macros" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" dependencies = [ "proc-macro2", "quote", "syn 1.0.103", ] [[package]] name = "tokio-util" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite 0.2.9", "tokio", "tracing", ] [[package]] name = "tower-service" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if 1.0.0", "log", "pin-project-lite 0.2.9", "tracing-core", ] [[package]] name = "tracing-core" version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ "once_cell", ] [[package]] name = "try-lock" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "typenum" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "unicode-bidi" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "unicode-normalization" version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-width" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "unindent" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" [[package]] name = "universal-hash" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" dependencies = [ "generic-array", "subtle", ] [[package]] name = "url" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", "idna", "percent-encoding", "serde", ] [[package]] name = "value-bag" version = "1.0.0-alpha.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55" dependencies = [ "ctor", "erased-serde", "serde", "serde_fmt", "sval", "version_check", ] [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "waker-fn" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" [[package]] name = "walkdir" version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" dependencies = [ "same-file", "winapi", "winapi-util", ] [[package]] name = "want" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" dependencies = [ "log", "try-lock", ] [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if 1.0.0", "serde", "serde_json", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", "syn 1.0.103", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" dependencies = [ "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", "syn 1.0.103", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "web-sys" version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] name = "wepoll-ffi" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" dependencies = [ "cc", ] [[package]] name = "which" version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" dependencies = [ "either", "libc", "once_cell", ] [[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ "winapi", ] [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ "windows_aarch64_gnullvm 0.42.0", "windows_aarch64_msvc 0.42.0", "windows_i686_gnu 0.42.0", "windows_i686_msvc 0.42.0", "windows_x86_64_gnu 0.42.0", "windows_x86_64_gnullvm 0.42.0", "windows_x86_64_msvc 0.42.0", ] [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" dependencies = [ "windows_aarch64_gnullvm 0.48.0", "windows_aarch64_msvc 0.48.0", "windows_i686_gnu 0.48.0", "windows_i686_msvc 0.48.0", "windows_x86_64_gnu 0.48.0", "windows_x86_64_gnullvm 0.48.0", "windows_x86_64_msvc 0.48.0", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" [[package]] name = "windows_aarch64_msvc" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" [[package]] name = "windows_i686_gnu" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" [[package]] name = "windows_i686_msvc" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" [[package]] name = "windows_x86_64_gnu" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" [[package]] name = "windows_x86_64_gnullvm" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" [[package]] name = "windows_x86_64_msvc" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" [[package]] name = "windows_x86_64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "zstd" version = "0.11.2+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" version = "5.0.2+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" dependencies = [ "libc", "zstd-sys", ] [[package]] name = "zstd-sys" version = "2.0.3+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44ccf97612ac95f3ccb89b2d7346b345e52f1c3019be4984f0455fb4ba991f8a" dependencies = [ "cc", "libc", ] prometheus-client-0.22.2/Cargo.toml0000644000000045010000000000100125640ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "prometheus-client" version = "0.22.2" authors = ["Max Inden "] description = "Open Metrics client library allowing users to natively instrument applications." homepage = "https://github.com/prometheus/client_rust" documentation = "https://docs.rs/prometheus-client" readme = "README.md" keywords = [ "openmetrics", "prometheus", "metrics", "instrumentation", "monitoring", ] license = "Apache-2.0 OR MIT" repository = "https://github.com/prometheus/client_rust" [[bench]] name = "baseline" harness = false [[bench]] name = "family" harness = false [[bench]] name = "text" path = "benches/encoding/text.rs" harness = false required-features = [] [[bench]] name = "proto" path = "benches/encoding/proto.rs" harness = false required-features = ["protobuf"] [dependencies.dtoa] version = "1.0" [dependencies.itoa] version = "1.0" [dependencies.parking_lot] version = "0.12" [dependencies.prometheus-client-derive-encode] version = "0.4.1" [dependencies.prost] version = "0.11.0" optional = true [dependencies.prost-types] version = "0.11.0" optional = true [dev-dependencies.actix-web] version = "4" [dev-dependencies.async-std] version = "1" features = ["attributes"] [dev-dependencies.criterion] version = "0.5" [dev-dependencies.http-types] version = "2" [dev-dependencies.hyper] version = "0.14.16" features = [ "server", "http1", "tcp", ] [dev-dependencies.pyo3] version = "0.20" [dev-dependencies.quickcheck] version = "1" [dev-dependencies.rand] version = "0.8.4" [dev-dependencies.tide] version = "0.16" [dev-dependencies.tokio] version = "1" features = [ "rt-multi-thread", "net", "macros", "signal", ] [build-dependencies.prost-build] version = "0.11.0" optional = true [features] default = [] protobuf = [ "dep:prost", "dep:prost-types", "dep:prost-build", ] prometheus-client-0.22.2/Cargo.toml.orig0000644000000030560000000000100135270ustar [package] name = "prometheus-client" version = "0.22.2" authors = ["Max Inden "] edition = "2021" description = "Open Metrics client library allowing users to natively instrument applications." license = "Apache-2.0 OR MIT" keywords = ["openmetrics", "prometheus", "metrics", "instrumentation", "monitoring"] repository = "https://github.com/prometheus/client_rust" homepage = "https://github.com/prometheus/client_rust" documentation = "https://docs.rs/prometheus-client" [features] default = [] protobuf = ["dep:prost", "dep:prost-types", "dep:prost-build"] [workspace] members = ["derive-encode"] [dependencies] 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 } [dev-dependencies] async-std = { version = "1", features = ["attributes"] } criterion = "0.5" http-types = "2" pyo3 = "0.20" 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"] } [build-dependencies] prost-build = { version = "0.11.0", optional = true } [[bench]] name = "baseline" harness = false [[bench]] name = "family" harness = false [[bench]] name = "text" path = "benches/encoding/text.rs" harness = false required-features = [] [[bench]] name = "proto" path = "benches/encoding/proto.rs" harness = false required-features = ["protobuf"] prometheus-client-0.22.2/Cargo.toml.orig000064400000000000000000000030561046102023000162510ustar 00000000000000[package] name = "prometheus-client" version = "0.22.2" authors = ["Max Inden "] edition = "2021" description = "Open Metrics client library allowing users to natively instrument applications." license = "Apache-2.0 OR MIT" keywords = ["openmetrics", "prometheus", "metrics", "instrumentation", "monitoring"] repository = "https://github.com/prometheus/client_rust" homepage = "https://github.com/prometheus/client_rust" documentation = "https://docs.rs/prometheus-client" [features] default = [] protobuf = ["dep:prost", "dep:prost-types", "dep:prost-build"] [workspace] members = ["derive-encode"] [dependencies] 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 } [dev-dependencies] async-std = { version = "1", features = ["attributes"] } criterion = "0.5" http-types = "2" pyo3 = "0.20" 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"] } [build-dependencies] prost-build = { version = "0.11.0", optional = true } [[bench]] name = "baseline" harness = false [[bench]] name = "family" harness = false [[bench]] name = "text" path = "benches/encoding/text.rs" harness = false required-features = [] [[bench]] name = "proto" path = "benches/encoding/proto.rs" harness = false required-features = ["protobuf"] prometheus-client-0.22.2/LICENSE-APACHE000064400000000000000000000251561046102023000153130ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. prometheus-client-0.22.2/LICENSE-MIT000064400000000000000000000020521046102023000150110ustar 00000000000000MIT License Copyright (c) 2020 Max Inden Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. prometheus-client-0.22.2/MAINTAINERS.md000064400000000000000000000000551046102023000154520ustar 00000000000000- Max Inden ( / @mxinden) prometheus-client-0.22.2/README.md000064400000000000000000000054051046102023000146410ustar 00000000000000# Prometheus Rust client library [![Test Status](https://github.com/prometheus/client_rust/actions/workflows/rust.yml/badge.svg?event=push)](https://github.com/prometheus/client_rust/actions) [![Crate](https://img.shields.io/crates/v/prometheus-client.svg)](https://crates.io/crates/prometheus-client) [![API](https://docs.rs/prometheus-client/badge.svg)](https://docs.rs/prometheus-client) [Rust](https://github.com/rust-lang/) client library implementation of the [Open Metrics specification](https://github.com/OpenObservability/OpenMetrics). Allows developers to instrument applications and thus enables operators to monitor said applications with monitoring systems like [Prometheus](https://prometheus.io/). **Documentation**: https://docs.rs/prometheus-client/ ## Goals - No `unsafe`. Don't use unsafe Rust within the library itself. - Type safe. Leverage Rust's type system to catch common instrumentation mistakes at compile time. - Fast. Don't force users to worry about the performance impact of instrumentation. Instead encourage users to instrument often and extensively. ## Specification Compliance Below is a list of properties where this client library implementation lags behind the Open Metrics specification. Not being compliant with all requirements (`MUST` and `MUST NOT`) of the specification is considered a bug and likely to be fixed in the future. Contributions in all forms are most welcome. - State set metric. - Enforce "A Histogram MetricPoint MUST contain at least one bucket". - Enforce "A MetricFamily MUST have a [...] UNIT metadata". - Enforce "MetricFamily names [...] MUST be unique within a MetricSet." - Enforce "Names SHOULD be in snake_case". - Enforce "MetricFamily names beginning with underscores are RESERVED and MUST NOT be used unless specified by this standard". - Enforce "Exposers SHOULD avoid names that could be confused with the suffixes that text format sample metric names use". - Gauge histogram metric. - Allow "A MetricPoint in a Metric with the type [Counter, Histogram] SHOULD have a Timestamp value called Created". - Summary metric. ## Related Libraries - [rust-prometheus](https://github.com/tikv/rust-prometheus/): See [tikv/rust-prometheus/#392](https://github.com/tikv/rust-prometheus/issues/392) for a high-level comparison. ## License Licensed under either of * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. #### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. prometheus-client-0.22.2/SECURITY.md000064400000000000000000000002541046102023000151500ustar 00000000000000# Reporting a security issue The Prometheus security policy, including how to report vulnerabilities, can be found here: prometheus-client-0.22.2/benches/baseline.rs000064400000000000000000000011501046102023000171120ustar 00000000000000use criterion::{criterion_group, criterion_main, Criterion}; use prometheus_client::metrics::counter::Counter; use prometheus_client::metrics::family::Family; pub fn baseline(c: &mut Criterion) { c.bench_function("counter", |b| { let counter: Counter = Counter::default(); b.iter(|| { counter.inc(); }) }); c.bench_function("counter via family lookup", |b| { let family = Family::<(), Counter>::default(); b.iter(|| { family.get_or_create(&()).inc(); }) }); } criterion_group!(benches, baseline); criterion_main!(benches); prometheus-client-0.22.2/benches/encoding/proto.rs000064400000000000000000000052531046102023000202710ustar 00000000000000// Benchmark inspired by // https://github.com/tikv/rust-prometheus/blob/ab1ca7285d3463504381a5025ae1951e020d6796/benches/text_encoder.rs:write use criterion::{black_box, criterion_group, criterion_main, Criterion}; use prometheus_client::encoding::protobuf; 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 prometheus_client_derive_encode::{EncodeLabelSet, EncodeLabelValue}; pub fn proto(c: &mut Criterion) { c.bench_function("encode", |b| { #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug)] struct CounterLabels { path: String, method: Method, some_number: u64, } #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelValue, Debug)] enum Method { Get, #[allow(dead_code)] Put, } #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug)] struct HistogramLabels { region: Region, } #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelValue, Debug)] enum Region { Africa, #[allow(dead_code)] Asia, } let mut registry = Registry::default(); for i in 0..100 { let counter_family = Family::::default(); let histogram_family = Family::::new_with_constructor(|| { Histogram::new(exponential_buckets(1.0, 2.0, 10)) }); registry.register( format!("my_counter{}", i), "My counter", counter_family.clone(), ); registry.register( format!("my_histogram{}", i), "My histogram", histogram_family.clone(), ); for j in 0_u32..100 { counter_family .get_or_create(&CounterLabels { path: format!("/path/{}", i), method: Method::Get, some_number: j.into(), }) .inc(); histogram_family .get_or_create(&HistogramLabels { region: Region::Africa, }) .observe(j.into()); } } b.iter(|| { let metric_set = protobuf::encode(®istry).unwrap(); black_box(metric_set); }) }); } criterion_group!(benches, proto); criterion_main!(benches); prometheus-client-0.22.2/benches/encoding/text.rs000064400000000000000000000060541046102023000201120ustar 00000000000000// 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::{self, EncodeLabelSet, EncodeLabelValue, LabelValueEncoder}; 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::Write; pub fn text(c: &mut Criterion) { c.bench_function("encode", |b| { #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug)] struct Labels { method: Method, status: Status, some_number: u64, } #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelValue, Debug)] enum Method { Get, #[allow(dead_code)] Put, } #[derive(Clone, Hash, PartialEq, Eq, Debug)] enum Status { Two, #[allow(dead_code)] Four, #[allow(dead_code)] Five, } impl prometheus_client::encoding::EncodeLabelValue for Status { fn encode(&self, writer: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> { let status = match self { Status::Two => "200", Status::Four => "400", Status::Five => "500", }; writer.write_str(status)?; Ok(()) } } let mut registry = Registry::default(); for i in 0..100 { let counter_family = Family::::default(); let histogram_family = Family::::new_with_constructor(|| { Histogram::new(exponential_buckets(1.0, 2.0, 10)) }); registry.register( format!("my_counter_{}", i), "My counter", counter_family.clone(), ); registry.register( format!("my_histogram_{}", i), "My histogram", histogram_family.clone(), ); for j in 0u32..100 { counter_family .get_or_create(&Labels { method: Method::Get, status: Status::Two, some_number: j.into(), }) .inc(); histogram_family .get_or_create(&Labels { method: Method::Get, status: Status::Two, some_number: j.into(), }) .observe(j.into()); } } let mut buffer = String::new(); b.iter(|| { encoding::text::encode(&mut buffer, ®istry).unwrap(); black_box(&mut buffer); }) }); } criterion_group!(benches, text); criterion_main!(benches); prometheus-client-0.22.2/benches/family.rs000064400000000000000000000043561046102023000166240ustar 00000000000000use criterion::{criterion_group, criterion_main, Criterion}; use prometheus_client::metrics::counter::Counter; use prometheus_client::metrics::family::Family; pub fn family(c: &mut Criterion) { c.bench_function( "counter family with [(&'static str, &'static str)] label set", |b| { let family = Family::<[(&'static str, &'static str); 2], Counter>::default(); b.iter(|| { family .get_or_create(&[("method", "GET"), ("status", "200")]) .inc(); }) }, ); c.bench_function( "counter family with Vec<(&'static str, &'static str)> label set", |b| { let family = Family::, Counter>::default(); b.iter(|| { family .get_or_create(&vec![("method", "GET"), ("status", "200")]) .inc(); }) }, ); c.bench_function("counter family with Vec<(String, String)> label set", |b| { let family = Family::, Counter>::default(); b.iter(|| { family .get_or_create(&vec![ ("method".to_owned(), "GET".to_owned()), ("status".to_owned(), "200".to_owned()), ]) .inc(); }) }); c.bench_function("counter family with custom type label set", |b| { #[derive(Clone, Hash, PartialEq, Eq)] struct Labels { method: Method, status: Status, } #[derive(Clone, Hash, PartialEq, Eq)] enum Method { Get, #[allow(dead_code)] Put, } #[derive(Clone, Hash, PartialEq, Eq)] enum Status { Two, #[allow(dead_code)] Four, #[allow(dead_code)] Five, } let family = Family::::default(); b.iter(|| { family .get_or_create(&Labels { method: Method::Get, status: Status::Two, }) .inc(); }) }); } criterion_group!(benches, family); criterion_main!(benches); prometheus-client-0.22.2/build.rs000064400000000000000000000003501046102023000150210ustar 00000000000000use std::io::Result; fn main() -> Result<()> { #[cfg(feature = "protobuf")] prost_build::compile_protos( &["src/encoding/proto/openmetrics_data_model.proto"], &["src/encoding/proto/"], )?; Ok(()) } prometheus-client-0.22.2/src/collector.rs000064400000000000000000000026761046102023000165140ustar 00000000000000//! Metric collector implementation. //! //! See [`Collector`] for details. use crate::encoding::DescriptorEncoder; /// The [`Collector`] abstraction allows users to provide additional metrics and /// their description on each scrape. /// /// An example use-case is an exporter that retrieves a set of operating system metrics /// ad-hoc on each scrape. /// /// Register a [`Collector`] with a [`Registry`](crate::registry::Registry) via /// [`Registry::register_collector`](crate::registry::Registry::register_collector). /// /// ``` /// # use prometheus_client::metrics::counter::ConstCounter; /// # use prometheus_client::collector::Collector; /// # use prometheus_client::encoding::{DescriptorEncoder, EncodeMetric}; /// # /// #[derive(Debug)] /// struct MyCollector {} /// /// impl Collector for MyCollector { /// fn encode(&self, mut encoder: DescriptorEncoder) -> Result<(), std::fmt::Error> { /// let counter = ConstCounter::new(42); /// let metric_encoder = encoder.encode_descriptor( /// "my_counter", /// "some help", /// None, /// counter.metric_type(), /// )?; /// counter.encode(metric_encoder)?; /// Ok(()) /// } /// } /// ``` pub trait Collector: std::fmt::Debug + Send + Sync + 'static { /// Once the [`Collector`] is registered, this method is called on each scrape. fn encode(&self, encoder: DescriptorEncoder) -> Result<(), std::fmt::Error>; } prometheus-client-0.22.2/src/encoding/proto/openmetrics_data_model.proto000064400000000000000000000106221046102023000246650ustar 00000000000000syntax = "proto3"; // The OpenMetrics protobuf schema which defines the protobuf wire format. // Ensure to interpret "required" as semantically required for a valid message. // All string fields MUST be UTF-8 encoded strings. package openmetrics; import "google/protobuf/timestamp.proto"; // The top-level container type that is encoded and sent over the wire. message MetricSet { // Each MetricFamily has one or more MetricPoints for a single Metric. repeated MetricFamily metric_families = 1; } // One or more Metrics for a single MetricFamily, where each Metric // has one or more MetricPoints. message MetricFamily { // Required. string name = 1; // Optional. MetricType type = 2; // Optional. string unit = 3; // Optional. string help = 4; // Optional. repeated Metric metrics = 5; } // The type of a Metric. enum MetricType { // Unknown must use unknown MetricPoint values. UNKNOWN = 0; // Gauge must use gauge MetricPoint values. GAUGE = 1; // Counter must use counter MetricPoint values. COUNTER = 2; // State set must use state set MetricPoint values. STATE_SET = 3; // Info must use info MetricPoint values. INFO = 4; // Histogram must use histogram value MetricPoint values. HISTOGRAM = 5; // Gauge histogram must use histogram value MetricPoint values. GAUGE_HISTOGRAM = 6; // Summary quantiles must use summary value MetricPoint values. SUMMARY = 7; } // A single metric with a unique set of labels within a metric family. message Metric { // Optional. repeated Label labels = 1; // Optional. repeated MetricPoint metric_points = 2; } // A name-value pair. These are used in multiple places: identifying // timeseries, value of INFO metrics, and exemplars in Histograms. message Label { // Required. string name = 1; // Required. string value = 2; } // A MetricPoint in a Metric. message MetricPoint { // Required. oneof value { UnknownValue unknown_value = 1; GaugeValue gauge_value = 2; CounterValue counter_value = 3; HistogramValue histogram_value = 4; StateSetValue state_set_value = 5; InfoValue info_value = 6; SummaryValue summary_value = 7; } // Optional. google.protobuf.Timestamp timestamp = 8; } // Value for UNKNOWN MetricPoint. message UnknownValue { // Required. oneof value { double double_value = 1; int64 int_value = 2; } } // Value for GAUGE MetricPoint. message GaugeValue { // Required. oneof value { double double_value = 1; int64 int_value = 2; } } // Value for COUNTER MetricPoint. message CounterValue { // Required. oneof total { double double_value = 1; uint64 int_value = 2; } // The time values began being collected for this counter. // Optional. google.protobuf.Timestamp created = 3; // Optional. Exemplar exemplar = 4; } // Value for HISTOGRAM or GAUGE_HISTOGRAM MetricPoint. message HistogramValue { // Optional. oneof sum { double double_value = 1; int64 int_value = 2; } // Optional. uint64 count = 3; // The time values began being collected for this histogram. // Optional. google.protobuf.Timestamp created = 4; // Optional. repeated Bucket buckets = 5; // Bucket is the number of values for a bucket in the histogram // with an optional exemplar. message Bucket { // Required. uint64 count = 1; // Optional. double upper_bound = 2; // Optional. Exemplar exemplar = 3; } } message Exemplar { // Required. double value = 1; // Optional. google.protobuf.Timestamp timestamp = 2; // Labels are additional information about the exemplar value (e.g. trace id). // Optional. repeated Label label = 3; } // Value for STATE_SET MetricPoint. message StateSetValue { // Optional. repeated State states = 1; message State { // Required. bool enabled = 1; // Required. string name = 2; } } // Value for INFO MetricPoint. message InfoValue { // Optional. repeated Label info = 1; } // Value for SUMMARY MetricPoint. message SummaryValue { // Optional. oneof sum { double double_value = 1; int64 int_value = 2; } // Optional. uint64 count = 3; // The time sum and count values began being collected for this summary. // Optional. google.protobuf.Timestamp created = 4; // Optional. repeated Quantile quantile = 5; message Quantile { // Required. double quantile = 1; // Required. double value = 2; } } prometheus-client-0.22.2/src/encoding/protobuf.rs000064400000000000000000000740341046102023000201510ustar 00000000000000//! Open Metrics protobuf implementation. //! //! ``` //! # use prometheus_client::encoding::protobuf::encode; //! # use prometheus_client::metrics::counter::Counter; //! # use prometheus_client::registry::Registry; //! # //! # // Create registry and counter and register the latter with the former. //! # let mut registry = Registry::default(); //! # let counter: Counter = Counter::default(); //! # registry.register( //! # "my_counter", //! # "This is my counter", //! # counter.clone(), //! # ); //! # counter.inc(); //! // Returns `MetricSet`, the top-level container type. Please refer to [openmetrics_data_model.proto](https://github.com/OpenObservability/OpenMetrics/blob/main/proto/openmetrics_data_model.proto) for details. //! let metric_set = encode(®istry).unwrap(); //! //! let family = metric_set.metric_families.first().unwrap(); //! assert_eq!("my_counter", family.name); //! assert_eq!("This is my counter.", family.help); //! ``` // Allowing some lints here as the `openmetrics.rs` is an automatically generated file. #[allow(missing_docs, clippy::derive_partial_eq_without_eq)] /// Data models that are automatically generated from OpenMetrics protobuf /// format. pub mod openmetrics_data_model { include!(concat!(env!("OUT_DIR"), "/openmetrics.rs")); } use std::{borrow::Cow, collections::HashMap}; use crate::metrics::MetricType; use crate::registry::{Registry, Unit}; use crate::{metrics::exemplar::Exemplar, registry::Prefix}; use super::{EncodeCounterValue, EncodeExemplarValue, EncodeGaugeValue, EncodeLabelSet}; /// Encode the metrics registered with the provided [`Registry`] into MetricSet /// using the OpenMetrics protobuf format. pub fn encode(registry: &Registry) -> Result { let mut metric_set = openmetrics_data_model::MetricSet::default(); let mut descriptor_encoder = DescriptorEncoder::new(&mut metric_set.metric_families).into(); registry.encode(&mut descriptor_encoder)?; Ok(metric_set) } impl From for openmetrics_data_model::MetricType { fn from(m: MetricType) -> Self { match m { MetricType::Counter => openmetrics_data_model::MetricType::Counter, MetricType::Gauge => openmetrics_data_model::MetricType::Gauge, MetricType::Histogram => openmetrics_data_model::MetricType::Histogram, MetricType::Info => openmetrics_data_model::MetricType::Info, MetricType::Unknown => openmetrics_data_model::MetricType::Unknown, } } } /// Metric Descriptor encoder for protobuf encoding. /// /// This is an inner type for [`super::DescriptorEncoder`]. #[derive(Debug)] pub(crate) struct DescriptorEncoder<'a> { metric_families: &'a mut Vec, prefix: Option<&'a Prefix>, labels: &'a [(Cow<'static, str>, Cow<'static, str>)], } impl DescriptorEncoder<'_> { pub(crate) fn new( metric_families: &mut Vec, ) -> DescriptorEncoder { DescriptorEncoder { metric_families, prefix: Default::default(), labels: Default::default(), } } pub(crate) fn with_prefix_and_labels<'s>( &'s mut self, prefix: Option<&'s Prefix>, labels: &'s [(Cow<'static, str>, Cow<'static, str>)], ) -> DescriptorEncoder<'s> { DescriptorEncoder { prefix, labels, metric_families: self.metric_families, } } pub fn encode_descriptor<'s>( &'s mut self, name: &str, help: &str, unit: Option<&Unit>, metric_type: MetricType, ) -> Result, std::fmt::Error> { let family = openmetrics_data_model::MetricFamily { name: { match self.prefix { Some(prefix) => prefix.as_str().to_string() + "_" + name, None => name.to_string(), } }, r#type: { let metric_type: openmetrics_data_model::MetricType = metric_type.into(); metric_type as i32 }, unit: if let Some(unit) = unit { unit.as_str().to_string() } else { String::new() }, help: help.to_string(), ..Default::default() }; let mut labels = vec![]; self.labels.encode( LabelSetEncoder { labels: &mut labels, } .into(), )?; self.metric_families.push(family); Ok(MetricEncoder { family: &mut self .metric_families .last_mut() .expect("previous push") .metrics, metric_type, labels, }) } } /// Encoder for protobuf encoding. /// /// This is an inner type for [`super::MetricEncoder`]. #[derive(Debug)] pub(crate) struct MetricEncoder<'f> { /// OpenMetrics metric type of the metric. metric_type: MetricType, /// Vector of OpenMetrics metrics to which encoded metrics are added. family: &'f mut Vec, /// Labels to be added to each metric. labels: Vec, } impl MetricEncoder<'_> { pub fn encode_counter< S: EncodeLabelSet, CounterValue: EncodeCounterValue, ExemplarValue: EncodeExemplarValue, >( &mut self, v: &CounterValue, exemplar: Option<&Exemplar>, ) -> Result<(), std::fmt::Error> { let mut value = openmetrics_data_model::counter_value::Total::IntValue(0); let mut e = CounterValueEncoder { value: &mut value }.into(); v.encode(&mut e)?; self.family.push(openmetrics_data_model::Metric { labels: self.labels.clone(), metric_points: vec![openmetrics_data_model::MetricPoint { value: Some(openmetrics_data_model::metric_point::Value::CounterValue( openmetrics_data_model::CounterValue { total: Some(value), exemplar: exemplar.map(|e| e.try_into()).transpose()?, ..Default::default() }, )), ..Default::default() }], }); Ok(()) } pub fn encode_gauge( &mut self, v: &GaugeValue, ) -> Result<(), std::fmt::Error> { let mut value = openmetrics_data_model::gauge_value::Value::IntValue(0); let mut e = GaugeValueEncoder { value: &mut value }.into(); v.encode(&mut e)?; self.family.push(openmetrics_data_model::Metric { labels: self.labels.clone(), metric_points: vec![openmetrics_data_model::MetricPoint { value: Some(openmetrics_data_model::metric_point::Value::GaugeValue( openmetrics_data_model::GaugeValue { value: Some(value) }, )), ..Default::default() }], }); Ok(()) } pub fn encode_info( &mut self, label_set: &impl super::EncodeLabelSet, ) -> Result<(), std::fmt::Error> { let mut info_labels = vec![]; label_set.encode( LabelSetEncoder { labels: &mut info_labels, } .into(), )?; self.family.push(openmetrics_data_model::Metric { labels: self.labels.clone(), metric_points: vec![openmetrics_data_model::MetricPoint { value: Some(openmetrics_data_model::metric_point::Value::InfoValue( openmetrics_data_model::InfoValue { info: info_labels }, )), ..Default::default() }], }); Ok(()) } pub fn encode_family( &mut self, label_set: &S, ) -> Result { let mut labels = self.labels.clone(); label_set.encode( LabelSetEncoder { labels: &mut labels, } .into(), )?; Ok(MetricEncoder { metric_type: self.metric_type, family: self.family, labels, }) } pub fn encode_histogram( &mut self, sum: f64, count: u64, buckets: &[(f64, u64)], exemplars: Option<&HashMap>>, ) -> Result<(), std::fmt::Error> { let buckets = buckets .iter() .enumerate() .map(|(i, (upper_bound, count))| { Ok(openmetrics_data_model::histogram_value::Bucket { upper_bound: *upper_bound, count: *count, exemplar: exemplars .and_then(|exemplars| exemplars.get(&i).map(|exemplar| exemplar.try_into())) .transpose()?, }) }) .collect::, std::fmt::Error>>()?; self.family.push(openmetrics_data_model::Metric { labels: self.labels.clone(), metric_points: vec![openmetrics_data_model::MetricPoint { value: Some(openmetrics_data_model::metric_point::Value::HistogramValue( openmetrics_data_model::HistogramValue { count, created: None, buckets, sum: Some(openmetrics_data_model::histogram_value::Sum::DoubleValue( sum, )), }, )), ..Default::default() }], }); Ok(()) } } impl TryFrom<&Exemplar> for openmetrics_data_model::Exemplar { type Error = std::fmt::Error; fn try_from(exemplar: &Exemplar) -> Result { let mut value = f64::default(); exemplar .value .encode(ExemplarValueEncoder { value: &mut value }.into())?; let mut labels = vec![]; exemplar.label_set.encode( LabelSetEncoder { labels: &mut labels, } .into(), )?; Ok(openmetrics_data_model::Exemplar { value, timestamp: Default::default(), label: labels, }) } } #[derive(Debug)] pub(crate) struct GaugeValueEncoder<'a> { value: &'a mut openmetrics_data_model::gauge_value::Value, } impl<'a> GaugeValueEncoder<'a> { pub fn encode_u32(&mut self, v: u32) -> Result<(), std::fmt::Error> { self.encode_i64(v as i64) } pub fn encode_i64(&mut self, v: i64) -> Result<(), std::fmt::Error> { *self.value = openmetrics_data_model::gauge_value::Value::IntValue(v); Ok(()) } pub fn encode_f64(&mut self, v: f64) -> Result<(), std::fmt::Error> { *self.value = openmetrics_data_model::gauge_value::Value::DoubleValue(v); Ok(()) } } #[derive(Debug)] pub(crate) struct ExemplarValueEncoder<'a> { value: &'a mut f64, } impl<'a> ExemplarValueEncoder<'a> { pub fn encode(&mut self, v: f64) -> Result<(), std::fmt::Error> { *self.value = v; Ok(()) } } impl From<&(K, V)> for openmetrics_data_model::Label { fn from(kv: &(K, V)) -> Self { openmetrics_data_model::Label { name: kv.0.to_string(), value: kv.1.to_string(), } } } #[derive(Debug)] pub(crate) struct CounterValueEncoder<'a> { value: &'a mut openmetrics_data_model::counter_value::Total, } impl<'a> CounterValueEncoder<'a> { pub fn encode_f64(&mut self, v: f64) -> Result<(), std::fmt::Error> { *self.value = openmetrics_data_model::counter_value::Total::DoubleValue(v); Ok(()) } pub fn encode_u64(&mut self, v: u64) -> Result<(), std::fmt::Error> { *self.value = openmetrics_data_model::counter_value::Total::IntValue(v); Ok(()) } } #[derive(Debug)] pub(crate) struct LabelSetEncoder<'a> { labels: &'a mut Vec, } impl<'a> LabelSetEncoder<'a> { pub fn encode_label(&mut self) -> LabelEncoder { LabelEncoder { labels: self.labels, } } } #[derive(Debug)] pub(crate) struct LabelEncoder<'a> { labels: &'a mut Vec, } impl<'a> LabelEncoder<'a> { pub fn encode_label_key(&mut self) -> Result { self.labels.push(openmetrics_data_model::Label::default()); Ok(LabelKeyEncoder { label: self.labels.last_mut().expect("To find pushed label."), }) } } #[derive(Debug)] pub(crate) struct LabelKeyEncoder<'a> { label: &'a mut openmetrics_data_model::Label, } impl<'a> std::fmt::Write for LabelKeyEncoder<'a> { fn write_str(&mut self, s: &str) -> std::fmt::Result { self.label.name.write_str(s) } } impl<'a> LabelKeyEncoder<'a> { pub fn encode_label_value(self) -> Result, std::fmt::Error> { Ok(LabelValueEncoder { label_value: &mut self.label.value, }) } } #[derive(Debug)] pub(crate) struct LabelValueEncoder<'a> { label_value: &'a mut String, } impl<'a> LabelValueEncoder<'a> { pub fn finish(self) -> Result<(), std::fmt::Error> { Ok(()) } } impl<'a> std::fmt::Write for LabelValueEncoder<'a> { fn write_str(&mut self, s: &str) -> std::fmt::Result { self.label_value.write_str(s) } } #[cfg(test)] mod tests { use super::*; use crate::metrics::counter::Counter; use crate::metrics::exemplar::{CounterWithExemplar, HistogramWithExemplars}; use crate::metrics::family::Family; use crate::metrics::gauge::Gauge; use crate::metrics::histogram::{exponential_buckets, Histogram}; use crate::metrics::info::Info; use crate::registry::Unit; use std::borrow::Cow; use std::collections::HashSet; use std::sync::atomic::AtomicI64; #[test] fn encode_counter_int() { let counter: Counter = Counter::default(); let mut registry = Registry::default(); registry.register("my_counter", "My counter", counter.clone()); counter.inc(); let metric_set = encode(®istry).unwrap(); let family = metric_set.metric_families.first().unwrap(); assert_eq!("my_counter", family.name); assert_eq!("My counter.", family.help); assert_eq!( openmetrics_data_model::MetricType::Counter as i32, extract_metric_type(&metric_set) ); match extract_metric_point_value(&metric_set) { openmetrics_data_model::metric_point::Value::CounterValue(value) => { let expected = openmetrics_data_model::counter_value::Total::IntValue(1); assert_eq!(Some(expected), value.total); assert_eq!(None, value.exemplar); assert_eq!(None, value.created); } _ => panic!("wrong value type"), } } #[test] fn encode_counter_double() { // Using `f64` let counter: Counter = Counter::default(); let mut registry = Registry::default(); registry.register("my_counter", "My counter", counter.clone()); counter.inc(); let metric_set = encode(®istry).unwrap(); let family = metric_set.metric_families.first().unwrap(); assert_eq!("my_counter", family.name); assert_eq!("My counter.", family.help); assert_eq!( openmetrics_data_model::MetricType::Counter as i32, extract_metric_type(&metric_set) ); match extract_metric_point_value(&metric_set) { openmetrics_data_model::metric_point::Value::CounterValue(value) => { // The counter should be encoded as `DoubleValue` let expected = openmetrics_data_model::counter_value::Total::DoubleValue(1.0); assert_eq!(Some(expected), value.total); assert_eq!(None, value.exemplar); assert_eq!(None, value.created); } _ => panic!("wrong value type"), } } #[test] fn encode_counter_with_unit() { let mut registry = Registry::default(); let counter: Counter = Counter::default(); registry.register_with_unit("my_counter", "My counter", Unit::Seconds, counter); let metric_set = encode(®istry).unwrap(); let family = metric_set.metric_families.first().unwrap(); assert_eq!("my_counter", family.name); assert_eq!("My counter.", family.help); assert_eq!("seconds", family.unit); } #[test] fn encode_counter_with_exemplar() { let mut registry = Registry::default(); let counter_with_exemplar: CounterWithExemplar, f64> = CounterWithExemplar::default(); registry.register( "my_counter_with_exemplar", "My counter with exemplar", counter_with_exemplar.clone(), ); counter_with_exemplar.inc_by(1.0, Some(vec![("user_id".to_string(), 42.0)])); let metric_set = encode(®istry).unwrap(); let family = metric_set.metric_families.first().unwrap(); assert_eq!("my_counter_with_exemplar", family.name); assert_eq!("My counter with exemplar.", family.help); assert_eq!( openmetrics_data_model::MetricType::Counter as i32, extract_metric_type(&metric_set) ); match extract_metric_point_value(&metric_set) { openmetrics_data_model::metric_point::Value::CounterValue(value) => { // The counter should be encoded as `DoubleValue` let expected = openmetrics_data_model::counter_value::Total::DoubleValue(1.0); assert_eq!(Some(expected), value.total); let exemplar = value.exemplar.as_ref().unwrap(); assert_eq!(1.0, exemplar.value); let expected_label = { openmetrics_data_model::Label { name: "user_id".to_string(), value: "42.0".to_string(), } }; assert_eq!(vec![expected_label], exemplar.label); } _ => panic!("wrong value type"), } } #[test] fn encode_gauge() { let mut registry = Registry::default(); let gauge = Gauge::::default(); registry.register("my_gauge", "My gauge", gauge.clone()); gauge.inc(); let metric_set = encode(®istry).unwrap(); let family = metric_set.metric_families.first().unwrap(); assert_eq!("my_gauge", family.name); assert_eq!("My gauge.", family.help); assert_eq!( openmetrics_data_model::MetricType::Gauge as i32, extract_metric_type(&metric_set) ); match extract_metric_point_value(&metric_set) { openmetrics_data_model::metric_point::Value::GaugeValue(value) => { let expected = openmetrics_data_model::gauge_value::Value::IntValue(1); assert_eq!(Some(expected), value.value); } _ => panic!("wrong value type"), } } #[test] fn encode_counter_family() { let mut registry = Registry::default(); let family = Family::, Counter>::default(); registry.register("my_counter_family", "My counter family", family.clone()); family .get_or_create(&vec![ ("method".to_string(), "GET".to_string()), ("status".to_string(), "200".to_string()), ]) .inc(); family .get_or_create(&vec![ ("method".to_string(), "POST".to_string()), ("status".to_string(), "200".to_string()), ]) .inc(); let metric_set = encode(®istry).unwrap(); let family = metric_set.metric_families.first().unwrap(); assert_eq!("my_counter_family", family.name); assert_eq!("My counter family.", family.help); assert_eq!( openmetrics_data_model::MetricType::Counter as i32, extract_metric_type(&metric_set) ); // The order of the labels is not deterministic so we are testing the // value to be either let mut potential_method_value = HashSet::new(); potential_method_value.insert("GET"); potential_method_value.insert("POST"); // the first metric let metric = family.metrics.first().unwrap(); assert_eq!(2, metric.labels.len()); assert_eq!("method", metric.labels[0].name); assert!(potential_method_value.remove(&metric.labels[0].value.as_str())); assert_eq!("status", metric.labels[1].name); assert_eq!("200", metric.labels[1].value); match extract_metric_point_value(&metric_set) { openmetrics_data_model::metric_point::Value::CounterValue(value) => { let expected = openmetrics_data_model::counter_value::Total::IntValue(1); assert_eq!(Some(expected), value.total); assert_eq!(None, value.exemplar); assert_eq!(None, value.created); } _ => panic!("wrong value type"), } // the second metric let metric2 = &family.metrics[1]; assert_eq!(2, metric2.labels.len()); assert_eq!("method", metric2.labels[0].name); assert!(potential_method_value.remove(&metric2.labels[0].value.as_str())); assert_eq!("status", metric2.labels[1].name); assert_eq!("200", metric2.labels[1].value); } #[test] fn encode_counter_family_with_prefix_with_label() { let mut registry = Registry::default(); let sub_registry = registry.sub_registry_with_prefix("my_prefix"); let sub_sub_registry = sub_registry .sub_registry_with_label((Cow::Borrowed("my_key"), Cow::Borrowed("my_value"))); let family = Family::, Counter>::default(); sub_sub_registry.register("my_counter_family", "My counter family", family.clone()); family .get_or_create(&vec![ ("method".to_string(), "GET".to_string()), ("status".to_string(), "200".to_string()), ]) .inc(); let metric_set = encode(®istry).unwrap(); let family = metric_set.metric_families.first().unwrap(); assert_eq!("my_prefix_my_counter_family", family.name); assert_eq!("My counter family.", family.help); assert_eq!( openmetrics_data_model::MetricType::Counter as i32, extract_metric_type(&metric_set) ); let metric = family.metrics.first().unwrap(); assert_eq!(3, metric.labels.len()); assert_eq!("my_key", metric.labels[0].name); assert_eq!("my_value", metric.labels[0].value); assert_eq!("method", metric.labels[1].name); assert_eq!("GET", metric.labels[1].value); assert_eq!("status", metric.labels[2].name); assert_eq!("200", metric.labels[2].value); match extract_metric_point_value(&metric_set) { openmetrics_data_model::metric_point::Value::CounterValue(value) => { let expected = openmetrics_data_model::counter_value::Total::IntValue(1); assert_eq!(Some(expected), value.total); assert_eq!(None, value.exemplar); assert_eq!(None, value.created); } _ => panic!("wrong value type"), } } #[test] fn encode_histogram() { let mut registry = Registry::default(); let histogram = Histogram::new(exponential_buckets(1.0, 2.0, 10)); registry.register("my_histogram", "My histogram", histogram.clone()); histogram.observe(1.0); let metric_set = encode(®istry).unwrap(); let family = metric_set.metric_families.first().unwrap(); assert_eq!("my_histogram", family.name); assert_eq!("My histogram.", family.help); assert_eq!( openmetrics_data_model::MetricType::Histogram as i32, extract_metric_type(&metric_set) ); match extract_metric_point_value(&metric_set) { openmetrics_data_model::metric_point::Value::HistogramValue(value) => { assert_eq!( Some(openmetrics_data_model::histogram_value::Sum::DoubleValue( 1.0 )), value.sum ); assert_eq!(1, value.count); assert_eq!(11, value.buckets.len()); } _ => panic!("wrong value type"), } } #[test] fn encode_histogram_with_exemplars() { let mut registry = Registry::default(); let histogram = HistogramWithExemplars::new(exponential_buckets(1.0, 2.0, 10)); registry.register("my_histogram", "My histogram", histogram.clone()); histogram.observe(1.0, Some(vec![("user_id".to_string(), 42u64)])); let metric_set = encode(®istry).unwrap(); let family = metric_set.metric_families.first().unwrap(); assert_eq!("my_histogram", family.name); assert_eq!("My histogram.", family.help); assert_eq!( openmetrics_data_model::MetricType::Histogram as i32, extract_metric_type(&metric_set) ); match extract_metric_point_value(&metric_set) { openmetrics_data_model::metric_point::Value::HistogramValue(value) => { let exemplar = value.buckets.first().unwrap().exemplar.as_ref().unwrap(); assert_eq!(1.0, exemplar.value); let expected_label = { openmetrics_data_model::Label { name: "user_id".to_string(), value: "42".to_string(), } }; assert_eq!(vec![expected_label], exemplar.label); } _ => panic!("wrong value type"), } } #[test] fn encode_family_counter_histogram() { let mut registry = Registry::default(); let counter_family = Family::, Counter>::default(); let histogram_family = Family::, Histogram>::new_with_constructor(|| { Histogram::new(exponential_buckets(1.0, 2.0, 10)) }); registry.register("my_counter", "My counter", counter_family.clone()); registry.register("my_histogram", "My histogram", histogram_family.clone()); counter_family .get_or_create(&vec![("path".to_string(), "/".to_string())]) .inc(); histogram_family .get_or_create(&vec![("path".to_string(), "/".to_string())]) .observe(1.0); let metric_set = encode(®istry).unwrap(); assert_eq!("my_counter", metric_set.metric_families[0].name); assert_eq!("my_histogram", metric_set.metric_families[1].name); } #[test] fn encode_family_and_counter_and_histogram() { let mut registry = Registry::default(); // Family let counter_family = Family::, Counter>::default(); let histogram_family = Family::, Histogram>::new_with_constructor(|| { Histogram::new(exponential_buckets(1.0, 2.0, 10)) }); registry.register("my_family_counter", "My counter", counter_family.clone()); registry.register( "my_family_histogram", "My histogram", histogram_family.clone(), ); counter_family .get_or_create(&vec![("path".to_string(), "/".to_string())]) .inc(); histogram_family .get_or_create(&vec![("path".to_string(), "/".to_string())]) .observe(1.0); // Counter let counter: Counter = Counter::default(); registry.register("my_counter", "My counter", counter.clone()); counter.inc(); // Histogram let histogram = Histogram::new(exponential_buckets(1.0, 2.0, 10)); registry.register("my_histogram", "My histogram", histogram.clone()); histogram.observe(1.0); let metric_set = encode(®istry).unwrap(); assert_eq!("my_family_counter", metric_set.metric_families[0].name); assert_eq!("my_family_histogram", metric_set.metric_families[1].name); } #[test] fn encode_info() { let mut registry = Registry::default(); let info = Info::new(vec![("os".to_string(), "GNU/linux".to_string())]); registry.register("my_info_metric", "My info metric", info); let metric_set = encode(®istry).unwrap(); let family = metric_set.metric_families.first().unwrap(); assert_eq!("my_info_metric", family.name); assert_eq!("My info metric.", family.help); assert_eq!( openmetrics_data_model::MetricType::Info as i32, extract_metric_type(&metric_set) ); match extract_metric_point_value(&metric_set) { openmetrics_data_model::metric_point::Value::InfoValue(value) => { assert_eq!(1, value.info.len()); let info = value.info.first().unwrap(); assert_eq!("os", info.name); assert_eq!("GNU/linux", info.value); } _ => panic!("wrong value type"), } } fn extract_metric_type(metric_set: &openmetrics_data_model::MetricSet) -> i32 { let family = metric_set.metric_families.first().unwrap(); family.r#type } fn extract_metric_point_value( metric_set: &openmetrics_data_model::MetricSet, ) -> openmetrics_data_model::metric_point::Value { let metric = metric_set .metric_families .first() .unwrap() .metrics .first() .unwrap(); metric .metric_points .first() .unwrap() .value .as_ref() .unwrap() .clone() } } prometheus-client-0.22.2/src/encoding/text.rs000064400000000000000000000741121046102023000172720ustar 00000000000000//! Open Metrics text format implementation. //! //! ``` //! # use prometheus_client::encoding::text::encode; //! # use prometheus_client::metrics::counter::Counter; //! # use prometheus_client::registry::Registry; //! # //! # // Create registry and counter and register the latter with the former. //! # let mut registry = Registry::default(); //! # let counter: Counter = Counter::default(); //! # registry.register( //! # "my_counter", //! # "This is my counter", //! # counter.clone(), //! # ); //! # counter.inc(); //! let mut buffer = String::new(); //! encode(&mut buffer, ®istry).unwrap(); //! //! let expected = "# HELP my_counter This is my counter.\n".to_owned() + //! "# TYPE my_counter counter\n" + //! "my_counter_total 1\n" + //! "# EOF\n"; //! assert_eq!(expected, buffer); //! ``` use crate::encoding::{EncodeExemplarValue, EncodeLabelSet}; use crate::metrics::exemplar::Exemplar; use crate::metrics::MetricType; use crate::registry::{Prefix, Registry, Unit}; use std::borrow::Cow; use std::collections::HashMap; use std::fmt::Write; /// Encode the metrics registered with the provided [`Registry`] into the /// provided [`Write`]r using the OpenMetrics text format. pub fn encode(writer: &mut W, registry: &Registry) -> Result<(), std::fmt::Error> where W: Write, { registry.encode(&mut DescriptorEncoder::new(writer).into())?; writer.write_str("# EOF\n")?; Ok(()) } pub(crate) struct DescriptorEncoder<'a> { writer: &'a mut dyn Write, prefix: Option<&'a Prefix>, labels: &'a [(Cow<'static, str>, Cow<'static, str>)], } impl<'a> std::fmt::Debug for DescriptorEncoder<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("DescriptorEncoder").finish() } } impl DescriptorEncoder<'_> { pub(crate) fn new(writer: &mut dyn Write) -> DescriptorEncoder { DescriptorEncoder { writer, prefix: Default::default(), labels: Default::default(), } } pub(crate) fn with_prefix_and_labels<'s>( &'s mut self, prefix: Option<&'s Prefix>, labels: &'s [(Cow<'static, str>, Cow<'static, str>)], ) -> DescriptorEncoder<'s> { DescriptorEncoder { prefix, labels, writer: self.writer, } } pub fn encode_descriptor<'s>( &'s mut self, name: &'s str, help: &str, unit: Option<&'s Unit>, metric_type: MetricType, ) -> Result, std::fmt::Error> { self.writer.write_str("# HELP ")?; if let Some(prefix) = self.prefix { self.writer.write_str(prefix.as_str())?; self.writer.write_str("_")?; } self.writer.write_str(name)?; if let Some(unit) = unit { self.writer.write_str("_")?; self.writer.write_str(unit.as_str())?; } self.writer.write_str(" ")?; self.writer.write_str(help)?; self.writer.write_str("\n")?; self.writer.write_str("# TYPE ")?; if let Some(prefix) = self.prefix { self.writer.write_str(prefix.as_str())?; self.writer.write_str("_")?; } self.writer.write_str(name)?; if let Some(unit) = unit { self.writer.write_str("_")?; self.writer.write_str(unit.as_str())?; } self.writer.write_str(" ")?; self.writer.write_str(metric_type.as_str())?; self.writer.write_str("\n")?; if let Some(unit) = unit { self.writer.write_str("# UNIT ")?; if let Some(prefix) = self.prefix { self.writer.write_str(prefix.as_str())?; self.writer.write_str("_")?; } self.writer.write_str(name)?; self.writer.write_str("_")?; self.writer.write_str(unit.as_str())?; self.writer.write_str(" ")?; self.writer.write_str(unit.as_str())?; self.writer.write_str("\n")?; } Ok(MetricEncoder { writer: self.writer, prefix: self.prefix, name, unit, const_labels: self.labels, family_labels: None, }) } } /// Helper type for [`EncodeMetric`](super::EncodeMetric), see /// [`EncodeMetric::encode`](super::EncodeMetric::encode). /// // `MetricEncoder` does not take a trait parameter for `writer` and `labels` // because `EncodeMetric` which uses `MetricEncoder` needs to be usable as a // trait object in order to be able to register different metric types with a // `Registry`. Trait objects can not use type parameters. // // TODO: Alternative solutions to the above are very much appreciated. pub(crate) struct MetricEncoder<'a> { writer: &'a mut dyn Write, prefix: Option<&'a Prefix>, name: &'a str, unit: Option<&'a Unit>, const_labels: &'a [(Cow<'static, str>, Cow<'static, str>)], family_labels: Option<&'a dyn super::EncodeLabelSet>, } impl<'a> std::fmt::Debug for MetricEncoder<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut labels = String::new(); if let Some(l) = self.family_labels { l.encode(LabelSetEncoder::new(&mut labels).into())?; } f.debug_struct("Encoder") .field("name", &self.name) .field("prefix", &self.prefix) .field("unit", &self.unit) .field("const_labels", &self.const_labels) .field("labels", &labels.as_str()) .finish() } } impl<'a> MetricEncoder<'a> { pub fn encode_counter< S: EncodeLabelSet, CounterValue: super::EncodeCounterValue, ExemplarValue: EncodeExemplarValue, >( &mut self, v: &CounterValue, exemplar: Option<&Exemplar>, ) -> Result<(), std::fmt::Error> { self.write_prefix_name_unit()?; self.write_suffix("total")?; self.encode_labels::<()>(None)?; v.encode( &mut CounterValueEncoder { writer: self.writer, } .into(), )?; if let Some(exemplar) = exemplar { self.encode_exemplar(exemplar)?; } self.newline()?; Ok(()) } pub fn encode_gauge( &mut self, v: &GaugeValue, ) -> Result<(), std::fmt::Error> { self.write_prefix_name_unit()?; self.encode_labels::<()>(None)?; v.encode( &mut GaugeValueEncoder { writer: self.writer, } .into(), )?; self.newline()?; Ok(()) } pub fn encode_info(&mut self, label_set: &S) -> Result<(), std::fmt::Error> { self.write_prefix_name_unit()?; self.write_suffix("info")?; self.encode_labels(Some(label_set))?; self.writer.write_str(" ")?; self.writer.write_str(itoa::Buffer::new().format(1))?; self.newline()?; Ok(()) } /// Encode a set of labels. Used by wrapper metric types like /// [`Family`](crate::metrics::family::Family). pub fn encode_family<'s, S: EncodeLabelSet>( &'s mut self, label_set: &'s S, ) -> Result, std::fmt::Error> { debug_assert!(self.family_labels.is_none()); Ok(MetricEncoder { writer: self.writer, prefix: self.prefix, name: self.name, unit: self.unit, const_labels: self.const_labels, family_labels: Some(label_set), }) } pub fn encode_histogram( &mut self, sum: f64, count: u64, buckets: &[(f64, u64)], exemplars: Option<&HashMap>>, ) -> Result<(), std::fmt::Error> { self.write_prefix_name_unit()?; self.write_suffix("sum")?; self.encode_labels::<()>(None)?; self.writer.write_str(" ")?; self.writer.write_str(dtoa::Buffer::new().format(sum))?; self.newline()?; self.write_prefix_name_unit()?; self.write_suffix("count")?; self.encode_labels::<()>(None)?; self.writer.write_str(" ")?; self.writer.write_str(itoa::Buffer::new().format(count))?; self.newline()?; let mut cummulative = 0; for (i, (upper_bound, count)) in buckets.iter().enumerate() { cummulative += count; self.write_prefix_name_unit()?; self.write_suffix("bucket")?; if *upper_bound == f64::MAX { self.encode_labels(Some(&[("le", "+Inf")]))?; } else { self.encode_labels(Some(&[("le", *upper_bound)]))?; } self.writer.write_str(" ")?; self.writer .write_str(itoa::Buffer::new().format(cummulative))?; if let Some(exemplar) = exemplars.and_then(|e| e.get(&i)) { self.encode_exemplar(exemplar)? } self.newline()?; } Ok(()) } /// Encode an exemplar for the given metric. fn encode_exemplar( &mut self, exemplar: &Exemplar, ) -> Result<(), std::fmt::Error> { self.writer.write_str(" # {")?; exemplar .label_set .encode(LabelSetEncoder::new(self.writer).into())?; self.writer.write_str("} ")?; exemplar.value.encode( ExemplarValueEncoder { writer: self.writer, } .into(), )?; Ok(()) } fn newline(&mut self) -> Result<(), std::fmt::Error> { self.writer.write_str("\n") } fn write_prefix_name_unit(&mut self) -> Result<(), std::fmt::Error> { if let Some(prefix) = self.prefix { self.writer.write_str(prefix.as_str())?; self.writer.write_str("_")?; } self.writer.write_str(self.name)?; if let Some(unit) = self.unit { self.writer.write_str("_")?; self.writer.write_str(unit.as_str())?; } Ok(()) } fn write_suffix(&mut self, suffix: &'static str) -> Result<(), std::fmt::Error> { self.writer.write_str("_")?; self.writer.write_str(suffix)?; Ok(()) } // TODO: Consider caching the encoded labels for Histograms as they stay the // same but are currently encoded multiple times. fn encode_labels( &mut self, additional_labels: Option<&S>, ) -> Result<(), std::fmt::Error> { if self.const_labels.is_empty() && additional_labels.is_none() && self.family_labels.is_none() { return Ok(()); } self.writer.write_str("{")?; self.const_labels .encode(LabelSetEncoder::new(self.writer).into())?; if let Some(additional_labels) = additional_labels { if !self.const_labels.is_empty() { self.writer.write_str(",")?; } additional_labels.encode(LabelSetEncoder::new(self.writer).into())?; } if let Some(labels) = &self.family_labels { if !self.const_labels.is_empty() || additional_labels.is_some() { self.writer.write_str(",")?; } labels.encode(LabelSetEncoder::new(self.writer).into())?; } self.writer.write_str("}")?; Ok(()) } } pub(crate) struct CounterValueEncoder<'a> { writer: &'a mut dyn Write, } impl<'a> std::fmt::Debug for CounterValueEncoder<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("CounterValueEncoder").finish() } } impl<'a> CounterValueEncoder<'a> { pub fn encode_f64(&mut self, v: f64) -> Result<(), std::fmt::Error> { self.writer.write_str(" ")?; self.writer.write_str(dtoa::Buffer::new().format(v))?; Ok(()) } pub fn encode_u64(&mut self, v: u64) -> Result<(), std::fmt::Error> { self.writer.write_str(" ")?; self.writer.write_str(itoa::Buffer::new().format(v))?; Ok(()) } } pub(crate) struct GaugeValueEncoder<'a> { writer: &'a mut dyn Write, } impl<'a> std::fmt::Debug for GaugeValueEncoder<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("GaugeValueEncoder").finish() } } impl<'a> GaugeValueEncoder<'a> { pub fn encode_u32(&mut self, v: u32) -> Result<(), std::fmt::Error> { self.writer.write_str(" ")?; self.writer.write_str(itoa::Buffer::new().format(v))?; Ok(()) } pub fn encode_i64(&mut self, v: i64) -> Result<(), std::fmt::Error> { self.writer.write_str(" ")?; self.writer.write_str(itoa::Buffer::new().format(v))?; Ok(()) } pub fn encode_f64(&mut self, v: f64) -> Result<(), std::fmt::Error> { self.writer.write_str(" ")?; self.writer.write_str(dtoa::Buffer::new().format(v))?; Ok(()) } } pub(crate) struct ExemplarValueEncoder<'a> { writer: &'a mut dyn Write, } impl<'a> std::fmt::Debug for ExemplarValueEncoder<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("ExemplarValueEncoder").finish() } } impl<'a> ExemplarValueEncoder<'a> { pub fn encode(&mut self, v: f64) -> Result<(), std::fmt::Error> { self.writer.write_str(dtoa::Buffer::new().format(v)) } } pub(crate) struct LabelSetEncoder<'a> { writer: &'a mut dyn Write, first: bool, } impl<'a> std::fmt::Debug for LabelSetEncoder<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("LabelSetEncoder") .field("first", &self.first) .finish() } } impl<'a> LabelSetEncoder<'a> { fn new(writer: &'a mut dyn Write) -> Self { Self { writer, first: true, } } pub fn encode_label(&mut self) -> LabelEncoder { let first = self.first; self.first = false; LabelEncoder { writer: self.writer, first, } } } pub(crate) struct LabelEncoder<'a> { writer: &'a mut dyn Write, first: bool, } impl<'a> std::fmt::Debug for LabelEncoder<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("LabelEncoder") .field("first", &self.first) .finish() } } impl<'a> LabelEncoder<'a> { pub fn encode_label_key(&mut self) -> Result { if !self.first { self.writer.write_str(",")?; } Ok(LabelKeyEncoder { writer: self.writer, }) } } pub(crate) struct LabelKeyEncoder<'a> { writer: &'a mut dyn Write, } impl<'a> std::fmt::Debug for LabelKeyEncoder<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("LabelKeyEncoder").finish() } } impl<'a> LabelKeyEncoder<'a> { pub fn encode_label_value(self) -> Result, std::fmt::Error> { self.writer.write_str("=\"")?; Ok(LabelValueEncoder { writer: self.writer, }) } } impl<'a> std::fmt::Write for LabelKeyEncoder<'a> { fn write_str(&mut self, s: &str) -> std::fmt::Result { self.writer.write_str(s) } } pub(crate) struct LabelValueEncoder<'a> { writer: &'a mut dyn Write, } impl<'a> std::fmt::Debug for LabelValueEncoder<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("LabelValueEncoder").finish() } } impl<'a> LabelValueEncoder<'a> { pub fn finish(self) -> Result<(), std::fmt::Error> { self.writer.write_str("\"") } } impl<'a> std::fmt::Write for LabelValueEncoder<'a> { fn write_str(&mut self, s: &str) -> std::fmt::Result { self.writer.write_str(s) } } #[cfg(test)] mod tests { use super::*; use crate::metrics::exemplar::HistogramWithExemplars; use crate::metrics::family::Family; use crate::metrics::gauge::Gauge; use crate::metrics::histogram::{exponential_buckets, Histogram}; use crate::metrics::info::Info; use crate::metrics::{counter::Counter, exemplar::CounterWithExemplar}; use pyo3::{prelude::*, types::PyModule}; use std::borrow::Cow; use std::sync::atomic::AtomicU32; #[test] fn encode_counter() { let counter: Counter = Counter::default(); let mut registry = Registry::default(); registry.register("my_counter", "My counter", counter); let mut encoded = String::new(); encode(&mut encoded, ®istry).unwrap(); parse_with_python_client(encoded); } #[test] fn encode_counter_with_unit() { let mut registry = Registry::default(); let counter: Counter = Counter::default(); registry.register_with_unit("my_counter", "My counter", Unit::Seconds, counter); let mut encoded = String::new(); encode(&mut encoded, ®istry).unwrap(); let expected = "# HELP my_counter_seconds My counter.\n".to_owned() + "# TYPE my_counter_seconds counter\n" + "# UNIT my_counter_seconds seconds\n" + "my_counter_seconds_total 0\n" + "# EOF\n"; assert_eq!(expected, encoded); parse_with_python_client(encoded); } #[test] fn encode_counter_with_exemplar() { let mut registry = Registry::default(); let counter_with_exemplar: CounterWithExemplar> = CounterWithExemplar::default(); registry.register_with_unit( "my_counter_with_exemplar", "My counter with exemplar", Unit::Seconds, counter_with_exemplar.clone(), ); counter_with_exemplar.inc_by(1, Some(vec![("user_id".to_string(), 42)])); let mut encoded = String::new(); encode(&mut encoded, ®istry).unwrap(); let expected = "# HELP my_counter_with_exemplar_seconds My counter with exemplar.\n" .to_owned() + "# TYPE my_counter_with_exemplar_seconds counter\n" + "# UNIT my_counter_with_exemplar_seconds seconds\n" + "my_counter_with_exemplar_seconds_total 1 # {user_id=\"42\"} 1.0\n" + "# EOF\n"; assert_eq!(expected, encoded); parse_with_python_client(encoded); } #[test] fn encode_gauge() { let mut registry = Registry::default(); let gauge: Gauge = Gauge::default(); registry.register("my_gauge", "My gauge", gauge); let gauge = Gauge::::default(); registry.register("u32_gauge", "Gauge::", gauge); let mut encoded = String::new(); encode(&mut encoded, ®istry).unwrap(); parse_with_python_client(encoded); } #[test] fn encode_counter_family() { let mut registry = Registry::default(); let family = Family::, Counter>::default(); registry.register("my_counter_family", "My counter family", family.clone()); family .get_or_create(&vec![ ("method".to_string(), "GET".to_string()), ("status".to_string(), "200".to_string()), ]) .inc(); let mut encoded = String::new(); encode(&mut encoded, ®istry).unwrap(); parse_with_python_client(encoded); } #[test] fn encode_counter_family_with_prefix_with_label() { let mut registry = Registry::default(); let sub_registry = registry.sub_registry_with_prefix("my_prefix"); let sub_sub_registry = sub_registry .sub_registry_with_label((Cow::Borrowed("my_key"), Cow::Borrowed("my_value"))); let family = Family::, Counter>::default(); sub_sub_registry.register("my_counter_family", "My counter family", family.clone()); family .get_or_create(&vec![ ("method".to_string(), "GET".to_string()), ("status".to_string(), "200".to_string()), ]) .inc(); let mut encoded = String::new(); encode(&mut encoded, ®istry).unwrap(); let expected = "# HELP my_prefix_my_counter_family My counter family.\n" .to_owned() + "# TYPE my_prefix_my_counter_family counter\n" + "my_prefix_my_counter_family_total{my_key=\"my_value\",method=\"GET\",status=\"200\"} 1\n" + "# EOF\n"; assert_eq!(expected, encoded); parse_with_python_client(encoded); } #[test] fn encode_info() { let mut registry = Registry::default(); let info = Info::new(vec![("os".to_string(), "GNU/linux".to_string())]); registry.register("my_info_metric", "My info metric", info); let mut encoded = String::new(); encode(&mut encoded, ®istry).unwrap(); let expected = "# HELP my_info_metric My info metric.\n".to_owned() + "# TYPE my_info_metric info\n" + "my_info_metric_info{os=\"GNU/linux\"} 1\n" + "# EOF\n"; assert_eq!(expected, encoded); parse_with_python_client(encoded); } #[test] fn encode_histogram() { let mut registry = Registry::default(); let histogram = Histogram::new(exponential_buckets(1.0, 2.0, 10)); registry.register("my_histogram", "My histogram", histogram.clone()); histogram.observe(1.0); let mut encoded = String::new(); encode(&mut encoded, ®istry).unwrap(); parse_with_python_client(encoded); } #[test] fn encode_histogram_family() { let mut registry = Registry::default(); let family = Family::new_with_constructor(|| Histogram::new(exponential_buckets(1.0, 2.0, 10))); registry.register("my_histogram", "My histogram", family.clone()); family .get_or_create(&vec![ ("method".to_string(), "GET".to_string()), ("status".to_string(), "200".to_string()), ]) .observe(1.0); let mut encoded = String::new(); encode(&mut encoded, ®istry).unwrap(); parse_with_python_client(encoded); } #[test] fn encode_histogram_with_exemplars() { let mut registry = Registry::default(); let histogram = HistogramWithExemplars::new(exponential_buckets(1.0, 2.0, 10)); registry.register("my_histogram", "My histogram", histogram.clone()); histogram.observe(1.0, Some([("user_id".to_string(), 42u64)])); let mut encoded = String::new(); encode(&mut encoded, ®istry).unwrap(); let expected = "# HELP my_histogram My histogram.\n".to_owned() + "# TYPE my_histogram histogram\n" + "my_histogram_sum 1.0\n" + "my_histogram_count 1\n" + "my_histogram_bucket{le=\"1.0\"} 1 # {user_id=\"42\"} 1.0\n" + "my_histogram_bucket{le=\"2.0\"} 1\n" + "my_histogram_bucket{le=\"4.0\"} 1\n" + "my_histogram_bucket{le=\"8.0\"} 1\n" + "my_histogram_bucket{le=\"16.0\"} 1\n" + "my_histogram_bucket{le=\"32.0\"} 1\n" + "my_histogram_bucket{le=\"64.0\"} 1\n" + "my_histogram_bucket{le=\"128.0\"} 1\n" + "my_histogram_bucket{le=\"256.0\"} 1\n" + "my_histogram_bucket{le=\"512.0\"} 1\n" + "my_histogram_bucket{le=\"+Inf\"} 1\n" + "# EOF\n"; assert_eq!(expected, encoded); parse_with_python_client(encoded); } #[test] fn sub_registry_with_prefix_and_label() { let top_level_metric_name = "my_top_level_metric"; let mut registry = Registry::default(); let counter: Counter = Counter::default(); registry.register(top_level_metric_name, "some help", counter.clone()); let prefix_1 = "prefix_1"; let prefix_1_metric_name = "my_prefix_1_metric"; let sub_registry = registry.sub_registry_with_prefix(prefix_1); sub_registry.register(prefix_1_metric_name, "some help", counter.clone()); let prefix_1_1 = "prefix_1_1"; let prefix_1_1_metric_name = "my_prefix_1_1_metric"; let sub_sub_registry = sub_registry.sub_registry_with_prefix(prefix_1_1); sub_sub_registry.register(prefix_1_1_metric_name, "some help", counter.clone()); let label_1_2 = (Cow::Borrowed("registry"), Cow::Borrowed("1_2")); let prefix_1_2_metric_name = "my_prefix_1_2_metric"; let sub_sub_registry = sub_registry.sub_registry_with_label(label_1_2.clone()); sub_sub_registry.register(prefix_1_2_metric_name, "some help", counter.clone()); let labels_1_3 = vec![ (Cow::Borrowed("label_1_3_1"), Cow::Borrowed("value_1_3_1")), (Cow::Borrowed("label_1_3_2"), Cow::Borrowed("value_1_3_2")), ]; let prefix_1_3_metric_name = "my_prefix_1_3_metric"; let sub_sub_registry = sub_registry.sub_registry_with_labels(labels_1_3.clone().into_iter()); sub_sub_registry.register(prefix_1_3_metric_name, "some help", counter.clone()); let prefix_1_3_1 = "prefix_1_3_1"; let prefix_1_3_1_metric_name = "my_prefix_1_3_1_metric"; let sub_sub_sub_registry = sub_sub_registry.sub_registry_with_prefix(prefix_1_3_1); sub_sub_sub_registry.register(prefix_1_3_1_metric_name, "some help", counter.clone()); let prefix_2 = "prefix_2"; let _ = registry.sub_registry_with_prefix(prefix_2); let prefix_3 = "prefix_3"; let prefix_3_metric_name = "my_prefix_3_metric"; let sub_registry = registry.sub_registry_with_prefix(prefix_3); sub_registry.register(prefix_3_metric_name, "some help", counter); let mut encoded = String::new(); encode(&mut encoded, ®istry).unwrap(); let expected = "# HELP my_top_level_metric some help.\n".to_owned() + "# TYPE my_top_level_metric counter\n" + "my_top_level_metric_total 0\n" + "# HELP prefix_1_my_prefix_1_metric some help.\n" + "# TYPE prefix_1_my_prefix_1_metric counter\n" + "prefix_1_my_prefix_1_metric_total 0\n" + "# HELP prefix_1_prefix_1_1_my_prefix_1_1_metric some help.\n" + "# TYPE prefix_1_prefix_1_1_my_prefix_1_1_metric counter\n" + "prefix_1_prefix_1_1_my_prefix_1_1_metric_total 0\n" + "# HELP prefix_1_my_prefix_1_2_metric some help.\n" + "# TYPE prefix_1_my_prefix_1_2_metric counter\n" + "prefix_1_my_prefix_1_2_metric_total{registry=\"1_2\"} 0\n" + "# HELP prefix_1_my_prefix_1_3_metric some help.\n" + "# TYPE prefix_1_my_prefix_1_3_metric counter\n" + "prefix_1_my_prefix_1_3_metric_total{label_1_3_1=\"value_1_3_1\",label_1_3_2=\"value_1_3_2\"} 0\n" + "# HELP prefix_1_prefix_1_3_1_my_prefix_1_3_1_metric some help.\n" + "# TYPE prefix_1_prefix_1_3_1_my_prefix_1_3_1_metric counter\n" + "prefix_1_prefix_1_3_1_my_prefix_1_3_1_metric_total{label_1_3_1=\"value_1_3_1\",label_1_3_2=\"value_1_3_2\"} 0\n" + "# HELP prefix_3_my_prefix_3_metric some help.\n" + "# TYPE prefix_3_my_prefix_3_metric counter\n" + "prefix_3_my_prefix_3_metric_total 0\n" + "# EOF\n"; assert_eq!(expected, encoded); parse_with_python_client(encoded); } #[test] fn sub_registry_collector() { use crate::encoding::EncodeMetric; #[derive(Debug)] struct Collector { name: String, } impl Collector { fn new(name: impl Into) -> Self { Self { name: name.into() } } } impl crate::collector::Collector for Collector { fn encode( &self, mut encoder: crate::encoding::DescriptorEncoder, ) -> Result<(), std::fmt::Error> { let counter = crate::metrics::counter::ConstCounter::new(42); let metric_encoder = encoder.encode_descriptor( &self.name, "some help", None, counter.metric_type(), )?; counter.encode(metric_encoder)?; Ok(()) } } let mut registry = Registry::default(); registry.register_collector(Box::new(Collector::new("top_level"))); let sub_registry = registry.sub_registry_with_prefix("prefix_1"); sub_registry.register_collector(Box::new(Collector::new("sub_level"))); let sub_sub_registry = sub_registry.sub_registry_with_prefix("prefix_1_2"); sub_sub_registry.register_collector(Box::new(Collector::new("sub_sub_level"))); let mut encoded = String::new(); encode(&mut encoded, ®istry).unwrap(); let expected = "# HELP top_level some help\n".to_owned() + "# TYPE top_level counter\n" + "top_level_total 42\n" + "# HELP prefix_1_sub_level some help\n" + "# TYPE prefix_1_sub_level counter\n" + "prefix_1_sub_level_total 42\n" + "# HELP prefix_1_prefix_1_2_sub_sub_level some help\n" + "# TYPE prefix_1_prefix_1_2_sub_sub_level counter\n" + "prefix_1_prefix_1_2_sub_sub_level_total 42\n" + "# EOF\n"; assert_eq!(expected, encoded); parse_with_python_client(encoded); } fn parse_with_python_client(input: String) { pyo3::prepare_freethreaded_python(); println!("{:?}", input); Python::with_gil(|py| { let parser = PyModule::from_code( py, r#" from prometheus_client.openmetrics.parser import text_string_to_metric_families def parse(input): families = text_string_to_metric_families(input) list(families) "#, "parser.py", "parser", ) .map_err(|e| e.to_string()) .unwrap(); parser .getattr("parse") .expect("`parse` to exist.") .call1((input.clone(),)) .map_err(|e| e.to_string()) .unwrap(); }) } } prometheus-client-0.22.2/src/encoding.rs000064400000000000000000000473201046102023000163070ustar 00000000000000//! Exposition format implementations. pub use prometheus_client_derive_encode::*; use crate::metrics::exemplar::Exemplar; use crate::metrics::MetricType; use crate::registry::{Prefix, Unit}; use std::borrow::Cow; use std::collections::HashMap; use std::fmt::Write; use std::ops::Deref; use std::rc::Rc; use std::sync::Arc; #[cfg(feature = "protobuf")] pub mod protobuf; pub mod text; macro_rules! for_both_mut { ($self:expr, $inner:ident, $pattern:pat, $fn:expr) => { match &mut $self.0 { $inner::Text($pattern) => $fn, #[cfg(feature = "protobuf")] $inner::Protobuf($pattern) => $fn, } }; } macro_rules! for_both { ($self:expr, $inner:ident, $pattern:pat, $fn:expr) => { match $self.0 { $inner::Text($pattern) => $fn, #[cfg(feature = "protobuf")] $inner::Protobuf($pattern) => $fn, } }; } /// Trait implemented by each metric type, e.g. /// [`Counter`](crate::metrics::counter::Counter), to implement its encoding in /// the OpenMetric text format. pub trait EncodeMetric { /// Encode the given instance in the OpenMetrics text encoding. // TODO: Lifetimes on MetricEncoder needed? fn encode(&self, encoder: MetricEncoder) -> Result<(), std::fmt::Error>; /// The OpenMetrics metric type of the instance. // One can not use [`TypedMetric`] directly, as associated constants are not // object safe and thus can not be used with dynamic dispatching. fn metric_type(&self) -> MetricType; } impl EncodeMetric for Box { fn encode(&self, encoder: MetricEncoder) -> Result<(), std::fmt::Error> { self.deref().encode(encoder) } fn metric_type(&self) -> MetricType { self.deref().metric_type() } } /// Encoder for a Metric Descriptor. #[derive(Debug)] pub struct DescriptorEncoder<'a>(DescriptorEncoderInner<'a>); #[derive(Debug)] enum DescriptorEncoderInner<'a> { Text(text::DescriptorEncoder<'a>), #[cfg(feature = "protobuf")] Protobuf(protobuf::DescriptorEncoder<'a>), } impl<'a> From> for DescriptorEncoder<'a> { fn from(e: text::DescriptorEncoder<'a>) -> Self { Self(DescriptorEncoderInner::Text(e)) } } #[cfg(feature = "protobuf")] impl<'a> From> for DescriptorEncoder<'a> { fn from(e: protobuf::DescriptorEncoder<'a>) -> Self { Self(DescriptorEncoderInner::Protobuf(e)) } } impl DescriptorEncoder<'_> { pub(crate) fn with_prefix_and_labels<'s>( &'s mut self, prefix: Option<&'s Prefix>, labels: &'s [(Cow<'static, str>, Cow<'static, str>)], // TODO: result needed? ) -> DescriptorEncoder<'s> { for_both_mut!( self, DescriptorEncoderInner, e, e.with_prefix_and_labels(prefix, labels).into() ) } /// Encode a descriptor. pub fn encode_descriptor<'s>( &'s mut self, name: &'s str, help: &str, unit: Option<&'s Unit>, metric_type: MetricType, ) -> Result, std::fmt::Error> { for_both_mut!( self, DescriptorEncoderInner, e, Ok(e.encode_descriptor(name, help, unit, metric_type)?.into()) ) } } /// Encoder for a metric. #[derive(Debug)] pub struct MetricEncoder<'a>(MetricEncoderInner<'a>); #[derive(Debug)] enum MetricEncoderInner<'a> { Text(text::MetricEncoder<'a>), #[cfg(feature = "protobuf")] Protobuf(protobuf::MetricEncoder<'a>), } impl<'a> From> for MetricEncoder<'a> { fn from(e: text::MetricEncoder<'a>) -> Self { Self(MetricEncoderInner::Text(e)) } } #[cfg(feature = "protobuf")] impl<'a> From> for MetricEncoder<'a> { fn from(e: protobuf::MetricEncoder<'a>) -> Self { Self(MetricEncoderInner::Protobuf(e)) } } impl MetricEncoder<'_> { /// Encode a counter. pub fn encode_counter< S: EncodeLabelSet, CounterValue: EncodeCounterValue, ExemplarValue: EncodeExemplarValue, >( &mut self, v: &CounterValue, exemplar: Option<&Exemplar>, ) -> Result<(), std::fmt::Error> { for_both_mut!(self, MetricEncoderInner, e, e.encode_counter(v, exemplar)) } /// Encode a gauge. pub fn encode_gauge( &mut self, v: &GaugeValue, ) -> Result<(), std::fmt::Error> { for_both_mut!(self, MetricEncoderInner, e, e.encode_gauge(v)) } /// Encode an info. pub fn encode_info(&mut self, label_set: &impl EncodeLabelSet) -> Result<(), std::fmt::Error> { for_both_mut!(self, MetricEncoderInner, e, e.encode_info(label_set)) } /// Encode a histogram. pub fn encode_histogram( &mut self, sum: f64, count: u64, buckets: &[(f64, u64)], exemplars: Option<&HashMap>>, ) -> Result<(), std::fmt::Error> { for_both_mut!( self, MetricEncoderInner, e, e.encode_histogram(sum, count, buckets, exemplars) ) } /// Encode a metric family. pub fn encode_family<'s, S: EncodeLabelSet>( &'s mut self, label_set: &'s S, ) -> Result, std::fmt::Error> { for_both_mut!( self, MetricEncoderInner, e, e.encode_family(label_set).map(Into::into) ) } } /// An encodable label set. pub trait EncodeLabelSet { /// Encode oneself into the given encoder. fn encode(&self, encoder: LabelSetEncoder) -> Result<(), std::fmt::Error>; } impl<'a> From> for LabelSetEncoder<'a> { fn from(e: text::LabelSetEncoder<'a>) -> Self { Self(LabelSetEncoderInner::Text(e)) } } /// Encoder for a label set. #[derive(Debug)] pub struct LabelSetEncoder<'a>(LabelSetEncoderInner<'a>); #[derive(Debug)] enum LabelSetEncoderInner<'a> { Text(text::LabelSetEncoder<'a>), #[cfg(feature = "protobuf")] Protobuf(protobuf::LabelSetEncoder<'a>), } #[cfg(feature = "protobuf")] impl<'a> From> for LabelSetEncoder<'a> { fn from(e: protobuf::LabelSetEncoder<'a>) -> Self { Self(LabelSetEncoderInner::Protobuf(e)) } } impl<'a> LabelSetEncoder<'a> { /// Encode the given label. pub fn encode_label(&mut self) -> LabelEncoder { for_both_mut!(self, LabelSetEncoderInner, e, e.encode_label().into()) } } /// An encodable label. pub trait EncodeLabel { /// Encode oneself into the given encoder. fn encode(&self, encoder: LabelEncoder) -> Result<(), std::fmt::Error>; } /// Encoder for a label. #[derive(Debug)] pub struct LabelEncoder<'a>(LabelEncoderInner<'a>); #[derive(Debug)] enum LabelEncoderInner<'a> { Text(text::LabelEncoder<'a>), #[cfg(feature = "protobuf")] Protobuf(protobuf::LabelEncoder<'a>), } impl<'a> From> for LabelEncoder<'a> { fn from(e: text::LabelEncoder<'a>) -> Self { Self(LabelEncoderInner::Text(e)) } } #[cfg(feature = "protobuf")] impl<'a> From> for LabelEncoder<'a> { fn from(e: protobuf::LabelEncoder<'a>) -> Self { Self(LabelEncoderInner::Protobuf(e)) } } impl<'a> LabelEncoder<'a> { /// Encode a label. pub fn encode_label_key(&mut self) -> Result { for_both_mut!( self, LabelEncoderInner, e, e.encode_label_key().map(Into::into) ) } } /// An encodable label key. pub trait EncodeLabelKey { /// Encode oneself into the given encoder. fn encode(&self, encoder: &mut LabelKeyEncoder) -> Result<(), std::fmt::Error>; } /// Encoder for a label key. #[derive(Debug)] pub struct LabelKeyEncoder<'a>(LabelKeyEncoderInner<'a>); #[derive(Debug)] enum LabelKeyEncoderInner<'a> { Text(text::LabelKeyEncoder<'a>), #[cfg(feature = "protobuf")] Protobuf(protobuf::LabelKeyEncoder<'a>), } impl<'a> From> for LabelKeyEncoder<'a> { fn from(e: text::LabelKeyEncoder<'a>) -> Self { Self(LabelKeyEncoderInner::Text(e)) } } #[cfg(feature = "protobuf")] impl<'a> From> for LabelKeyEncoder<'a> { fn from(e: protobuf::LabelKeyEncoder<'a>) -> Self { Self(LabelKeyEncoderInner::Protobuf(e)) } } impl<'a> std::fmt::Write for LabelKeyEncoder<'a> { fn write_str(&mut self, s: &str) -> std::fmt::Result { for_both_mut!(self, LabelKeyEncoderInner, e, e.write_str(s)) } } impl<'a> LabelKeyEncoder<'a> { /// Encode a label value. pub fn encode_label_value(self) -> Result, std::fmt::Error> { for_both!( self, LabelKeyEncoderInner, e, e.encode_label_value().map(LabelValueEncoder::from) ) } } impl EncodeLabelSet for [T; N] { fn encode(&self, encoder: LabelSetEncoder) -> Result<(), std::fmt::Error> { self.as_ref().encode(encoder) } } impl EncodeLabelSet for &[T] { fn encode(&self, mut encoder: LabelSetEncoder) -> Result<(), std::fmt::Error> { if self.is_empty() { return Ok(()); } for label in self.iter() { label.encode(encoder.encode_label())? } Ok(()) } } impl EncodeLabelSet for Vec { fn encode(&self, encoder: LabelSetEncoder) -> Result<(), std::fmt::Error> { self.as_slice().encode(encoder) } } impl EncodeLabelSet for () { fn encode(&self, _encoder: LabelSetEncoder) -> Result<(), std::fmt::Error> { Ok(()) } } impl EncodeLabel for (K, V) { fn encode(&self, mut encoder: LabelEncoder) -> Result<(), std::fmt::Error> { let (key, value) = self; let mut label_key_encoder = encoder.encode_label_key()?; key.encode(&mut label_key_encoder)?; let mut label_value_encoder = label_key_encoder.encode_label_value()?; value.encode(&mut label_value_encoder)?; label_value_encoder.finish()?; Ok(()) } } impl EncodeLabelKey for &str { fn encode(&self, encoder: &mut LabelKeyEncoder) -> Result<(), std::fmt::Error> { encoder.write_str(self)?; Ok(()) } } impl EncodeLabelKey for String { fn encode(&self, encoder: &mut LabelKeyEncoder) -> Result<(), std::fmt::Error> { EncodeLabelKey::encode(&self.as_str(), encoder) } } impl<'a> EncodeLabelKey for Cow<'a, str> { fn encode(&self, encoder: &mut LabelKeyEncoder) -> Result<(), std::fmt::Error> { EncodeLabelKey::encode(&self.as_ref(), encoder) } } impl EncodeLabelKey for Box where for<'a> &'a T: EncodeLabelKey, { fn encode(&self, encoder: &mut LabelKeyEncoder) -> Result<(), std::fmt::Error> { EncodeLabelKey::encode(&self.as_ref(), encoder) } } impl EncodeLabelKey for Arc where for<'a> &'a T: EncodeLabelKey, { fn encode(&self, encoder: &mut LabelKeyEncoder) -> Result<(), std::fmt::Error> { EncodeLabelKey::encode(&self.as_ref(), encoder) } } impl EncodeLabelKey for Rc where for<'a> &'a T: EncodeLabelKey, { fn encode(&self, encoder: &mut LabelKeyEncoder) -> Result<(), std::fmt::Error> { EncodeLabelKey::encode(&self.as_ref(), encoder) } } /// An encodable label value. pub trait EncodeLabelValue { /// Encode oneself into the given encoder. fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error>; } /// Encoder for a label value. #[derive(Debug)] pub struct LabelValueEncoder<'a>(LabelValueEncoderInner<'a>); impl<'a> From> for LabelValueEncoder<'a> { fn from(e: text::LabelValueEncoder<'a>) -> Self { LabelValueEncoder(LabelValueEncoderInner::Text(e)) } } #[cfg(feature = "protobuf")] impl<'a> From> for LabelValueEncoder<'a> { fn from(e: protobuf::LabelValueEncoder<'a>) -> Self { LabelValueEncoder(LabelValueEncoderInner::Protobuf(e)) } } #[derive(Debug)] enum LabelValueEncoderInner<'a> { Text(text::LabelValueEncoder<'a>), #[cfg(feature = "protobuf")] Protobuf(protobuf::LabelValueEncoder<'a>), } impl<'a> LabelValueEncoder<'a> { /// Finish encoding the label value. pub fn finish(self) -> Result<(), std::fmt::Error> { for_both!(self, LabelValueEncoderInner, e, e.finish()) } } impl<'a> std::fmt::Write for LabelValueEncoder<'a> { fn write_str(&mut self, s: &str) -> std::fmt::Result { for_both_mut!(self, LabelValueEncoderInner, e, e.write_str(s)) } } impl EncodeLabelValue for &str { fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> { encoder.write_str(self)?; Ok(()) } } impl EncodeLabelValue for String { fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> { EncodeLabelValue::encode(&self.as_str(), encoder) } } impl<'a> EncodeLabelValue for Cow<'a, str> { fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> { EncodeLabelValue::encode(&self.as_ref(), encoder) } } impl EncodeLabelValue for Box where for<'a> &'a T: EncodeLabelValue, { fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> { EncodeLabelValue::encode(&self.as_ref(), encoder) } } impl EncodeLabelValue for Arc where for<'a> &'a T: EncodeLabelValue, { fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> { EncodeLabelValue::encode(&self.as_ref(), encoder) } } impl EncodeLabelValue for Rc where for<'a> &'a T: EncodeLabelValue, { fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> { EncodeLabelValue::encode(&self.as_ref(), encoder) } } impl EncodeLabelValue for f64 { fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> { encoder.write_str(dtoa::Buffer::new().format(*self)) } } impl EncodeLabelValue for Option where T: EncodeLabelValue, { fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> { match self { Some(v) => EncodeLabelValue::encode(v, encoder), None => EncodeLabelValue::encode(&"", encoder), } } } macro_rules! impl_encode_label_value_for_integer { ($($t:ident),*) => {$( impl EncodeLabelValue for $t { fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> { encoder.write_str(itoa::Buffer::new().format(*self)) } } )*}; } impl_encode_label_value_for_integer!( u128, i128, u64, i64, u32, i32, u16, i16, u8, i8, usize, isize ); /// An encodable gauge value. pub trait EncodeGaugeValue { /// Encode the given instance in the OpenMetrics text encoding. fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error>; } impl EncodeGaugeValue for u32 { fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error> { encoder.encode_u32(*self) } } impl EncodeGaugeValue for i64 { fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error> { encoder.encode_i64(*self) } } impl EncodeGaugeValue for f64 { fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error> { encoder.encode_f64(*self) } } /// Encoder for a gauge value. #[derive(Debug)] pub struct GaugeValueEncoder<'a>(GaugeValueEncoderInner<'a>); #[derive(Debug)] enum GaugeValueEncoderInner<'a> { Text(text::GaugeValueEncoder<'a>), #[cfg(feature = "protobuf")] Protobuf(protobuf::GaugeValueEncoder<'a>), } impl<'a> GaugeValueEncoder<'a> { fn encode_u32(&mut self, v: u32) -> Result<(), std::fmt::Error> { for_both_mut!(self, GaugeValueEncoderInner, e, e.encode_u32(v)) } fn encode_i64(&mut self, v: i64) -> Result<(), std::fmt::Error> { for_both_mut!(self, GaugeValueEncoderInner, e, e.encode_i64(v)) } fn encode_f64(&mut self, v: f64) -> Result<(), std::fmt::Error> { for_both_mut!(self, GaugeValueEncoderInner, e, e.encode_f64(v)) } } impl<'a> From> for GaugeValueEncoder<'a> { fn from(e: text::GaugeValueEncoder<'a>) -> Self { GaugeValueEncoder(GaugeValueEncoderInner::Text(e)) } } #[cfg(feature = "protobuf")] impl<'a> From> for GaugeValueEncoder<'a> { fn from(e: protobuf::GaugeValueEncoder<'a>) -> Self { GaugeValueEncoder(GaugeValueEncoderInner::Protobuf(e)) } } /// An encodable counter value. pub trait EncodeCounterValue { /// Encode the given instance in the OpenMetrics text encoding. fn encode(&self, encoder: &mut CounterValueEncoder) -> Result<(), std::fmt::Error>; } impl EncodeCounterValue for u64 { fn encode(&self, encoder: &mut CounterValueEncoder) -> Result<(), std::fmt::Error> { encoder.encode_u64(*self) } } impl EncodeCounterValue for f64 { fn encode(&self, encoder: &mut CounterValueEncoder) -> Result<(), std::fmt::Error> { encoder.encode_f64(*self) } } /// Encoder for a counter value. #[derive(Debug)] pub struct CounterValueEncoder<'a>(CounterValueEncoderInner<'a>); #[derive(Debug)] enum CounterValueEncoderInner<'a> { Text(text::CounterValueEncoder<'a>), #[cfg(feature = "protobuf")] Protobuf(protobuf::CounterValueEncoder<'a>), } impl<'a> CounterValueEncoder<'a> { fn encode_f64(&mut self, v: f64) -> Result<(), std::fmt::Error> { for_both_mut!(self, CounterValueEncoderInner, e, e.encode_f64(v)) } fn encode_u64(&mut self, v: u64) -> Result<(), std::fmt::Error> { for_both_mut!(self, CounterValueEncoderInner, e, e.encode_u64(v)) } } /// An encodable exemplar value. pub trait EncodeExemplarValue { /// Encode the given instance in the OpenMetrics text encoding. fn encode(&self, encoder: ExemplarValueEncoder) -> Result<(), std::fmt::Error>; } impl EncodeExemplarValue for f64 { fn encode(&self, mut encoder: ExemplarValueEncoder) -> Result<(), std::fmt::Error> { encoder.encode(*self) } } impl EncodeExemplarValue for u64 { fn encode(&self, mut encoder: ExemplarValueEncoder) -> Result<(), std::fmt::Error> { encoder.encode(*self as f64) } } impl<'a> From> for CounterValueEncoder<'a> { fn from(e: text::CounterValueEncoder<'a>) -> Self { CounterValueEncoder(CounterValueEncoderInner::Text(e)) } } #[cfg(feature = "protobuf")] impl<'a> From> for CounterValueEncoder<'a> { fn from(e: protobuf::CounterValueEncoder<'a>) -> Self { CounterValueEncoder(CounterValueEncoderInner::Protobuf(e)) } } /// Encoder for an exemplar value. #[derive(Debug)] pub struct ExemplarValueEncoder<'a>(ExemplarValueEncoderInner<'a>); #[derive(Debug)] enum ExemplarValueEncoderInner<'a> { Text(text::ExemplarValueEncoder<'a>), #[cfg(feature = "protobuf")] Protobuf(protobuf::ExemplarValueEncoder<'a>), } impl<'a> ExemplarValueEncoder<'a> { fn encode(&mut self, v: f64) -> Result<(), std::fmt::Error> { for_both_mut!(self, ExemplarValueEncoderInner, e, e.encode(v)) } } impl<'a> From> for ExemplarValueEncoder<'a> { fn from(e: text::ExemplarValueEncoder<'a>) -> Self { ExemplarValueEncoder(ExemplarValueEncoderInner::Text(e)) } } #[cfg(feature = "protobuf")] impl<'a> From> for ExemplarValueEncoder<'a> { fn from(e: protobuf::ExemplarValueEncoder<'a>) -> Self { ExemplarValueEncoder(ExemplarValueEncoderInner::Protobuf(e)) } } prometheus-client-0.22.2/src/lib.rs000064400000000000000000000056111046102023000152640ustar 00000000000000#![deny(dead_code)] #![deny(missing_docs)] #![deny(unused)] #![forbid(unsafe_code)] #![warn(missing_debug_implementations)] //! Client library implementation of the [Open Metrics //! specification](https://github.com/OpenObservability/OpenMetrics). Allows //! developers to instrument applications and thus enables operators to monitor //! said applications with monitoring systems like //! [Prometheus](https://prometheus.io/). //! //! # Examples //! //! ``` //! use prometheus_client::encoding::{EncodeLabelSet, EncodeLabelValue}; //! use prometheus_client::encoding::text::encode; //! use prometheus_client::metrics::counter::{Atomic, Counter}; //! use prometheus_client::metrics::family::Family; //! use prometheus_client::registry::Registry; //! use std::io::Write; //! //! // Create a metric registry. //! // //! // Note the angle brackets to make sure to use the default (dynamic //! // dispatched boxed metric) for the generic type parameter. //! let mut registry = ::default(); //! //! // Define a type representing a metric label set, i.e. a key value pair. //! // //! // You could as well use `(String, String)` to represent a label set, //! // instead of the custom type below. //! #[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)] //! struct Labels { //! // Use your own enum types to represent label values. //! method: Method, //! // Or just a plain string. //! path: String, //! }; //! //! #[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelValue)] //! enum Method { //! GET, //! PUT, //! }; //! //! // Create a sample counter metric family utilizing the above custom label //! // type, representing the number of HTTP requests received. //! let http_requests = Family::::default(); //! //! // Register the metric family with the registry. //! registry.register( //! // With the metric name. //! "http_requests", //! // And the metric help text. //! "Number of HTTP requests received", //! http_requests.clone(), //! ); //! //! // Somewhere in your business logic record a single HTTP GET request. //! http_requests.get_or_create( //! &Labels { method: Method::GET, path: "/metrics".to_string() } //! ).inc(); //! //! // When a monitoring system like Prometheus scrapes the local node, encode //! // all metrics in the registry in the text format, and send the encoded //! // metrics back. //! let mut buffer = String::new(); //! encode(&mut buffer, ®istry).unwrap(); //! //! let expected = "# HELP http_requests Number of HTTP requests received.\n".to_owned() + //! "# TYPE http_requests counter\n" + //! "http_requests_total{method=\"GET\",path=\"/metrics\"} 1\n" + //! "# EOF\n"; //! assert_eq!(expected, buffer); //! ``` //! See [examples] directory for more. //! //! [examples]: https://github.com/prometheus/client_rust/tree/master/examples pub mod collector; pub mod encoding; pub mod metrics; pub mod registry; prometheus-client-0.22.2/src/metrics/counter.rs000064400000000000000000000147651046102023000176550ustar 00000000000000//! Module implementing an Open Metrics counter. //! //! See [`Counter`] for details. use crate::encoding::{EncodeMetric, MetricEncoder}; use super::{MetricType, TypedMetric}; use std::marker::PhantomData; #[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] use std::sync::atomic::AtomicU64; use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::Arc; /// Open Metrics [`Counter`] to measure discrete events. /// /// Single monotonically increasing value metric. /// /// [`Counter`] is generic over the actual data type tracking the [`Counter`] /// state as well as the data type used to interact with the [`Counter`]. Out of /// convenience the generic type parameters are set to use an [`AtomicU64`] as a /// storage and [`u64`] on the interface by default. /// /// # Examples /// /// ## Using [`AtomicU64`] as storage and [`u64`] on the interface /// /// ``` /// # use prometheus_client::metrics::counter::Counter; /// let counter: Counter = Counter::default(); /// counter.inc(); /// let _value: u64 = counter.get(); /// ``` /// /// ## Using [`AtomicU64`] as storage and [`f64`] on the interface /// /// ``` /// # use prometheus_client::metrics::counter::Counter; /// # use std::sync::atomic::AtomicU64; /// let counter = Counter::::default(); /// counter.inc(); /// let _value: f64 = counter.get(); /// ``` #[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] #[derive(Debug)] pub struct Counter { value: Arc, phantom: PhantomData, } /// Open Metrics [`Counter`] to measure discrete events. #[cfg(any(target_arch = "mips", target_arch = "powerpc"))] #[derive(Debug)] pub struct Counter { value: Arc, phantom: PhantomData, } impl Clone for Counter { fn clone(&self) -> Self { Self { value: self.value.clone(), phantom: PhantomData, } } } impl Default for Counter { fn default() -> Self { Counter { value: Arc::new(A::default()), phantom: PhantomData, } } } impl> Counter { /// Increase the [`Counter`] by 1, returning the previous value. pub fn inc(&self) -> N { self.value.inc() } /// Increase the [`Counter`] by `v`, returning the previous value. pub fn inc_by(&self, v: N) -> N { self.value.inc_by(v) } /// Get the current value of the [`Counter`]. pub fn get(&self) -> N { self.value.get() } /// Exposes the inner atomic type of the [`Counter`]. /// /// This should only be used for advanced use-cases which are not directly /// supported by the library. /// /// The caller of this function has to uphold the property of an Open /// Metrics counter namely that the value is monotonically increasing, i.e. /// either stays the same or increases. pub fn inner(&self) -> &A { &self.value } } /// Atomic operations for a [`Counter`] value store. pub trait Atomic { /// Increase the value by `1`. fn inc(&self) -> N; /// Increase the value. fn inc_by(&self, v: N) -> N; /// Get the the value. fn get(&self) -> N; } #[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] impl Atomic for AtomicU64 { fn inc(&self) -> u64 { self.inc_by(1) } fn inc_by(&self, v: u64) -> u64 { self.fetch_add(v, Ordering::Relaxed) } fn get(&self) -> u64 { self.load(Ordering::Relaxed) } } impl Atomic for AtomicU32 { fn inc(&self) -> u32 { self.inc_by(1) } fn inc_by(&self, v: u32) -> u32 { self.fetch_add(v, Ordering::Relaxed) } fn get(&self) -> u32 { self.load(Ordering::Relaxed) } } #[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] impl Atomic for AtomicU64 { fn inc(&self) -> f64 { self.inc_by(1.0) } fn inc_by(&self, v: f64) -> f64 { let mut old_u64 = self.load(Ordering::Relaxed); let mut old_f64; loop { old_f64 = f64::from_bits(old_u64); let new = f64::to_bits(old_f64 + v); match self.compare_exchange_weak(old_u64, new, Ordering::Relaxed, Ordering::Relaxed) { Ok(_) => break, Err(x) => old_u64 = x, } } old_f64 } fn get(&self) -> f64 { f64::from_bits(self.load(Ordering::Relaxed)) } } impl TypedMetric for Counter { const TYPE: MetricType = MetricType::Counter; } impl EncodeMetric for Counter where N: crate::encoding::EncodeCounterValue, A: Atomic, { fn encode(&self, mut encoder: MetricEncoder) -> Result<(), std::fmt::Error> { encoder.encode_counter::<(), _, u64>(&self.get(), None) } fn metric_type(&self) -> MetricType { Self::TYPE } } /// As a [`Counter`], but constant, meaning it cannot change once created. /// /// Needed for advanced use-cases, e.g. in combination with [`Collector`](crate::collector::Collector). #[derive(Debug, Default)] pub struct ConstCounter { value: N, } impl ConstCounter { /// Creates a new [`ConstCounter`]. pub fn new(value: N) -> Self { Self { value } } } impl TypedMetric for ConstCounter { const TYPE: MetricType = MetricType::Counter; } impl EncodeMetric for ConstCounter where N: crate::encoding::EncodeCounterValue, { fn encode(&self, mut encoder: MetricEncoder) -> Result<(), std::fmt::Error> { encoder.encode_counter::<(), _, u64>(&self.value, None) } fn metric_type(&self) -> MetricType { Self::TYPE } } #[cfg(test)] mod tests { use super::*; use quickcheck::QuickCheck; #[test] fn inc_and_get() { let counter: Counter = Counter::default(); assert_eq!(0, counter.inc()); assert_eq!(1, counter.get()); } #[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] #[test] fn f64_stored_in_atomic_u64() { fn prop(fs: Vec) { let fs: Vec = fs .into_iter() // Map infinite, subnormal and NaN to 0.0. .map(|f| if f.is_normal() { f } else { 0.0 }) .collect(); let sum = fs.iter().sum(); let counter = Counter::::default(); for f in fs { counter.inc_by(f); } assert_eq!(counter.get(), sum) } QuickCheck::new().tests(10).quickcheck(prop as fn(_)) } } prometheus-client-0.22.2/src/metrics/exemplar.rs000064400000000000000000000224751046102023000200100ustar 00000000000000//! Module implementing an Open Metrics exemplars for counters and histograms. //! //! See [`CounterWithExemplar`] and [`HistogramWithExemplars`] for details. use crate::encoding::{ EncodeCounterValue, EncodeExemplarValue, EncodeLabelSet, EncodeMetric, MetricEncoder, }; use super::counter::{self, Counter}; use super::histogram::Histogram; use super::{MetricType, TypedMetric}; use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard}; use std::collections::HashMap; #[cfg(any(target_arch = "mips", target_arch = "powerpc"))] use std::sync::atomic::AtomicU32; #[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] use std::sync::atomic::AtomicU64; use std::sync::Arc; /// An OpenMetrics exemplar. #[derive(Debug)] pub struct Exemplar { pub(crate) label_set: S, pub(crate) value: V, } ///////////////////////////////////////////////////////////////////////////////// // Counter /// Open Metrics [`Counter`] with an [`Exemplar`] to both measure discrete /// events and track references to data outside of the metric set. /// /// ``` /// # use prometheus_client::metrics::exemplar::CounterWithExemplar; /// let counter_with_exemplar = CounterWithExemplar::>::default(); /// counter_with_exemplar.inc_by(1, Some(vec![("user_id".to_string(), "42".to_string())])); /// let _value: (u64, _) = counter_with_exemplar.get(); /// ``` /// You can also use exemplars with families. Just wrap the exemplar in a Family. /// ``` /// # use prometheus_client::metrics::exemplar::CounterWithExemplar; /// # use prometheus_client::metrics::histogram::exponential_buckets; /// # use prometheus_client::metrics::family::Family; /// # use prometheus_client_derive_encode::EncodeLabelSet; /// #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug, Default)] /// pub struct ResultLabel { /// pub result: String, /// } /// /// #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug, Default)] /// pub struct TraceLabel { /// pub trace_id: String, /// } /// /// let latency: Family> = Family::default(); /// /// latency /// .get_or_create(&ResultLabel { /// result: "success".to_owned(), /// }) /// .inc_by( /// 1, /// Some(TraceLabel { /// trace_id: "3a2f90c9f80b894f".to_owned(), /// }), /// ); /// ``` #[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] #[derive(Debug)] pub struct CounterWithExemplar { pub(crate) inner: Arc>>, } impl TypedMetric for CounterWithExemplar { const TYPE: MetricType = MetricType::Counter; } /// Open Metrics [`Counter`] with an [`Exemplar`] to both measure discrete /// events and track references to data outside of the metric set. #[cfg(any(target_arch = "mips", target_arch = "powerpc"))] #[derive(Debug)] pub struct CounterWithExemplar { pub(crate) inner: Arc>>, } impl Clone for CounterWithExemplar { fn clone(&self) -> Self { CounterWithExemplar { inner: self.inner.clone(), } } } /// An OpenMetrics [`Counter`] in combination with an OpenMetrics [`Exemplar`]. #[derive(Debug)] pub struct CounterWithExemplarInner { pub(crate) exemplar: Option>, pub(crate) counter: Counter, } impl Default for CounterWithExemplar { fn default() -> Self { Self { inner: Arc::new(RwLock::new(CounterWithExemplarInner { exemplar: None, counter: Default::default(), })), } } } impl> CounterWithExemplar { // TODO: Implement `fn inc`. Problematic right now as one can not produce // value `1` of type `N`. /// Increase the [`CounterWithExemplar`] by `v`, updating the [`Exemplar`] /// if a label set is provided, returning the previous value. pub fn inc_by(&self, v: N, label_set: Option) -> N { let mut inner = self.inner.write(); inner.exemplar = label_set.map(|label_set| Exemplar { label_set, value: v.clone(), }); inner.counter.inc_by(v) } /// Get the current value of the [`CounterWithExemplar`] as well as its /// [`Exemplar`] if any. pub fn get(&self) -> (N, MappedRwLockReadGuard>>) { let inner = self.inner.read(); let value = inner.counter.get(); let exemplar = RwLockReadGuard::map(inner, |inner| &inner.exemplar); (value, exemplar) } /// Exposes the inner atomic type of the [`CounterWithExemplar`]. /// /// This should only be used for advanced use-cases which are not directly /// supported by the library. /// /// The caller of this function has to uphold the property of an Open /// Metrics counter namely that the value is monotonically increasing, i.e. /// either stays the same or increases. pub fn inner(&self) -> MappedRwLockReadGuard { RwLockReadGuard::map(self.inner.read(), |inner| inner.counter.inner()) } } // TODO: S, V, N, A are hard to grasp. impl EncodeMetric for crate::metrics::exemplar::CounterWithExemplar where S: EncodeLabelSet, N: EncodeCounterValue + EncodeExemplarValue + Clone, A: counter::Atomic, { fn encode(&self, mut encoder: MetricEncoder) -> Result<(), std::fmt::Error> { let (value, exemplar) = self.get(); encoder.encode_counter(&value, exemplar.as_ref()) } fn metric_type(&self) -> MetricType { Counter::::TYPE } } ///////////////////////////////////////////////////////////////////////////////// // Histogram /// Open Metrics [`Histogram`] to both measure distributions of discrete events. /// and track references to data outside of the metric set. /// /// ``` /// # use prometheus_client::metrics::exemplar::HistogramWithExemplars; /// # use prometheus_client::metrics::histogram::exponential_buckets; /// let histogram = HistogramWithExemplars::new(exponential_buckets(1.0, 2.0, 10)); /// histogram.observe(4.2, Some(vec![("user_id".to_string(), "42".to_string())])); /// ``` /// You can also use exemplars with families. Just wrap the exemplar in a Family. /// ``` /// # use prometheus_client::metrics::exemplar::HistogramWithExemplars; /// # use prometheus_client::metrics::histogram::exponential_buckets; /// # use prometheus_client::metrics::family::Family; /// # use prometheus_client::encoding::EncodeLabelSet; /// #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug, Default)] /// pub struct ResultLabel { /// pub result: String, /// } /// /// #[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug, Default)] /// pub struct TraceLabel { /// pub trace_id: String, /// } /// /// let latency: Family> = /// Family::new_with_constructor(|| { /// HistogramWithExemplars::new(exponential_buckets(1.0, 2.0, 10)) /// }); /// /// latency /// .get_or_create(&ResultLabel { /// result: "success".to_owned(), /// }) /// .observe( /// 0.001345422, /// Some(TraceLabel { /// trace_id: "3a2f90c9f80b894f".to_owned(), /// }), /// ); /// ``` #[derive(Debug)] pub struct HistogramWithExemplars { // TODO: Not ideal, as Histogram has a Mutex as well. pub(crate) inner: Arc>>, } impl TypedMetric for HistogramWithExemplars { const TYPE: MetricType = MetricType::Histogram; } impl Clone for HistogramWithExemplars { fn clone(&self) -> Self { Self { inner: self.inner.clone(), } } } /// An OpenMetrics [`Histogram`] in combination with an OpenMetrics [`Exemplar`]. #[derive(Debug)] pub struct HistogramWithExemplarsInner { pub(crate) exemplars: HashMap>, pub(crate) histogram: Histogram, } impl HistogramWithExemplars { /// Create a new [`HistogramWithExemplars`]. pub fn new(buckets: impl Iterator) -> Self { Self { inner: Arc::new(RwLock::new(HistogramWithExemplarsInner { exemplars: Default::default(), histogram: Histogram::new(buckets), })), } } /// Observe the given value, optionally providing a label set and thus /// setting the [`Exemplar`] value. pub fn observe(&self, v: f64, label_set: Option) { let mut inner = self.inner.write(); let bucket = inner.histogram.observe_and_bucket(v); if let (Some(bucket), Some(label_set)) = (bucket, label_set) { inner.exemplars.insert( bucket, Exemplar { label_set, value: v, }, ); } } pub(crate) fn inner(&self) -> RwLockReadGuard> { self.inner.read() } } impl EncodeMetric for HistogramWithExemplars { fn encode(&self, mut encoder: MetricEncoder) -> Result<(), std::fmt::Error> { let inner = self.inner(); let (sum, count, buckets) = inner.histogram.get(); encoder.encode_histogram(sum, count, &buckets, Some(&inner.exemplars)) } fn metric_type(&self) -> MetricType { Histogram::TYPE } } prometheus-client-0.22.2/src/metrics/family.rs000064400000000000000000000354261046102023000174540ustar 00000000000000//! Module implementing an Open Metrics metric family. //! //! See [`Family`] for details. use crate::encoding::{EncodeLabelSet, EncodeMetric, MetricEncoder}; use super::{MetricType, TypedMetric}; use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard, RwLockWriteGuard}; use std::collections::HashMap; use std::sync::Arc; /// Representation of the OpenMetrics *MetricFamily* data type. /// /// A [`Family`] is a set of metrics with the same name, help text and /// type, differentiated by their label values thus spanning a multidimensional /// space. /// /// # Generic over the label set /// /// A [`Family`] is generic over the label type. For convenience one might /// choose a `Vec<(String, String)>`, for performance and/or type safety one might /// define a custom type. /// /// ## Examples /// /// ### [`Family`] with `Vec<(String, String)>` for convenience /// /// ``` /// # use prometheus_client::encoding::text::encode; /// # use prometheus_client::metrics::counter::{Atomic, Counter}; /// # use prometheus_client::metrics::family::Family; /// # use prometheus_client::registry::Registry; /// # /// # let mut registry = Registry::default(); /// let family = Family::, Counter>::default(); /// # registry.register( /// # "my_counter", /// # "This is my counter", /// # family.clone(), /// # ); /// /// // Record a single HTTP GET request. /// family.get_or_create(&vec![("method".to_owned(), "GET".to_owned())]).inc(); /// /// # // Encode all metrics in the registry in the text format. /// # let mut buffer = String::new(); /// # encode(&mut buffer, ®istry).unwrap(); /// # /// # let expected = "# HELP my_counter This is my counter.\n".to_owned() + /// # "# TYPE my_counter counter\n" + /// # "my_counter_total{method=\"GET\"} 1\n" + /// # "# EOF\n"; /// # assert_eq!(expected, buffer); /// ``` /// /// ### [`Family`] with custom type for performance and/or type safety /// /// Using `EncodeLabelSet` and `EncodeLabelValue` derive macro to generate /// [`EncodeLabelSet`] for `struct`s and /// [`EncodeLabelValue`](crate::encoding::EncodeLabelValue) for `enum`s. /// /// ``` /// # use prometheus_client::encoding::{EncodeLabelSet, EncodeLabelValue}; /// # use prometheus_client::encoding::text::encode; /// # use prometheus_client::metrics::counter::{Atomic, Counter}; /// # use prometheus_client::metrics::family::Family; /// # use prometheus_client::registry::Registry; /// # use std::io::Write; /// # /// # let mut registry = Registry::default(); /// #[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)] /// struct Labels { /// method: Method, /// }; /// /// #[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelValue)] /// enum Method { /// GET, /// PUT, /// }; /// /// let family = Family::::default(); /// # registry.register( /// # "my_counter", /// # "This is my counter", /// # family.clone(), /// # ); /// /// // Record a single HTTP GET request. /// family.get_or_create(&Labels { method: Method::GET }).inc(); /// # /// # // Encode all metrics in the registry in the text format. /// # let mut buffer = String::new(); /// # encode(&mut buffer, ®istry).unwrap(); /// # /// # let expected = "# HELP my_counter This is my counter.\n".to_owned() + /// # "# TYPE my_counter counter\n" + /// # "my_counter_total{method=\"GET\"} 1\n" + /// # "# EOF\n"; /// # assert_eq!(expected, buffer); /// ``` // TODO: Consider exposing hash algorithm. pub struct Family M> { metrics: Arc>>, /// Function that when called constructs a new metric. /// /// For most metric types this would simply be its [`Default`] /// implementation set through [`Family::default`]. For metric types that /// need custom construction logic like /// [`Histogram`](crate::metrics::histogram::Histogram) in order to set /// specific buckets, a custom constructor is set via /// [`Family::new_with_constructor`]. constructor: C, } impl std::fmt::Debug for Family { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Family") .field("metrics", &self.metrics) .finish() } } /// A constructor for creating new metrics in a [`Family`] when calling /// [`Family::get_or_create`]. Such constructor is provided via /// [`Family::new_with_constructor`]. /// /// This is mostly used when creating histograms using constructors that need to /// capture variables. /// /// ``` /// # use prometheus_client::metrics::family::{Family, MetricConstructor}; /// # use prometheus_client::metrics::histogram::Histogram; /// struct CustomBuilder { /// buckets: Vec, /// } /// /// impl MetricConstructor for CustomBuilder { /// fn new_metric(&self) -> Histogram { /// // When a new histogram is created, this function will be called. /// Histogram::new(self.buckets.iter().cloned()) /// } /// } /// /// let custom_builder = CustomBuilder { buckets: vec![0.0, 10.0, 100.0] }; /// let metric = Family::<(), Histogram, CustomBuilder>::new_with_constructor(custom_builder); /// ``` pub trait MetricConstructor { /// Create a new instance of the metric type. fn new_metric(&self) -> M; } /// In cases in which the explicit type of the metric is not required, it is /// posible to directly provide a closure even if it captures variables. /// /// ``` /// # use prometheus_client::metrics::family::{Family}; /// # use prometheus_client::metrics::histogram::Histogram; /// let custom_buckets = [0.0, 10.0, 100.0]; /// let metric = Family::<(), Histogram, _>::new_with_constructor(|| { /// Histogram::new(custom_buckets.into_iter()) /// }); /// # metric.get_or_create(&()); /// ``` impl M> MetricConstructor for F { fn new_metric(&self) -> M { self() } } impl Default for Family { fn default() -> Self { Self { metrics: Arc::new(RwLock::new(Default::default())), constructor: M::default, } } } impl Family { /// Create a metric family using a custom constructor to construct new /// metrics. /// /// When calling [`Family::get_or_create`] a [`Family`] needs to be able to /// construct a new metric in case none exists for the given label set. In /// most cases, e.g. for [`Counter`](crate::metrics::counter::Counter) /// [`Family`] can just use the [`Default::default`] implementation for the /// metric type. For metric types such as /// [`Histogram`](crate::metrics::histogram::Histogram) one might want /// [`Family`] to construct a /// [`Histogram`](crate::metrics::histogram::Histogram) with custom buckets /// (see example below). For such case one can use this method. For more /// involved constructors see [`MetricConstructor`]. /// /// ``` /// # use prometheus_client::metrics::family::Family; /// # use prometheus_client::metrics::histogram::{exponential_buckets, Histogram}; /// Family::, Histogram>::new_with_constructor(|| { /// Histogram::new(exponential_buckets(1.0, 2.0, 10)) /// }); /// ``` pub fn new_with_constructor(constructor: C) -> Self { Self { metrics: Arc::new(RwLock::new(Default::default())), constructor, } } } impl> Family { /// Access a metric with the given label set, creating it if one does not /// yet exist. /// /// ``` /// # use prometheus_client::metrics::counter::{Atomic, Counter}; /// # use prometheus_client::metrics::family::Family; /// # /// let family = Family::, Counter>::default(); /// /// // Will create the metric with label `method="GET"` on first call and /// // return a reference. /// family.get_or_create(&vec![("method".to_owned(), "GET".to_owned())]).inc(); /// /// // Will return a reference to the existing metric on all subsequent /// // calls. /// family.get_or_create(&vec![("method".to_owned(), "GET".to_owned())]).inc(); /// ``` pub fn get_or_create(&self, label_set: &S) -> MappedRwLockReadGuard { if let Ok(metric) = RwLockReadGuard::try_map(self.metrics.read(), |metrics| metrics.get(label_set)) { return metric; } let mut write_guard = self.metrics.write(); write_guard .entry(label_set.clone()) .or_insert_with(|| self.constructor.new_metric()); let read_guard = RwLockWriteGuard::downgrade(write_guard); RwLockReadGuard::map(read_guard, |metrics| { metrics .get(label_set) .expect("Metric to exist after creating it.") }) } /// Remove a label set from the metric family. /// /// Returns a bool indicating if a label set was removed or not. /// /// ``` /// # use prometheus_client::metrics::counter::{Atomic, Counter}; /// # use prometheus_client::metrics::family::Family; /// # /// let family = Family::, Counter>::default(); /// /// // Will create the metric with label `method="GET"` on first call and /// // return a reference. /// family.get_or_create(&vec![("method".to_owned(), "GET".to_owned())]).inc(); /// /// // Will return `true`, indicating that the `method="GET"` label set was /// // removed. /// assert!(family.remove(&vec![("method".to_owned(), "GET".to_owned())])); /// ``` pub fn remove(&self, label_set: &S) -> bool { self.metrics.write().remove(label_set).is_some() } /// Clear all label sets from the metric family. /// /// ``` /// # use prometheus_client::metrics::counter::{Atomic, Counter}; /// # use prometheus_client::metrics::family::Family; /// # /// let family = Family::, Counter>::default(); /// /// // Will create the metric with label `method="GET"` on first call and /// // return a reference. /// family.get_or_create(&vec![("method".to_owned(), "GET".to_owned())]).inc(); /// /// // Clear the family of all label sets. /// family.clear(); /// ``` pub fn clear(&self) { self.metrics.write().clear() } pub(crate) fn read(&self) -> RwLockReadGuard> { self.metrics.read() } } impl Clone for Family { fn clone(&self) -> Self { Family { metrics: self.metrics.clone(), constructor: self.constructor.clone(), } } } impl TypedMetric for Family { const TYPE: MetricType = ::TYPE; } impl EncodeMetric for Family where S: Clone + std::hash::Hash + Eq + EncodeLabelSet, M: EncodeMetric + TypedMetric, C: MetricConstructor, { fn encode(&self, mut encoder: MetricEncoder) -> Result<(), std::fmt::Error> { let guard = self.read(); for (label_set, m) in guard.iter() { let encoder = encoder.encode_family(label_set)?; m.encode(encoder)?; } Ok(()) } fn metric_type(&self) -> MetricType { M::TYPE } } #[cfg(test)] mod tests { use super::*; use crate::metrics::counter::Counter; use crate::metrics::histogram::{exponential_buckets, Histogram}; #[test] fn counter_family() { let family = Family::, Counter>::default(); family .get_or_create(&vec![("method".to_string(), "GET".to_string())]) .inc(); assert_eq!( 1, family .get_or_create(&vec![("method".to_string(), "GET".to_string())]) .get() ); } #[test] fn histogram_family() { Family::<(), Histogram>::new_with_constructor(|| { Histogram::new(exponential_buckets(1.0, 2.0, 10)) }); } #[test] fn histogram_family_with_struct_constructor() { struct CustomBuilder { custom_start: f64, } impl MetricConstructor for CustomBuilder { fn new_metric(&self) -> Histogram { Histogram::new(exponential_buckets(self.custom_start, 2.0, 10)) } } let custom_builder = CustomBuilder { custom_start: 1.0 }; Family::<(), Histogram, CustomBuilder>::new_with_constructor(custom_builder); } #[test] fn counter_family_remove() { let family = Family::, Counter>::default(); family .get_or_create(&vec![("method".to_string(), "GET".to_string())]) .inc(); assert_eq!( 1, family .get_or_create(&vec![("method".to_string(), "GET".to_string())]) .get() ); family .get_or_create(&vec![("method".to_string(), "POST".to_string())]) .inc_by(2); assert_eq!( 2, family .get_or_create(&vec![("method".to_string(), "POST".to_string())]) .get() ); // Attempt to remove it twice, showing it really was removed on the // first attempt. assert!(family.remove(&vec![("method".to_string(), "POST".to_string())])); assert!(!family.remove(&vec![("method".to_string(), "POST".to_string())])); // This should make a new POST label. family .get_or_create(&vec![("method".to_string(), "POST".to_string())]) .inc(); assert_eq!( 1, family .get_or_create(&vec![("method".to_string(), "POST".to_string())]) .get() ); // GET label should have be untouched. assert_eq!( 1, family .get_or_create(&vec![("method".to_string(), "GET".to_string())]) .get() ); } #[test] fn counter_family_clear() { let family = Family::, Counter>::default(); // Create a label and check it. family .get_or_create(&vec![("method".to_string(), "GET".to_string())]) .inc(); assert_eq!( 1, family .get_or_create(&vec![("method".to_string(), "GET".to_string())]) .get() ); // Clear it, then try recreating and checking it again. family.clear(); family .get_or_create(&vec![("method".to_string(), "GET".to_string())]) .inc(); assert_eq!( 1, family .get_or_create(&vec![("method".to_string(), "GET".to_string())]) .get() ); } } prometheus-client-0.22.2/src/metrics/gauge.rs000064400000000000000000000173571046102023000172660ustar 00000000000000//! Module implementing an Open Metrics gauge. //! //! See [`Gauge`] for details. use crate::encoding::{EncodeGaugeValue, EncodeMetric, MetricEncoder}; use super::{MetricType, TypedMetric}; use std::marker::PhantomData; use std::sync::atomic::{AtomicI32, AtomicU32, Ordering}; #[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] use std::sync::atomic::{AtomicI64, AtomicU64}; use std::sync::Arc; /// Open Metrics [`Gauge`] to record current measurements. /// /// Single increasing, decreasing or constant value metric. /// /// [`Gauge`] is generic over the actual data type tracking the [`Gauge`] state /// as well as the data type used to interact with the [`Gauge`]. Out of /// convenience the generic type parameters are set to use an [`AtomicI64`] as a /// storage and [`i64`] on the interface by default. /// /// # Examples /// /// ## Using [`AtomicI64`] as storage and [`i64`] on the interface /// /// ``` /// # use prometheus_client::metrics::gauge::Gauge; /// let gauge: Gauge = Gauge::default(); /// gauge.set(42); /// let _value = gauge.get(); /// ``` /// /// ## Using [`AtomicU64`] as storage and [`f64`] on the interface /// /// ``` /// # use prometheus_client::metrics::gauge::Gauge; /// # use std::sync::atomic::AtomicU64; /// let gauge = Gauge::::default(); /// gauge.set(42.0); /// let _value: f64 = gauge.get(); /// ``` #[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] #[derive(Debug)] pub struct Gauge { value: Arc, phantom: PhantomData, } /// Open Metrics [`Gauge`] to record current measurements. #[cfg(any(target_arch = "mips", target_arch = "powerpc"))] #[derive(Debug)] pub struct Gauge { value: Arc, phantom: PhantomData, } impl Clone for Gauge { fn clone(&self) -> Self { Self { value: self.value.clone(), phantom: PhantomData, } } } impl Default for Gauge { fn default() -> Self { Self { value: Arc::new(A::default()), phantom: PhantomData, } } } impl> Gauge { /// Increase the [`Gauge`] by 1, returning the previous value. pub fn inc(&self) -> N { self.value.inc() } /// Increase the [`Gauge`] by `v`, returning the previous value. pub fn inc_by(&self, v: N) -> N { self.value.inc_by(v) } /// Decrease the [`Gauge`] by 1, returning the previous value. pub fn dec(&self) -> N { self.value.dec() } /// Decrease the [`Gauge`] by `v`, returning the previous value. pub fn dec_by(&self, v: N) -> N { self.value.dec_by(v) } /// Sets the [`Gauge`] to `v`, returning the previous value. pub fn set(&self, v: N) -> N { self.value.set(v) } /// Get the current value of the [`Gauge`]. pub fn get(&self) -> N { self.value.get() } /// Exposes the inner atomic type of the [`Gauge`]. /// /// This should only be used for advanced use-cases which are not directly /// supported by the library. pub fn inner(&self) -> &A { &self.value } } /// Atomic operations for a [`Gauge`] value store. pub trait Atomic { /// Increase the value by `1`. fn inc(&self) -> N; /// Increase the value. fn inc_by(&self, v: N) -> N; /// Decrease the value by `1`. fn dec(&self) -> N; /// Decrease the value. fn dec_by(&self, v: N) -> N; /// Set the value. fn set(&self, v: N) -> N; /// Get the value. fn get(&self) -> N; } impl Atomic for AtomicI32 { fn inc(&self) -> i32 { self.inc_by(1) } fn inc_by(&self, v: i32) -> i32 { self.fetch_add(v, Ordering::Relaxed) } fn dec(&self) -> i32 { self.dec_by(1) } fn dec_by(&self, v: i32) -> i32 { self.fetch_sub(v, Ordering::Relaxed) } fn set(&self, v: i32) -> i32 { self.swap(v, Ordering::Relaxed) } fn get(&self) -> i32 { self.load(Ordering::Relaxed) } } impl Atomic for AtomicU32 { fn inc(&self) -> u32 { self.inc_by(1) } fn inc_by(&self, v: u32) -> u32 { self.fetch_add(v, Ordering::Relaxed) } fn dec(&self) -> u32 { self.dec_by(1) } fn dec_by(&self, v: u32) -> u32 { self.fetch_sub(v, Ordering::Relaxed) } fn set(&self, v: u32) -> u32 { self.swap(v, Ordering::Relaxed) } fn get(&self) -> u32 { self.load(Ordering::Relaxed) } } #[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] impl Atomic for AtomicI64 { fn inc(&self) -> i64 { self.inc_by(1) } fn inc_by(&self, v: i64) -> i64 { self.fetch_add(v, Ordering::Relaxed) } fn dec(&self) -> i64 { self.dec_by(1) } fn dec_by(&self, v: i64) -> i64 { self.fetch_sub(v, Ordering::Relaxed) } fn set(&self, v: i64) -> i64 { self.swap(v, Ordering::Relaxed) } fn get(&self) -> i64 { self.load(Ordering::Relaxed) } } #[cfg(not(any(target_arch = "mips", target_arch = "powerpc")))] impl Atomic for AtomicU64 { fn inc(&self) -> f64 { self.inc_by(1.0) } fn inc_by(&self, v: f64) -> f64 { let mut old_u64 = self.load(Ordering::Relaxed); let mut old_f64; loop { old_f64 = f64::from_bits(old_u64); let new = f64::to_bits(old_f64 + v); match self.compare_exchange_weak(old_u64, new, Ordering::Relaxed, Ordering::Relaxed) { Ok(_) => break, Err(x) => old_u64 = x, } } old_f64 } fn dec(&self) -> f64 { self.dec_by(1.0) } fn dec_by(&self, v: f64) -> f64 { let mut old_u64 = self.load(Ordering::Relaxed); let mut old_f64; loop { old_f64 = f64::from_bits(old_u64); let new = f64::to_bits(old_f64 - v); match self.compare_exchange_weak(old_u64, new, Ordering::Relaxed, Ordering::Relaxed) { Ok(_) => break, Err(x) => old_u64 = x, } } old_f64 } fn set(&self, v: f64) -> f64 { f64::from_bits(self.swap(f64::to_bits(v), Ordering::Relaxed)) } fn get(&self) -> f64 { f64::from_bits(self.load(Ordering::Relaxed)) } } impl TypedMetric for Gauge { const TYPE: MetricType = MetricType::Gauge; } impl EncodeMetric for Gauge where N: EncodeGaugeValue, A: Atomic, { fn encode(&self, mut encoder: MetricEncoder) -> Result<(), std::fmt::Error> { encoder.encode_gauge(&self.get()) } fn metric_type(&self) -> MetricType { Self::TYPE } } /// As a [`Gauge`], but constant, meaning it cannot change once created. /// /// Needed for advanced use-cases, e.g. in combination with [`Collector`](crate::collector::Collector). #[derive(Debug, Default)] pub struct ConstGauge { value: N, } impl ConstGauge { /// Creates a new [`ConstGauge`]. pub fn new(value: N) -> Self { Self { value } } } impl TypedMetric for ConstGauge { const TYPE: MetricType = MetricType::Gauge; } impl EncodeMetric for ConstGauge where N: EncodeGaugeValue, { fn encode(&self, mut encoder: MetricEncoder) -> Result<(), std::fmt::Error> { encoder.encode_gauge(&self.value) } fn metric_type(&self) -> MetricType { Self::TYPE } } #[cfg(test)] mod tests { use super::*; #[test] fn inc_dec_and_get() { let gauge: Gauge = Gauge::default(); assert_eq!(0, gauge.inc()); assert_eq!(1, gauge.get()); assert_eq!(1, gauge.dec()); assert_eq!(0, gauge.get()); assert_eq!(0, gauge.set(10)); assert_eq!(10, gauge.get()); } } prometheus-client-0.22.2/src/metrics/histogram.rs000064400000000000000000000115531046102023000201630ustar 00000000000000//! Module implementing an Open Metrics histogram. //! //! See [`Histogram`] for details. use crate::encoding::{EncodeMetric, MetricEncoder}; use super::{MetricType, TypedMetric}; use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard}; use std::iter::{self, once}; use std::sync::Arc; /// Open Metrics [`Histogram`] to measure distributions of discrete events. /// /// ``` /// # use prometheus_client::metrics::histogram::{Histogram, exponential_buckets}; /// let histogram = Histogram::new(exponential_buckets(1.0, 2.0, 10)); /// histogram.observe(4.2); /// ``` /// /// [`Histogram`] does not implement [`Default`], given that the choice of /// bucket values depends on the situation [`Histogram`] is used in. As an /// example, to measure HTTP request latency, the values suggested in the /// Golang implementation might work for you: /// /// ``` /// # use prometheus_client::metrics::histogram::Histogram; /// // Default values from go client(https://github.com/prometheus/client_golang/blob/5d584e2717ef525673736d72cd1d12e304f243d7/prometheus/histogram.go#L68) /// let custom_buckets = [ /// 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0, /// ]; /// let histogram = Histogram::new(custom_buckets.into_iter()); /// histogram.observe(4.2); /// ``` // TODO: Consider using atomics. See // https://github.com/tikv/rust-prometheus/pull/314. #[derive(Debug)] pub struct Histogram { inner: Arc>, } impl Clone for Histogram { fn clone(&self) -> Self { Histogram { inner: self.inner.clone(), } } } #[derive(Debug)] pub(crate) struct Inner { // TODO: Consider allowing integer observe values. sum: f64, count: u64, // TODO: Consider being generic over the bucket length. buckets: Vec<(f64, u64)>, } impl Histogram { /// Create a new [`Histogram`]. pub fn new(buckets: impl Iterator) -> Self { Self { inner: Arc::new(RwLock::new(Inner { sum: Default::default(), count: Default::default(), buckets: buckets .into_iter() .chain(once(f64::MAX)) .map(|upper_bound| (upper_bound, 0)) .collect(), })), } } /// Observe the given value. pub fn observe(&self, v: f64) { self.observe_and_bucket(v); } /// Observes the given value, returning the index of the first bucket the /// value is added to. /// /// Needed in /// [`HistogramWithExemplars`](crate::metrics::exemplar::HistogramWithExemplars). pub(crate) fn observe_and_bucket(&self, v: f64) -> Option { let mut inner = self.inner.write(); inner.sum += v; inner.count += 1; let first_bucket = inner .buckets .iter_mut() .enumerate() .find(|(_i, (upper_bound, _value))| upper_bound >= &v); match first_bucket { Some((i, (_upper_bound, value))) => { *value += 1; Some(i) } None => None, } } pub(crate) fn get(&self) -> (f64, u64, MappedRwLockReadGuard>) { let inner = self.inner.read(); let sum = inner.sum; let count = inner.count; let buckets = RwLockReadGuard::map(inner, |inner| &inner.buckets); (sum, count, buckets) } } impl TypedMetric for Histogram { const TYPE: MetricType = MetricType::Histogram; } /// Exponential bucket distribution. pub fn exponential_buckets(start: f64, factor: f64, length: u16) -> impl Iterator { iter::repeat(()) .enumerate() .map(move |(i, _)| start * factor.powf(i as f64)) .take(length.into()) } /// Linear bucket distribution. pub fn linear_buckets(start: f64, width: f64, length: u16) -> impl Iterator { iter::repeat(()) .enumerate() .map(move |(i, _)| start + (width * (i as f64))) .take(length.into()) } impl EncodeMetric for Histogram { fn encode(&self, mut encoder: MetricEncoder) -> Result<(), std::fmt::Error> { let (sum, count, buckets) = self.get(); encoder.encode_histogram::<()>(sum, count, &buckets, None) } fn metric_type(&self) -> MetricType { Self::TYPE } } #[cfg(test)] mod tests { use super::*; #[test] fn histogram() { let histogram = Histogram::new(exponential_buckets(1.0, 2.0, 10)); histogram.observe(1.0); } #[test] fn exponential() { assert_eq!( vec![1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0, 512.0], exponential_buckets(1.0, 2.0, 10).collect::>() ); } #[test] fn linear() { assert_eq!( vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0], linear_buckets(0.0, 1.0, 10).collect::>() ); } } prometheus-client-0.22.2/src/metrics/info.rs000064400000000000000000000020041046102023000171100ustar 00000000000000//! Module implementing an Open Metrics info metric. //! //! See [`Info`] for details. use crate::{ encoding::{EncodeLabelSet, EncodeMetric, MetricEncoder}, metrics::{MetricType, TypedMetric}, }; /// Open Metrics [`Info`] metric "to expose textual information which SHOULD NOT /// change during process lifetime". /// /// ``` /// # use prometheus_client::metrics::info::Info; /// /// let _info = Info::new(vec![("os", "GNU/linux")]); /// ``` #[derive(Debug)] pub struct Info(pub(crate) S); impl Info { /// Create [`Info`] metric with the provided label set. pub fn new(label_set: S) -> Self { Self(label_set) } } impl TypedMetric for Info { const TYPE: MetricType = MetricType::Info; } impl EncodeMetric for Info where S: Clone + std::hash::Hash + Eq + EncodeLabelSet, { fn encode(&self, mut encoder: MetricEncoder) -> Result<(), std::fmt::Error> { encoder.encode_info(&self.0) } fn metric_type(&self) -> MetricType { Self::TYPE } } prometheus-client-0.22.2/src/metrics.rs000064400000000000000000000016741046102023000161710ustar 00000000000000//! Metric type implementations. pub mod counter; pub mod exemplar; pub mod family; pub mod gauge; pub mod histogram; pub mod info; /// A metric that is aware of its Open Metrics metric type. pub trait TypedMetric { /// The OpenMetrics metric type. const TYPE: MetricType = MetricType::Unknown; } /// OpenMetrics metric type. #[derive(Clone, Copy, Debug)] #[allow(missing_docs)] pub enum MetricType { Counter, Gauge, Histogram, Info, Unknown, // Not (yet) supported metric types. // // GaugeHistogram, // StateSet, // Summary } impl MetricType { /// Returns the given metric type's str representation. pub fn as_str(&self) -> &str { match self { MetricType::Counter => "counter", MetricType::Gauge => "gauge", MetricType::Histogram => "histogram", MetricType::Info => "info", MetricType::Unknown => "unknown", } } } prometheus-client-0.22.2/src/registry.rs000064400000000000000000000310501046102023000163620ustar 00000000000000//! Metric registry implementation. //! //! See [`Registry`] for details. use std::borrow::Cow; use crate::collector::Collector; use crate::encoding::{DescriptorEncoder, EncodeMetric}; /// A metric registry. /// /// First off one registers metrics with the registry via /// [`Registry::register`]. Later on the [`Registry`] is passed to an encoder /// collecting samples of each metric by iterating all metrics in the /// [`Registry`]. /// /// [`Registry`] is the core building block, generic over the metric type being /// registered. Out of convenience, the generic type parameter is set to use /// dynamic dispatching by default to be able to register different types of /// metrics (e.g. [`Counter`](crate::metrics::counter::Counter) and /// [`Gauge`](crate::metrics::gauge::Gauge)) with the same registry. Advanced /// users might want to use their custom types. /// /// ``` /// # use prometheus_client::encoding::text::encode; /// # use prometheus_client::metrics::counter::{Atomic as _, Counter}; /// # use prometheus_client::metrics::gauge::{Atomic as _, Gauge}; /// # use prometheus_client::registry::Registry; /// # /// // Create a metric registry. /// let mut registry = Registry::default(); /// /// let counter: Counter = Counter::default(); /// let gauge: Gauge = Gauge::default(); /// /// registry.register( /// "my_counter", /// "This is my counter", /// counter.clone(), /// ); /// registry.register( /// "my_gauge", /// "This is my gauge", /// gauge.clone(), /// ); /// /// # // Encode all metrics in the registry in the text format. /// # let mut buffer = String::new(); /// # encode(&mut buffer, ®istry).unwrap(); /// # /// # let expected = "# HELP my_counter This is my counter.\n".to_owned() + /// # "# TYPE my_counter counter\n" + /// # "my_counter_total 0\n" + /// # "# HELP my_gauge This is my gauge.\n" + /// # "# TYPE my_gauge gauge\n" + /// # "my_gauge 0\n" + /// # "# EOF\n"; /// # assert_eq!(expected, buffer); /// ``` #[derive(Debug, Default)] pub struct Registry { prefix: Option, labels: Vec<(Cow<'static, str>, Cow<'static, str>)>, metrics: Vec<(Descriptor, Box)>, collectors: Vec>, sub_registries: Vec, } impl Registry { /// Creates a new default [`Registry`] with the given prefix. pub fn with_prefix(prefix: impl Into) -> Self { Self { prefix: Some(Prefix(prefix.into())), ..Default::default() } } /// Creates a new default [`Registry`] with the given labels. pub fn with_labels( labels: impl Iterator, Cow<'static, str>)>, ) -> Self { Self { labels: labels.into_iter().collect(), ..Default::default() } } /// Creates a new default [`Registry`] with the given prefix and labels. pub fn with_prefix_and_labels( prefix: impl Into, labels: impl Iterator, Cow<'static, str>)>, ) -> Self { Self { prefix: Some(Prefix(prefix.into())), labels: labels.into_iter().collect(), ..Default::default() } } /// Register a metric with the [`Registry`]. /// /// Note: In the Open Metrics text exposition format some metric types have /// a special suffix, e.g. the /// [`Counter`](crate::metrics::counter::Counter`) metric with `_total`. /// These suffixes are inferred through the metric type and must not be /// appended to the metric name manually by the user. /// /// Note: A full stop punctuation mark (`.`) is automatically added to the /// passed help text. /// /// Use [`Registry::register_with_unit`] whenever a unit for the given /// metric is known. /// /// ``` /// # use prometheus_client::metrics::counter::{Atomic as _, Counter}; /// # use prometheus_client::registry::{Registry, Unit}; /// # /// let mut registry = Registry::default(); /// let counter: Counter = Counter::default(); /// /// registry.register("my_counter", "This is my counter", counter.clone()); /// ``` pub fn register, H: Into>( &mut self, name: N, help: H, metric: impl Metric, ) { self.priv_register(name, help, metric, None) } /// Register a metric with the [`Registry`] specifying the metric's unit. /// /// See [`Registry::register`] for additional documentation. /// /// Note: In the Open Metrics text exposition format units are appended to /// the metric name. This is done automatically. Users must not append the /// unit to the name manually. /// /// ``` /// # use prometheus_client::metrics::counter::{Atomic as _, Counter}; /// # use prometheus_client::registry::{Registry, Unit}; /// # /// let mut registry = Registry::default(); /// let counter: Counter = Counter::default(); /// /// registry.register_with_unit( /// "my_counter", /// "This is my counter", /// Unit::Seconds, /// counter.clone(), /// ); /// ``` pub fn register_with_unit, H: Into>( &mut self, name: N, help: H, unit: Unit, metric: impl Metric, ) { self.priv_register(name, help, metric, Some(unit)) } fn priv_register, H: Into>( &mut self, name: N, help: H, metric: impl Metric, unit: Option, ) { let descriptor = Descriptor::new(name, help, unit); self.metrics.push((descriptor, Box::new(metric))); } /// Register a [`Collector`]. /// /// ``` /// # use prometheus_client::metrics::counter::ConstCounter; /// # use prometheus_client::registry::Registry; /// # use prometheus_client::collector::Collector; /// # use prometheus_client::encoding::{DescriptorEncoder, EncodeMetric}; /// # /// #[derive(Debug)] /// struct MyCollector {} /// /// impl Collector for MyCollector { /// fn encode(&self, mut encoder: DescriptorEncoder) -> Result<(), std::fmt::Error> { /// let counter = ConstCounter::new(42); /// let metric_encoder = encoder.encode_descriptor( /// "my_counter", /// "some help", /// None, /// counter.metric_type(), /// )?; /// counter.encode(metric_encoder)?; /// Ok(()) /// } /// } /// /// let my_collector = Box::new(MyCollector{}); /// /// let mut registry = Registry::default(); /// /// registry.register_collector(my_collector); /// ``` pub fn register_collector(&mut self, collector: Box) { self.collectors.push(collector); } /// Create a sub-registry to register metrics with a common prefix. /// /// Say you would like to prefix one set of metrics with `subsystem_a` and /// one set of metrics with `subsystem_b`. Instead of prefixing each metric /// with the corresponding subsystem string individually, you can create two /// sub-registries like demonstrated below. /// /// This can be used to pass a prefixed sub-registry down to a subsystem of /// your architecture automatically adding a prefix to each metric the /// subsystem registers. /// /// ``` /// # use prometheus_client::metrics::counter::{Atomic as _, Counter}; /// # use prometheus_client::registry::{Registry, Unit}; /// # /// let mut registry = Registry::default(); /// /// let subsystem_a_counter_1: Counter = Counter::default(); /// let subsystem_a_counter_2: Counter = Counter::default(); /// /// let subsystem_a_registry = registry.sub_registry_with_prefix("subsystem_a"); /// registry.register("counter_1", "", subsystem_a_counter_1.clone()); /// registry.register("counter_2", "", subsystem_a_counter_2.clone()); /// /// let subsystem_b_counter_1: Counter = Counter::default(); /// let subsystem_b_counter_2: Counter = Counter::default(); /// /// let subsystem_a_registry = registry.sub_registry_with_prefix("subsystem_b"); /// registry.register("counter_1", "", subsystem_b_counter_1.clone()); /// registry.register("counter_2", "", subsystem_b_counter_2.clone()); /// ``` /// /// See [`Registry::sub_registry_with_label`] for the same functionality, /// but namespacing with a label instead of a metric name prefix. pub fn sub_registry_with_prefix>(&mut self, prefix: P) -> &mut Self { let sub_registry = Registry { prefix: Some(Prefix( self.prefix.clone().map(|p| p.0 + "_").unwrap_or_default() + prefix.as_ref(), )), labels: self.labels.clone(), ..Default::default() }; self.priv_sub_registry(sub_registry) } /// Like [`Registry::sub_registry_with_prefix`] but with a label instead. pub fn sub_registry_with_label( &mut self, label: (Cow<'static, str>, Cow<'static, str>), ) -> &mut Self { self.sub_registry_with_labels(std::iter::once(label)) } /// Like [`Registry::sub_registry_with_prefix`] but with multiple labels instead. pub fn sub_registry_with_labels( &mut self, labels: impl Iterator, Cow<'static, str>)>, ) -> &mut Self { let mut new_labels = self.labels.clone(); new_labels.extend(labels); let sub_registry = Registry { prefix: self.prefix.clone(), labels: new_labels, ..Default::default() }; self.priv_sub_registry(sub_registry) } fn priv_sub_registry(&mut self, sub_registry: Self) -> &mut Self { self.sub_registries.push(sub_registry); self.sub_registries .last_mut() .expect("sub_registries not to be empty.") } pub(crate) fn encode(&self, encoder: &mut DescriptorEncoder) -> Result<(), std::fmt::Error> { for (descriptor, metric) in self.metrics.iter() { let mut descriptor_encoder = encoder.with_prefix_and_labels(self.prefix.as_ref(), &self.labels); let metric_encoder = descriptor_encoder.encode_descriptor( &descriptor.name, &descriptor.help, descriptor.unit.as_ref(), EncodeMetric::metric_type(metric.as_ref()), )?; metric.encode(metric_encoder)?; } for collector in self.collectors.iter() { let descriptor_encoder = encoder.with_prefix_and_labels(self.prefix.as_ref(), &self.labels); collector.encode(descriptor_encoder)?; } for registry in self.sub_registries.iter() { registry.encode(encoder)?; } Ok(()) } } /// Metric prefix #[derive(Clone, Debug)] pub(crate) struct Prefix(String); impl Prefix { pub(crate) fn as_str(&self) -> &str { self.0.as_str() } } impl From for Prefix { fn from(s: String) -> Self { Prefix(s) } } /// OpenMetrics metric descriptor. #[derive(Debug, Clone)] struct Descriptor { name: String, help: String, unit: Option, } impl Descriptor { /// Create new [`Descriptor`]. fn new, H: Into>(name: N, help: H, unit: Option) -> Self { Self { name: name.into(), help: help.into() + ".", unit, } } } /// Metric units recommended by Open Metrics. /// /// See [`Unit::Other`] to specify alternative units. #[derive(Debug, Clone)] #[allow(missing_docs)] pub enum Unit { Amperes, Bytes, Celsius, Grams, Joules, Meters, Ratios, Seconds, Volts, Other(String), } impl Unit { /// Returns the given Unit's str representation. pub fn as_str(&self) -> &str { match self { Unit::Amperes => "amperes", Unit::Bytes => "bytes", Unit::Celsius => "celsius", Unit::Grams => "grams", Unit::Joules => "joules", Unit::Meters => "meters", Unit::Ratios => "ratios", Unit::Seconds => "seconds", Unit::Volts => "volts", Unit::Other(other) => other.as_str(), } } } /// Super trait representing an abstract Prometheus metric. pub trait Metric: crate::encoding::EncodeMetric + Send + Sync + std::fmt::Debug + 'static {} impl Metric for T where T: crate::encoding::EncodeMetric + Send + Sync + std::fmt::Debug + 'static {}