1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
use std::error::Error as StdError;
use std::fmt;

/// A global error enum that encapsulates other more specific
/// types of errors.
#[derive(Debug)]
pub enum Error {
    IllegalMetricName,
    InvalidTimeDuration,
    IllegalTimeSeriesSelector,
    InvalidRangeVector,
    Reqwest(reqwest::Error),
    ResponseError(ResponseError),
    UnsupportedQueryResultType(UnsupportedQueryResultType),
    UnknownResponseStatus(UnknownResponseStatus),
    InvalidFunctionArgument(InvalidFunctionArgument),
    UrlParse(url::ParseError),
    ResponseParse(serde_json::Error),
    MissingField,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Self::IllegalMetricName => IllegalMetricNameError.fmt(f),
            Self::InvalidTimeDuration => InvalidTimeDurationError.fmt(f),
            Self::IllegalTimeSeriesSelector => IllegalTimeSeriesSelectorError.fmt(f),
            Self::InvalidRangeVector => InvalidRangeVectorError.fmt(f),
            Self::Reqwest(e) => e.fmt(f),
            Self::ResponseError(e) => e.fmt(f),
            Self::UnsupportedQueryResultType(e) => e.fmt(f),
            Self::UnknownResponseStatus(e) => e.fmt(f),
            Self::InvalidFunctionArgument(e) => e.fmt(f),
            Self::UrlParse(e) => e.fmt(f),
            Self::ResponseParse(e) => e.fmt(f),
            Self::MissingField => MissingFieldError.fmt(f),
        }
    }
}

impl StdError for Error {}

/// This error is thrown when a reserved PromQL keyword is used
/// as metric name in a `Selector`.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct IllegalMetricNameError;

impl fmt::Display for IllegalMetricNameError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "the provided metric name is a reserved PromQL keyword")
    }
}

/// This error is thrown when a time duration is invalidated or empty.<br>
/// See the [Prometheus reference](https://prometheus.io/docs/prometheus/latest/querying/basics/#time-durations)
/// for the correct time duration syntax.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct InvalidTimeDurationError;

impl fmt::Display for InvalidTimeDurationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "the provided time duration is invalid as it does not comply with PromQL time duration syntax")
    }
}

/// This error is thrown when a [Selector] cannot be contructed from the
/// provided metric name and/or the list of labels.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct IllegalTimeSeriesSelectorError;

// error message was shamelessly copied from the PromQL documentation.
impl fmt::Display for IllegalTimeSeriesSelectorError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "vector selectors must either specify a name or at least one label matcher that does not match the empty string")
    }
}

/// This error is thrown when a [RangeVector] cannot be contructed from a
/// given [Selector] configuration, e.g. due to a missing time duration.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct InvalidRangeVectorError;

impl fmt::Display for InvalidRangeVectorError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "range vectors must contain a time duration")
    }
}

/// This error is thrown when the JSON response's `status` field contains `error`.<br>
/// The error-related information in the response is included in this error.
#[derive(Debug, Clone, PartialEq)]
pub struct ResponseError {
    pub kind: String,
    pub message: String,
}

impl fmt::Display for ResponseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "the JSON response contains an error of type {}: {}",
            self.kind, self.message
        )
    }
}

/// This error is thrown when the JSON response's `data.resultType` field contains
/// an unexpected result type.<br>
/// For instant and range queries this is expected to be either `vector` or `matrix`.
#[derive(Debug, Clone, PartialEq)]
pub struct UnsupportedQueryResultType(pub String);

impl fmt::Display for UnsupportedQueryResultType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let UnsupportedQueryResultType(data_type) = self;
        write!(f, "the API returned an unsupported result type, is '{}', must be either 'vector' or 'matrix'", data_type)
    }
}

/// This error is thrown when the JSON response's `status` field contains an
/// unexpected value. As per the Prometheus reference this must be either `success` or `error`.
#[derive(Debug, Clone, PartialEq)]
pub struct UnknownResponseStatus(pub String);

impl fmt::Display for UnknownResponseStatus {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let UnknownResponseStatus(status) = self;
        write!(f, "the API returned an unknown response status , is '{}', must be either 'success' or 'error'", status)
    }
}

/// This error is thrown whenever arguments supplied to [functions] have
/// invalid values and would result in an API error.
#[derive(Debug, Clone, PartialEq)]
pub struct InvalidFunctionArgument {
    pub message: String,
}

impl fmt::Display for InvalidFunctionArgument {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.message)
    }
}

/// This error is thrown when a field is unexpectedly not part of the API response.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct MissingFieldError;

impl fmt::Display for MissingFieldError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "the response cannot be parsed as an expected field is missing"
        )
    }
}