prometheus_http_client/
messages.rs1use crate::Error;
30use chrono::{DateTime, Utc};
31use serde::{Deserialize, Deserializer, de::DeserializeOwned};
32use std::{
33 collections::HashMap,
34 fmt::{self, Debug, Display},
35};
36use tracing::warn;
37
38#[derive(Clone, Copy, Debug)]
40pub struct MetricVal(pub f64);
41
42impl Display for MetricVal {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 Display::fmt(&self.0, f)
45 }
46}
47
48impl AsRef<f64> for MetricVal {
49 fn as_ref(&self) -> &f64 {
50 &self.0
51 }
52}
53
54impl<'de> Deserialize<'de> for MetricVal {
55 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
56 where
57 D: Deserializer<'de>,
58 {
59 let s = <&str>::deserialize(deserializer)?;
60 s.parse::<f64>()
61 .map(MetricVal)
62 .map_err(serde::de::Error::custom)
63 }
64}
65
66#[derive(Clone, Debug, Deserialize)]
68#[serde(bound = "KV: DeserializeOwned")]
69pub struct MetricValue<KV = HashMap<String, String>>
70where
71 KV: Clone + Debug,
72{
73 pub metric: KV,
75 #[serde(default)]
77 pub value: Option<(f64, MetricVal)>,
78 }
80
81#[derive(Clone, Debug, Deserialize)]
83#[serde(bound = "KV: DeserializeOwned")]
84pub struct MetricTimeseries<KV = HashMap<String, String>>
85where
86 KV: Clone + Debug,
87{
88 pub metric: KV,
90 #[serde(default)]
92 pub values: Vec<(f64, MetricVal)>,
93 }
95
96#[derive(Clone, Debug, Deserialize)]
98#[serde(bound = "KV: DeserializeOwned")]
99#[serde(tag = "resultType", content = "result", rename_all = "camelCase")]
100pub enum PromData<KV = HashMap<String, String>>
101where
102 KV: Clone + Debug,
103{
104 Matrix(Vec<MetricTimeseries<KV>>),
106 Vector(Vec<MetricValue<KV>>),
108}
109
110impl<KV> PromData<KV>
111where
112 KV: Clone + Debug,
113{
114 pub fn into_matrix(self) -> Result<Vec<MetricTimeseries<KV>>, Error> {
116 match self {
117 Self::Matrix(data) => Ok(data),
118 _ => Err(Error::UnexpectedResultType(format!("{self:?}"))),
119 }
120 }
121
122 pub fn into_vector(self) -> Result<Vec<MetricValue<KV>>, Error> {
124 match self {
125 Self::Vector(data) => Ok(data),
126 _ => Err(Error::UnexpectedResultType(format!("{self:?}"))),
127 }
128 }
129}
130
131#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
132#[serde(rename_all = "camelCase")]
133pub(crate) enum Status {
134 Success,
135 Error,
136}
137
138#[derive(Clone, Debug, Deserialize)]
139#[serde(bound = "T: DeserializeOwned", rename_all = "camelCase")]
140pub(crate) struct PromResponse<T>
141where
142 T: Clone + Debug,
143{
144 pub status: Status,
145 #[serde(default)]
146 pub data: Option<T>,
147 #[serde(default)]
148 pub error_type: Option<String>,
149 #[serde(default)]
150 pub error: Option<String>,
151 #[serde(default)]
152 pub warnings: Vec<String>,
153}
154
155impl<T> PromResponse<T>
156where
157 T: Clone + Debug,
158{
159 pub fn into_result(self) -> Result<T, Error> {
160 for warning in self.warnings {
161 warn!("Prometheus API response: {warning}");
162 }
163
164 match self.status {
165 Status::Success => Ok(self.data.ok_or(Error::MissingData)?),
166 Status::Error => Err(Error::API(
167 self.error_type.unwrap_or_default(),
168 self.error.unwrap_or_default(),
169 )),
170 }
171 }
172}
173
174#[derive(Clone, Debug, Deserialize)]
176#[serde(bound = "KV: DeserializeOwned")]
177pub struct AlertsResponse<KV = HashMap<String, String>>
178where
179 KV: Clone + Debug,
180{
181 pub alerts: Vec<AlertInfo<KV>>,
183}
184
185#[derive(Clone, Debug, Deserialize)]
187#[serde(bound = "KV: DeserializeOwned", rename_all = "camelCase")]
188pub struct AlertInfo<KV = HashMap<String, String>>
189where
190 KV: Clone + Debug,
191{
192 pub active_at: DateTime<Utc>,
194 pub annotations: KV,
196 pub labels: KV,
198 pub state: AlertStatus,
200 pub value: String,
202}
203
204#[derive(Clone, Copy, Debug, Deserialize)]
206#[serde(rename_all = "snake_case")]
207pub enum AlertStatus {
208 Pending,
210 Firing,
212 Resolved,
214}