prometheus_http_query/
error.rs

1//! All error types that are returned by methods in this crate.
2use serde::Deserialize;
3use std::error::Error as StdError;
4use std::fmt;
5
6/// A global error enum that contains all errors that are returned by this
7/// library. Some errors are wrappers for errors from underlying libraries.
8/// All errors (this enum as well as all contained structs) implement [`std::error::Error`].
9#[non_exhaustive]
10#[derive(Debug)]
11pub enum Error {
12    /// Wraps errors from the underlying [`reqwest::Client`] that cannot be mapped
13    /// to a more specific error type. Deserialization errors also fall into this
14    /// category.
15    Client(ClientError),
16    /// Occurs when Prometheus responds with e.g. HTTP 4xx (e.g. due to a syntax error in a PromQL query).<br>
17    /// Details on the error as reported by Prometheus are included in [`PrometheusError`].
18    Prometheus(PrometheusError),
19    /// Occurs when the [`Client::series`](crate::Client::series) method is called with an empty set of
20    /// series [`Selector`](crate::selector::Selector)s. According to the Prometheus API description at least one
21    /// [`Selector`](crate::selector::Selector) must be provided.
22    EmptySeriesSelector,
23    /// Wraps errors from the [`url`] crate.
24    ParseUrl(ParseUrlError),
25}
26
27impl fmt::Display for Error {
28    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
29        match self {
30            Self::Client(e) => e.fmt(f),
31            Self::Prometheus(e) => e.fmt(f),
32            Self::EmptySeriesSelector => f.write_str("at least one series selector must be provided in order to query the series endpoint"),
33            Self::ParseUrl(e) => e.fmt(f),
34        }
35    }
36}
37
38impl StdError for Error {
39    fn source(&self) -> Option<&(dyn StdError + 'static)> {
40        match self {
41            Self::Client(e) => e.source(),
42            Self::Prometheus(_) => None,
43            Self::EmptySeriesSelector => None,
44            Self::ParseUrl(e) => e.source(),
45        }
46    }
47}
48
49/// This error is thrown when the JSON response's `status` field contains `error`.<br>
50/// The error-related information from the JSON body is included in this error.
51#[derive(Debug, Clone, PartialEq, Deserialize)]
52pub struct PrometheusError {
53    #[serde(alias = "errorType")]
54    pub(crate) error_type: PrometheusErrorType,
55    #[serde(alias = "error")]
56    pub(crate) message: String,
57}
58
59impl StdError for PrometheusError {}
60
61impl fmt::Display for PrometheusError {
62    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63        write!(f, "{}: {}", self.error_type, self.message)
64    }
65}
66
67impl PrometheusError {
68    /// Returns the parsed version of the error type that was given by the Prometheus API.
69    pub fn error_type(&self) -> PrometheusErrorType {
70        self.error_type
71    }
72
73    /// Returns the error message that was given by the Prometheus API.
74    pub fn message(&self) -> &str {
75        &self.message
76    }
77
78    pub fn is_timeout(&self) -> bool {
79        self.error_type == PrometheusErrorType::Timeout
80    }
81
82    pub fn is_canceled(&self) -> bool {
83        self.error_type == PrometheusErrorType::Canceled
84    }
85
86    pub fn is_execution(&self) -> bool {
87        self.error_type == PrometheusErrorType::Execution
88    }
89
90    pub fn is_bad_data(&self) -> bool {
91        self.error_type == PrometheusErrorType::BadData
92    }
93
94    pub fn is_internal(&self) -> bool {
95        self.error_type == PrometheusErrorType::Internal
96    }
97
98    pub fn is_unavailable(&self) -> bool {
99        self.error_type == PrometheusErrorType::Unavailable
100    }
101
102    pub fn is_not_found(&self) -> bool {
103        self.error_type == PrometheusErrorType::NotFound
104    }
105}
106
107/// The parsed error type as returned by the Prometheus API.
108#[non_exhaustive]
109#[derive(Clone, Copy, Debug, Deserialize, PartialEq)]
110pub enum PrometheusErrorType {
111    #[serde(alias = "timeout")]
112    Timeout,
113    #[serde(alias = "canceled")]
114    Canceled,
115    #[serde(alias = "execution")]
116    Execution,
117    #[serde(alias = "bad_data")]
118    BadData,
119    #[serde(alias = "internal")]
120    Internal,
121    #[serde(alias = "unavailable")]
122    Unavailable,
123    #[serde(alias = "not_found")]
124    NotFound,
125}
126
127impl fmt::Display for PrometheusErrorType {
128    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
129        match self {
130            Self::Timeout => f.write_str("timeout"),
131            Self::Canceled => f.write_str("canceled"),
132            Self::Execution => f.write_str("execution"),
133            Self::BadData => f.write_str("bad_data"),
134            Self::Internal => f.write_str("internal"),
135            Self::Unavailable => f.write_str("unavailable"),
136            Self::NotFound => f.write_str("not_found"),
137        }
138    }
139}
140
141/// Is thrown when the [`Client`](crate::Client) or the underlying
142/// [`reqwest::Error`] fail to build or execute a request.
143#[derive(Debug)]
144pub struct ClientError {
145    pub(crate) message: &'static str,
146    pub(crate) source: Option<reqwest::Error>,
147}
148
149impl fmt::Display for ClientError {
150    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
151        f.write_str(&self.message)
152    }
153}
154
155impl StdError for ClientError {
156    fn source(&self) -> Option<&(dyn StdError + 'static)> {
157        self.source.as_ref().map(|e| e as &dyn StdError)
158    }
159}
160
161impl ClientError {
162    /// Obtain the [`reqwest::Error`] that is the actual cause of this
163    /// error or `None` if the error originated in [`Client`](crate::Client)
164    /// itself.<br>
165    pub fn inner(&self) -> Option<&reqwest::Error> {
166        self.source.as_ref()
167    }
168}
169
170/// Is thrown when the URL that is used to instantiate the [`Client`](crate::Client)
171/// is invalid.
172#[derive(Debug)]
173pub struct ParseUrlError {
174    pub(crate) message: &'static str,
175    pub(crate) source: url::ParseError,
176}
177
178impl fmt::Display for ParseUrlError {
179    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
180        f.write_str(&self.message)
181    }
182}
183
184impl StdError for ParseUrlError {
185    fn source(&self) -> Option<&(dyn StdError + 'static)> {
186        Some(&self.source)
187    }
188}
189
190impl ParseUrlError {
191    /// Obtain the [`url::ParseError`] that is the actual cause of this error.
192    pub fn inner(&self) -> &url::ParseError {
193        &self.source
194    }
195}