metrics_exporter_prometheus/
common.rs1use std::collections::HashMap;
2
3use crate::{distribution::Distribution, PrometheusRecorder};
4
5use crate::formatting::sanitize_metric_name;
6use indexmap::IndexMap;
7use metrics::SetRecorderError;
8use thiserror::Error;
9
10#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
15pub enum Matcher {
16 Full(String),
18 Prefix(String),
20 Suffix(String),
22}
23
24impl Matcher {
25 pub fn matches(&self, key: &str) -> bool {
27 match self {
28 Matcher::Prefix(prefix) => key.starts_with(prefix),
29 Matcher::Suffix(suffix) => key.ends_with(suffix),
30 Matcher::Full(full) => key == full,
31 }
32 }
33
34 pub(crate) fn sanitized(self) -> Matcher {
36 match self {
37 Matcher::Prefix(prefix) => Matcher::Prefix(sanitize_metric_name(prefix.as_str())),
38 Matcher::Suffix(suffix) => Matcher::Suffix(sanitize_metric_name(suffix.as_str())),
39 Matcher::Full(full) => Matcher::Full(sanitize_metric_name(full.as_str())),
40 }
41 }
42}
43
44#[derive(Debug, Error)]
46pub enum BuildError {
47 #[error("failed to create Tokio runtime for exporter: {0}")]
49 FailedToCreateRuntime(String),
50
51 #[error("failed to create HTTP listener: {0}")]
53 FailedToCreateHTTPListener(String),
54
55 #[error("failed to install exporter as global recorder: {0}")]
57 FailedToSetGlobalRecorder(#[from] SetRecorderError<PrometheusRecorder>),
58
59 #[error("failed to parse address as a valid IP address/subnet: {0}")]
61 InvalidAllowlistAddress(String),
62
63 #[error("push gateway endpoint is not valid: {0}")]
65 InvalidPushGatewayEndpoint(String),
66
67 #[error("attempted to build exporter with no exporters enabled; did you disable default features and forget to enable either the `http-listener` or `push-gateway` features?")]
72 MissingExporterConfiguration,
73
74 #[error("bucket bounds/quantiles cannot be empty")]
76 EmptyBucketsOrQuantiles,
77
78 #[error("bucket durations cannot be set to zero")]
80 ZeroBucketDuration,
81}
82
83#[derive(Debug, Clone, PartialEq, Eq, Hash)]
85pub struct LabelSet {
86 pub(crate) labels: Vec<(String, String)>,
87}
88
89impl LabelSet {
90 pub fn from_key_and_global(
92 key: &metrics::Key,
93 global_labels: &IndexMap<String, String>,
94 ) -> Self {
95 let mut labels = global_labels.clone();
96 key.labels().for_each(|label| {
97 labels.insert(label.key().to_string(), label.value().to_string());
98 });
99 Self { labels: labels.into_iter().collect() }
100 }
101
102 pub fn is_empty(&self) -> bool {
104 self.labels.is_empty()
105 }
106
107 pub fn to_strings(&self) -> impl Iterator<Item = String> + '_ {
109 self.labels.iter().map(|(k, v)| {
110 format!(
111 "{}=\"{}\"",
112 crate::formatting::sanitize_label_key(k),
113 crate::formatting::sanitize_label_value(v)
114 )
115 })
116 }
117}
118
119#[derive(Debug)]
120pub struct Snapshot {
121 pub counters: HashMap<String, HashMap<LabelSet, u64>>,
122 pub gauges: HashMap<String, HashMap<LabelSet, f64>>,
123 pub distributions: HashMap<String, IndexMap<LabelSet, Distribution>>,
124}