8 个不稳定版本 (3 个破坏性更新)
使用旧版Rust 2015
0.5.1 | 2021年1月8日 |
---|---|
0.5.0 | 2020年12月14日 |
0.4.0 | 2020年8月17日 |
0.2.0 | 2019年8月21日 |
0.1.4 | 2018年6月20日 |
#245 in 过程宏
12,902 每月下载量
在 34 个库中(直接使用6个) 使用
64KB
1.5K SLoC
prometheus-static-metric
用于为 rust-prometheus 库构建静态度量的实用宏。
为什么?
MetricVec
(即 CounterVec
、GaugeVec
或 HistogramVec
)较慢。然而,如果已知标签的所有可能值,则 MetricVec
中的每个度量都可以被缓存,以避免运行时成本。
例如,以下代码在多次调用时可能较慢
some_counter_vec.with_label_values(&["label_1_foo", "label_2_bar"]).inc();
这是因为我们每次根据值检索特定的 Counter
,为了确保线程安全,在锁内部进行操作,这使情况变得更糟。
我们可以通过按标签值缓存计数器来优化它
// init before hand
let foo_bar_counter = some_counter.with_label_values(&["label_1_foo", "label_2_bar"]);
foo_bar_counter.inc();
到目前为止,一切看起来都很好。我们实现了与 Counter
相同的性能,对于 CounterVec
。但如果有很多标签,并且每个标签都有很多值怎么办?我们需要手工编写大量的代码来实现这一点。
这正是这个库解决的问题。这个库提供了一个宏,帮助您在不引入大量模板代码的情况下执行上述优化。
入门
-
添加到
Cargo.toml
[dependencies] prometheus-static-metric = "0.4"
-
添加到
lib.rs
extern crate prometheus_static_metric;
示例
使用 make_static_metric!
定义每个标签的所有可能值。您的定义将被扩展为一个真实的 struct
,以便于访问,同时保持高性能。
use prometheus_static_metric::make_static_metric;
make_static_metric! {
pub struct MyStaticCounterVec: Counter {
"method" => {
post,
get,
put,
delete,
},
"product" => {
foo,
bar,
},
}
}
fn main() {
let vec = CounterVec::new(Opts::new("foo", "bar"), &["method", "product"]).unwrap();
let static_counter_vec = MyStaticCounterVec::from(&vec);
static_counter_vec.post.foo.inc();
static_counter_vec.delete.bar.inc_by(4.0);
assert_eq!(static_counter_vec.post.bar.get(), 0.0);
assert_eq!(vec.with_label_values(&["post", "foo"]).get(), 1.0);
assert_eq!(vec.with_label_values(&["delete", "bar"]).get(), 4.0);
}
自动刷新的本地线程指标
对于全局共享静态指标可能效率不足的重型场景,您可以使用 make_auto_flush_static_metric!
宏,该宏将数据存储在本地线程存储中,并自定义刷新到全局 MetricVec
的速率。
#[macro_use]
extern crate lazy_static;
extern crate prometheus;
extern crate prometheus_static_metric;
use prometheus::*;
use prometheus_static_metric::auto_flush_from;
use prometheus_static_metric::make_auto_flush_static_metric;
make_auto_flush_static_metric! {
pub label_enum FooBar {
foo,
bar,
}
pub label_enum Methods {
post,
get,
put,
delete,
}
pub struct Lhrs: LocalIntCounter {
"product" => FooBar,
"method" => Methods,
"version" => {
http1: "HTTP/1",
http2: "HTTP/2",
},
}
}
lazy_static! {
pub static ref HTTP_COUNTER_VEC: IntCounterVec =
register_int_counter_vec ! (
"http_requests_total",
"Number of HTTP requests.",
& ["product", "method", "version"] // it doesn't matter for the label order
).unwrap();
}
lazy_static! {
// You can also use default flush duration which is 1 second.
// pub static ref TLS_HTTP_COUNTER: Lhrs = auto_flush_from!(HTTP_COUNTER_VEC, Lhrs);
pub static ref TLS_HTTP_COUNTER: Lhrs = auto_flush_from!(HTTP_COUNTER_VEC, Lhrs, std::time::Duration::from_secs(1));
}
fn main() {
TLS_HTTP_COUNTER.foo.post.http1.inc();
TLS_HTTP_COUNTER.foo.post.http1.inc();
assert_eq!(
HTTP_COUNTER_VEC
.with_label_values(&["foo", "post", "HTTP/1"])
.get(),
0
);
::std::thread::sleep(::std::time::Duration::from_secs(2));
TLS_HTTP_COUNTER.foo.post.http1.inc();
assert_eq!(
HTTP_COUNTER_VEC
.with_label_values(&["foo", "post", "HTTP/1"])
.get(),
3
);
}
请查看 示例目录 以获取更多信息。
依赖项
~1.5MB
~35K SLoC