hyperlight_host/metrics/
int_counter_vec.rs

1/*
2Copyright 2024 The Hyperlight Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17use prometheus::core::{AtomicU64, GenericCounterVec};
18use prometheus::register_int_counter_vec_with_registry;
19use tracing::{instrument, Span};
20
21use super::{
22    get_metric_opts, get_metrics_registry, GetHyperlightMetric, HyperlightMetric,
23    HyperlightMetricOps,
24};
25use crate::{new_error, HyperlightError, Result};
26
27/// A 64-bit counter
28#[derive(Debug)]
29pub struct IntCounterVec {
30    counter: GenericCounterVec<AtomicU64>,
31    /// The name of the counter
32    pub name: &'static str,
33}
34
35impl IntCounterVec {
36    /// Creates a new counter and registers it with the metric registry
37    #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
38    pub fn new(name: &'static str, help: &str, labels: &[&str]) -> Result<Self> {
39        let registry = get_metrics_registry();
40        let opts = get_metric_opts(name, help);
41        let counter = register_int_counter_vec_with_registry!(opts, labels, registry)?;
42        Ok(Self { counter, name })
43    }
44    /// Increments a counter by 1
45    #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
46    pub fn inc(&self, label_vals: &[&str]) -> Result<()> {
47        self.counter.get_metric_with_label_values(label_vals)?.inc();
48        Ok(())
49    }
50    /// Increments a counter by a value
51    #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
52    pub fn inc_by(&self, label_vals: &[&str], val: u64) -> Result<()> {
53        self.counter
54            .get_metric_with_label_values(label_vals)?
55            .inc_by(val);
56        Ok(())
57    }
58    /// Gets the value of a counter
59    #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
60    pub fn get(&self, label_vals: &[&str]) -> Result<u64> {
61        Ok(self.counter.get_metric_with_label_values(label_vals)?.get())
62    }
63    /// Resets a counter
64    #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
65    pub fn reset(&self, label_vals: &[&str]) -> Result<()> {
66        self.counter
67            .get_metric_with_label_values(label_vals)?
68            .reset();
69        Ok(())
70    }
71}
72
73impl<S: HyperlightMetricOps> GetHyperlightMetric<IntCounterVec> for S {
74    #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
75    fn metric(&self) -> Result<&IntCounterVec> {
76        let metric = self.get_metric()?;
77        <&HyperlightMetric as TryInto<&IntCounterVec>>::try_into(metric)
78    }
79}
80
81impl<'a> TryFrom<&'a HyperlightMetric> for &'a IntCounterVec {
82    type Error = HyperlightError;
83    #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
84    fn try_from(metric: &'a HyperlightMetric) -> Result<Self> {
85        match metric {
86            HyperlightMetric::IntCounterVec(counter) => Ok(counter),
87            _ => Err(new_error!("metric is not a IntCounterVec")),
88        }
89    }
90}
91
92impl From<IntCounterVec> for HyperlightMetric {
93    #[instrument(skip_all, parent = Span::current(), level= "Trace")]
94    fn from(counter: IntCounterVec) -> Self {
95        HyperlightMetric::IntCounterVec(counter)
96    }
97}
98
99/// Increments an IntCounterVec by 1 or logs an error if the metric is not found
100#[macro_export]
101macro_rules! int_counter_vec_inc {
102    ($metric:expr, $label_vals:expr) => {{
103        match $crate::metrics::GetHyperlightMetric::<$crate::metrics::IntCounterVec>::metric(
104            $metric,
105        ) {
106            Ok(val) => {
107                if let Err(e) = val.inc($label_vals) {
108                    log::error!(
109                        "error incrementing metric with labels: {} {:?}",
110                        e,
111                        $label_vals
112                    )
113                }
114            }
115            Err(e) => log::error!("error getting metric: {}", e),
116        };
117    }};
118}
119
120/// Increments an IntCounterVec by a value or logs an error if the metric is not found
121#[macro_export]
122macro_rules! int_counter_vec_inc_by {
123    ($metric:expr, $label_vals:expr, $val:expr) => {{
124        match $crate::metrics::GetHyperlightMetric::<$crate::metrics::IntCounterVec>::metric(
125            $metric,
126        ) {
127            Ok(val) => {
128                if let Err(e) = val.inc_by($label_vals, $val) {
129                    log::error!(
130                        "error incrementing metric by {} with labels: {} {:?}",
131                        $val,
132                        e,
133                        $label_vals
134                    )
135                }
136            }
137            Err(e) => log::error!("error getting metric: {}", e),
138        };
139    }};
140}
141
142/// Gets the value of an IntCounterVec or logs an error if the metric is not found
143/// Returns 0 if the metric is not found
144#[macro_export]
145macro_rules! int_counter_vec_get {
146    ($metric:expr, $label_vals:expr) => {{
147        match $crate::metrics::GetHyperlightMetric::<$crate::metrics::IntCounterVec>::metric(
148            $metric,
149        ) {
150            Ok(val) => match val.get($label_vals) {
151                Ok(val) => val,
152                Err(e) => {
153                    log::error!("error getting metric with labels: {} {:?}", e, $label_vals);
154                    0
155                }
156            },
157
158            Err(e) => {
159                log::error!("error getting metric: {}", e);
160                0
161            }
162        }
163    }};
164}
165
166/// Resets an IntCounterVec or logs an error if the metric is not found
167#[macro_export]
168macro_rules! int_counter_vec_reset {
169    ($metric:expr, $label_vals:expr) => {{
170        match $crate::metrics::GetHyperlightMetric::<$crate::metrics::IntCounterVec>::metric(
171            $metric,
172        ) {
173            Ok(val) => {
174                if let Err(e) = val.reset($label_vals) {
175                    log::error!(
176                        "error resetting metric with labels: {} {:?}",
177                        e,
178                        $label_vals
179                    )
180                }
181            }
182            Err(e) => log::error!("error getting metric: {}", e),
183        };
184    }};
185}