Crates.io | vise |
lib.rs | vise |
version | 0.1.0 |
source | src |
created_at | 2024-07-05 07:00:15.42218 |
updated_at | 2024-07-05 07:00:15.42218 |
description | Typesafe metrics client |
homepage | |
repository | https://github.com/matter-labs/vise |
max_upload_size | |
id | 1292421 |
size | 148,565 |
This library provides a wrapper for defining and reporting metrics in Rust libraries and applications.
It is based on the prometheus-client
library, augmenting it with higher-level / more eloquent functionality.
Metrics are numerical measurements taken over time. Metrics are defined and collected in an application and reported to an external system, Prometheus, from which they can be accessed using e.g. Grafana dashboards.
Prometheus and compatible systems supports 3 main metric types:
Metrics of all types can be supplied with labels. Each set of labels defines a separate metric. Thus, label space should be reasonably small.
Besides these main types, Prometheus and this library support an additional info metric type. It should be used to observe values that do not change during the program lifetime (component configurations, metadata like app version / git commit, etc.). Values for this metric type are encoded as labels. Conceptually, an info metric is similar to a gauge with a constant value 1.
Add this to your Crate.toml:
[dependencies]
vise = "0.1.0"
Metrics are defined as structs, with each field corresponding to a metric or a family of metrics:
use vise::*;
use std::{fmt, time::Duration};
/// Metrics defined by the library or application. A single app / lib can define
/// multiple metric structs.
#[derive(Debug, Metrics)]
#[metrics(prefix = "my_app")]
// ^ Prefix added to all field names to get the final metric name (e.g., `my_app_latencies`).
pub(crate) struct MyMetrics {
/// Simple counter. Doc comments for the fields will be reported
/// as Prometheus metric descriptions.
pub counter: Counter,
/// Integer-valued gauge. Unit will be reported to Prometheus and will influence metric name
/// by adding the corresponding suffix to it (in this case, `_bytes`).
#[metrics(unit = Unit::Bytes)]
pub gauge: Gauge<u64>,
/// Group of histograms with the "method" label.
/// Each `Histogram` or `Family` of `Histogram`s must define buckets; in this case,
/// we use default buckets for latencies.
#[metrics(buckets = Buckets::LATENCIES, labels = ["method"])]
pub latencies: LabeledFamily<&'static str, Histogram<Duration>>,
}
// Commonly, it makes sense to make metrics available using a static:
#[vise::register]
static MY_METRICS: Global<MyMetrics> = Global::new();
// Metrics are singletons globally available using the `instance()` method.
MY_METRICS.counter.inc();
assert_eq!(MY_METRICS.counter.get(), 1); // Useful for testing
let latency = MY_METRICS.latencies[&"test"].start();
// Do some work...
let latency: Duration = latency.observe();
// `latency` can be used in logging etc.
See crate docs for more examples.
Depending on how you report metrics (e.g., whether the global state is used), testing metrics may require refactoring.
See also: Prometheus guidelines
Metrics
derive macro.)_
char._seconds
). This suffix is automatically added to the
metric name if you specify its unit; you must not specify it manually.Family
should have uniform meaning. If a Family
can be documented without going into label specifics,
you're usually on a right track.Suppose we want to report live and total data sizes for RocksDB instances that live in our application. We may want to define:
rocksdb_
prefixdb
and cf
labels specifying the database ID and column family name (the database ID should be globally
unique; column families will probably differ among db
values)Unit::Bytes
(since data sizes are measured in bytes)Thus, we might have the following metrics:
rocksdb_live_data_size_bytes{db="merkle_tree",cf="default"} 123456789
rocksdb_live_data_size_bytes{db="merkle_tree",cf="stale_keys"} 123456
rocksdb_total_data_size_bytes{db="merkle_tree",cf="default"} 130000000
rocksdb_total_data_size_bytes{db="merkle_tree",cf="stale_keys"} 130000
Distributed under the terms of either
at your option.