clickhouse_connection_pool/
metrics.rs1use actix_web_prom::{PrometheusMetrics, PrometheusMetricsBuilder};
2use prometheus::{CounterVec, GaugeVec, IntCounter, IntCounterVec, IntGaugeVec, Opts};
3use std::{
4 collections::HashMap,
5 sync::{Arc, RwLock},
6};
7
8#[derive(Debug, thiserror::Error)]
9pub enum Error {
10 #[error(transparent)]
11 Prometheus(#[from] prometheus::Error),
12}
13
14#[derive(Debug, Default, Clone)]
15pub enum Kind {
16 #[default]
17 Default,
18 GaugeVec,
19 CounterVec,
20 IntGaugeVec,
21 IntCounterVec,
22 IntCounter,
23}
24
25#[derive(Debug, Default, Clone)]
26pub struct MetricConfig<'a> {
27 pub kind: Kind,
28 pub name: &'a str,
29 pub help: &'a str,
30 pub label_names: &'a [&'a str],
31}
32
33pub type SharedRegistrar = Arc<Registrar>;
34
35#[derive(Clone)]
37pub struct Registrar {
38 prometheus: Arc<PrometheusMetrics>,
39 int_counters_vecs: Arc<RwLock<HashMap<String, IntCounterVec>>>,
40 int_counters: Arc<RwLock<HashMap<String, IntCounter>>>,
41 int_gauges_vecs: Arc<RwLock<HashMap<String, IntGaugeVec>>>,
42 counters_vecs: Arc<RwLock<HashMap<String, CounterVec>>>,
43 gauges_vecs: Arc<RwLock<HashMap<String, GaugeVec>>>,
44}
45
46impl std::fmt::Debug for Registrar {
47 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48 f.debug_struct("Registrar")
49 .field("prometheus", &format!("{:?}", self.prometheus.registry))
50 .field(
51 "int_counters_vecs",
52 &format!("{:?}", self.int_counters_vecs),
53 )
54 .field("int_gauges_vecs", &format!("{:?}", self.int_gauges_vecs))
55 .field("counters_vecs", &format!("{:?}", self.counters_vecs))
56 .field("gauges_vecs", &format!("{:?}", self.gauges_vecs))
57 .finish()
58 }
59}
60
61impl Default for Registrar {
62 fn default() -> Self {
63 Self {
64 prometheus: Arc::new(PrometheusMetricsBuilder::new("default").build().unwrap()),
65 int_counters_vecs: Default::default(),
66 int_counters: Default::default(),
67 int_gauges_vecs: Default::default(),
68 counters_vecs: Default::default(),
69 gauges_vecs: Default::default(),
70 }
71 }
72}
73
74pub trait Registry {
75 fn with_metric_configs<'a>(&self, metrics: &'a [MetricConfig<'a>]) -> Result<(), Error>;
76 fn with_metric_config<'a>(&self, metric: &'a MetricConfig<'a>) -> Result<(), Error>;
77}
78
79impl Registry for Registrar {
80 fn with_metric_config<'a>(&self, metric: &'a MetricConfig<'a>) -> Result<(), Error> {
81 log::info!(
82 "Attempting to register metric with name {:?} and labels {:?}",
83 metric.name,
84 metric.label_names
85 );
86 match &metric.kind {
87 Kind::Default => panic!("Registrar metric kind is `default`, so panicking."),
88 Kind::GaugeVec => {
89 let gauge =
90 GaugeVec::new(Opts::new(metric.name, metric.help), metric.label_names).unwrap();
91 match self.prometheus.registry.register(Box::new(gauge.clone())) {
92 Ok(()) => {
93 self.gauges_vecs
94 .write()
95 .unwrap()
96 .insert(metric.name.to_string(), gauge);
97 Ok(())
98 }
99 Err(e) => {
100 if let prometheus::Error::AlreadyReg = e {
101 log::info!("Metric {:?} is already registered.", metric.name);
102 Ok(())
103 } else {
104 log::error!("Failed to register metric {:?}. {:?}", metric.name, e);
105 Err(Error::Prometheus(e))
106 }
107 }
108 }
109 }
110 Kind::CounterVec => {
111 let counter =
112 CounterVec::new(Opts::new(metric.name, metric.help), metric.label_names)
113 .unwrap();
114 match self.prometheus.registry.register(Box::new(counter.clone())) {
115 Ok(()) => {
116 self.counters_vecs
117 .write()
118 .unwrap()
119 .insert(metric.name.to_string(), counter);
120 Ok(())
121 }
122 Err(e) => {
123 if let prometheus::Error::AlreadyReg = e {
124 log::info!("Metric {:?} is already registered.", metric.name);
125 Ok(())
126 } else {
127 log::error!("Failed to register metric {:?}. {:?}", metric.name, e);
128 Err(Error::Prometheus(e))
129 }
130 }
131 }
132 }
133 Kind::IntGaugeVec => {
134 let gauge =
135 IntGaugeVec::new(Opts::new(metric.name, metric.help), metric.label_names)
136 .unwrap();
137 match self.prometheus.registry.register(Box::new(gauge.clone())) {
138 Ok(()) => {
139 self.int_gauges_vecs
140 .write()
141 .unwrap()
142 .insert(metric.name.to_string(), gauge);
143 Ok(())
144 }
145 Err(e) => {
146 if let prometheus::Error::AlreadyReg = e {
147 log::info!("Metric {:?} is already registered.", metric.name);
148 Ok(())
149 } else {
150 log::error!("Failed to register metric {:?}. {:?}", metric.name, e);
151 Err(Error::Prometheus(e))
152 }
153 }
154 }
155 }
156 Kind::IntCounterVec => {
157 let counter =
158 IntCounterVec::new(Opts::new(metric.name, metric.help), metric.label_names)
159 .unwrap();
160 match self.prometheus.registry.register(Box::new(counter.clone())) {
161 Ok(()) => {
162 self.int_counters_vecs
163 .write()
164 .unwrap()
165 .insert(metric.name.to_string(), counter);
166 Ok(())
167 }
168 Err(e) => {
169 if let prometheus::Error::AlreadyReg = e {
170 log::info!("Metric {:?} is already registered.", metric.name);
171 Ok(())
172 } else {
173 log::error!("Failed to register metric {:?}. {:?}", metric.name, e);
174 Err(Error::Prometheus(e))
175 }
176 }
177 }
178 }
179 Kind::IntCounter => {
180 let counter = IntCounter::new(metric.name, metric.help).unwrap();
181 match self.prometheus.registry.register(Box::new(counter.clone())) {
182 Ok(()) => {
183 self.int_counters
184 .write()
185 .unwrap()
186 .insert(metric.name.to_string(), counter);
187 Ok(())
188 }
189 Err(e) => {
190 if let prometheus::Error::AlreadyReg = e {
191 log::info!("Metric {:?} is already registered.", metric.name);
192 Ok(())
193 } else {
194 log::error!("Failed to register metric {:?}. {:?}", metric.name, e);
195 Err(Error::Prometheus(e))
196 }
197 }
198 }
199 }
200 }
201 }
202 fn with_metric_configs<'a>(&self, metrics: &'a [MetricConfig<'a>]) -> Result<(), Error> {
203 for metric in metrics {
204 match self.with_metric_config(metric) {
205 Ok(()) => (),
206 Err(e) => return Err(e),
207 }
208 }
209 Ok(())
210 }
211}
212
213impl Registrar {
214 pub fn new(prometheus: Arc<PrometheusMetrics>) -> Self {
215 Self {
216 prometheus,
217 ..Default::default()
218 }
219 }
220 pub fn inc_int_counter(&self, key: &str) {
222 let mut counters = self.int_counters.write().unwrap();
223 let counter = match counters.get_mut(key) {
224 Some(r) => r,
225 None => return,
226 };
227
228 counter.inc()
229 }
230 pub fn inc_int_counter_vec_mut(&self, key: &str, labels: &[&str]) {
231 let mut counters = self.int_counters_vecs.write().unwrap();
232 let counter = match counters.get_mut(key) {
233 Some(r) => r,
234 None => return,
235 };
236
237 counter.with_label_values(labels).inc()
238 }
239 pub fn inc_by_int_counter_vec_mut(&self, key: &str, labels: &[&str], value: u64) {
240 let mut counters = self.int_counters_vecs.write().unwrap();
241 let counter = match counters.get_mut(key) {
242 Some(r) => r,
243 None => return,
244 };
245
246 counter.with_label_values(labels).inc_by(value)
247 }
248
249 pub fn set_int_gauge_vec_mut(&self, key: &str, labels: &[&str], value: i64) {
250 let mut gauges = self.int_gauges_vecs.write().unwrap();
251 let gauge = match gauges.get_mut(key) {
252 Some(r) => r,
253 None => return,
254 };
255
256 gauge.with_label_values(labels).set(value)
257 }
258 pub fn inc_counter_vec_mut(&self, key: &str, labels: &[&str]) {
260 let mut counters = self.counters_vecs.write().unwrap();
261 let counter = match counters.get_mut(key) {
262 Some(r) => r,
263 None => return,
264 };
265
266 counter.with_label_values(labels).inc()
267 }
268 pub fn set_gauge_vec_mut(&self, key: &str, labels: &[&str], value: f64) {
269 let mut gauges = self.gauges_vecs.write().unwrap();
270 let gauge = match gauges.get_mut(key) {
271 Some(r) => r,
272 None => return,
273 };
274
275 gauge.with_label_values(labels).set(value)
276 }
277}