1use std::sync::LazyLock;
5
6#[doc(hidden)]
8pub use linera_base::prometheus_util::{self, exponential_bucket_latencies};
9use prometheus::IntCounterVec;
10
11pub fn increment_counter(counter: &LazyLock<IntCounterVec>, struct_name: &str, base_key: &[u8]) {
13 let base_key = hex::encode(base_key);
14 let labels = [struct_name, &base_key];
15 counter.with_label_values(&labels).inc();
16}
17
18linera_base::declare_metrics! {
19 #[doc(hidden)]
21 pub static LOAD_VIEW_LATENCY: prometheus::HistogramVec =
22 prometheus_util::register_histogram_vec(
23 "load_view_latency",
24 "Load view latency in milliseconds",
25 &[],
26 exponential_bucket_latencies(1000.0),
27 );
28
29 #[doc(hidden)]
31 pub static LOAD_VIEW_COUNTER: IntCounterVec =
32 prometheus_util::register_int_counter_vec(
33 "load_view",
34 "The metric counting how often a view is read from storage",
35 &["type", "base_key"],
36 );
37
38 #[doc(hidden)]
40 pub static SAVE_VIEW_COUNTER: IntCounterVec =
41 prometheus_util::register_int_counter_vec(
42 "save_view",
43 "The metric counting how often a view is written from storage",
44 &["type", "base_key"],
45 );
46
47 #[doc(hidden)]
49 pub static SAVE_VIEW_LATENCY: prometheus::HistogramVec =
50 prometheus_util::register_histogram_vec(
51 "save_view_latency",
52 "Save view latency in milliseconds",
53 &["type"],
54 exponential_bucket_latencies(1000.0),
55 );
56}
57
58#[cfg(test)]
59mod tests {
60 #[test]
61 fn label_free_metrics_are_exported_before_their_code_path_runs() {
62 crate::init_metrics();
63
64 let families = prometheus::gather();
65 let contains_keys = families
66 .iter()
67 .find(|family| family.get_name() == "linera_key_value_store_view_contains_keys_latency")
68 .expect("a label-free metric must be exported once init_metrics has run");
69
70 let histogram = contains_keys
71 .get_metric()
72 .first()
73 .expect("registering the vector must also create its single label-free child")
74 .get_histogram();
75 assert_eq!(histogram.get_sample_count(), 0);
76 }
77
78 #[test]
83 fn labelled_metrics_stay_absent_until_a_label_combination_is_observed() {
84 crate::init_metrics();
85
86 let exported = prometheus::gather().iter().any(|family| {
87 family.get_name() == "linera_load_view" && !family.get_metric().is_empty()
88 });
89 assert!(!exported);
90 }
91}