prometheus_parser/types/
selector.rs

1// (C) Copyright 2019-2020 Hewlett Packard Enterprise Development LP
2
3use std::collections::HashSet;
4use std::fmt;
5use std::iter::FromIterator;
6
7use super::expression::Expression;
8use super::misc::{PromDuration, Span, Subquery};
9use super::return_value::{LabelSetOp, ReturnKind, ReturnValue};
10
11/// Label equality operators
12#[derive(Debug, PartialEq, Eq, Clone, Copy)]
13pub enum LabelOp {
14  Equal,
15  NotEqual,
16  RegexEqual,
17  RegexNotEqual
18}
19
20impl fmt::Display for LabelOp {
21  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
22    write!(f, "{}", match self {
23      LabelOp::Equal => "=",
24      LabelOp::NotEqual => "!=",
25      LabelOp::RegexEqual => "=~",
26      LabelOp::RegexNotEqual => "!~"
27    })
28  }
29}
30
31/// A label matcher in a selector
32#[derive(Debug, PartialEq, Eq, Clone)]
33pub struct Label {
34  pub key: String,
35  pub op: LabelOp,
36  pub value: String,
37  
38  pub span: Option<Span>
39}
40
41impl Label {
42  pub fn new<S: Into<String>>(op: LabelOp, key: S, value: S) -> Self {
43    Label {
44      op,
45      key: key.into(),
46      value: value.into(),
47      span: None
48    }
49  }
50
51  pub fn equal<S: Into<String>>(key: S, value: S) -> Self {
52    Label::new(LabelOp::Equal, key, value)
53  }
54
55  pub fn not_equal<S: Into<String>>(key: S, value: S) -> Self {
56    Label::new(LabelOp::NotEqual, key, value)
57  }
58
59  pub fn regex_equal<S: Into<String>>(key: S, value: S) -> Self {
60    Label::new(LabelOp::RegexEqual, key, value)
61  }
62
63  pub fn regex_notequal<S: Into<String>>(key: S, value: S) -> Self {
64    Label::new(LabelOp::RegexNotEqual, key, value)
65  }
66
67  pub fn key<S: Into<String>>(mut self, key: S) -> Self {
68    self.key = key.into();
69    self
70  }
71
72  pub fn op(mut self, op: LabelOp) -> Self {
73    self.op = op;
74    self
75  }
76
77  pub fn value<S: Into<String>>(mut self, value: S) -> Self {
78    self.value = value.into();
79    self
80  }
81
82  pub fn span<S: Into<Span>>(mut self, span: S) -> Self {
83    self.span = Some(span.into());
84    self
85  }
86}
87
88impl fmt::Display for Label {
89  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90    write!(f, "{}{}{:?}", self.key, self.op, self.value)
91  }
92}
93
94/// A Selector that retrieves time series data from Prometheus
95#[derive(Debug, PartialEq, Eq, Clone, Default)]
96pub struct Selector {
97  pub metric: Option<String>,
98  pub labels: Vec<Label>,
99  pub range: Option<PromDuration>,
100  pub offset: Option<PromDuration>,
101  pub subquery: Option<Subquery>,
102
103  pub span: Option<Span>
104}
105
106impl Selector {
107  pub fn new() -> Self {
108    Selector {
109      metric: None,
110      labels: vec![],
111      range: None,
112      offset: None,
113      subquery: None,
114      span: None
115    }
116  }
117
118  /// Sets or replaces this Selector's metric
119  pub fn metric<S: Into<String>>(mut self, metric: S) -> Self {
120    self.metric = Some(metric.into());
121    self
122  }
123
124  /// Clears this Selector's metric
125  pub fn clear_metric(mut self) -> Self {
126    self.metric = None;
127    self
128  }
129
130  /// Adds a label to this Selector
131  pub fn label(mut self, label: Label) -> Self {
132    self.labels.push(label);
133    self
134  }
135
136  /// Replaces this Selector's labels with the given set
137  pub fn labels(mut self, labels: Vec<Label>) -> Self {
138    self.labels = labels;
139    self
140  }
141
142  /// Clears this Selector's set of labels
143  pub fn clear_labels(mut self) -> Self {
144    self.labels.clear();
145    self
146  }
147
148  /// Sets or replaces this Selector's range
149  pub fn range(mut self, range: PromDuration) -> Self {
150    self.range = Some(range);
151    self
152  }
153
154  /// Clears this Selector's range
155  pub fn clear_range(mut self) -> Self {
156    self.range = None;
157    self
158  }
159
160  /// Sets or replaces this Selector's offset
161  pub fn offset(mut self, offset: PromDuration) -> Self {
162    self.offset = Some(offset);
163    self
164  }
165
166  pub fn clear_offset(mut self) -> Self {
167    self.offset = None;
168    self
169  }
170
171  pub fn subquery(mut self, subquery: Subquery) -> Self {
172    self.subquery = Some(subquery);
173    self
174  }
175
176  pub fn clear_subquery(mut self) -> Self {
177    self.subquery = None;
178    self
179  }
180
181  pub fn span<S: Into<Span>>(mut self, span: S) -> Self {
182    self.span = Some(span.into());
183    self
184  }
185
186  pub fn wrap(self) -> Expression {
187    Expression::Selector(self)
188  }
189
190  pub fn return_value(&self) -> ReturnValue {
191    let kind = match (self.range.is_some(), self.subquery.is_some()) {
192      (false, false) => ReturnKind::InstantVector,
193      (false, true) => ReturnKind::RangeVector,
194      (true, false) => ReturnKind::RangeVector,
195
196      // range + subquery is not allowed (however this is syntactically invalid)
197      (true, true) => ReturnKind::unknown(
198        "range and subquery are not allowed together",
199        self.clone().wrap()
200      )
201    };
202
203    // if a label is selected, we can infer that it must be present on the
204    // output vector
205    let mut label_ops = Vec::new();
206    if !self.labels.is_empty() {
207      label_ops.push(LabelSetOp::append(
208        self.clone().wrap(),
209        self.span,
210        HashSet::from_iter(self.labels.iter().cloned().map(|l| l.key))
211      ));
212    }
213
214    ReturnValue { kind, label_ops }
215  }
216}
217
218impl fmt::Display for Selector {
219  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
220    if let Some(metric) = &self.metric {
221      write!(f, "{}", metric)?;
222    }
223    
224    if !self.labels.is_empty() {
225      write!(f, "{{")?;
226      for (i, label) in self.labels.iter().enumerate() {
227        if i > 0 {
228          write!(f, ",")?;
229        }
230
231        write!(f, "{}", label)?;
232      }
233
234      write!(f, "}}")?;
235    };
236
237    if let Some(range) = &self.range {
238      write!(f, "[{}]", range)?;
239    }
240
241    if let Some(offset) = &self.offset {
242      write!(f, " offset {}", offset)?;
243    }
244
245    if let Some(subquery) = &self.subquery {
246      write!(f, "{}", subquery)?;
247    }
248
249    Ok(())
250  }
251}