1use crate::label::{Labels, Matchers, METRIC_NAME};
16use crate::parser::token::{
17 self, token_display, T_BOTTOMK, T_COUNT_VALUES, T_END, T_QUANTILE, T_START, T_TOPK,
18};
19use crate::parser::token::{Token, TokenId, TokenType};
20use crate::parser::value::ValueType;
21use crate::parser::{indent, Function, FunctionArgs, Prettier, MAX_CHARACTERS_PER_LINE};
22use crate::util::display_duration;
23use chrono::{DateTime, Utc};
24use std::fmt::{self, Write};
25use std::ops::Neg;
26use std::sync::Arc;
27use std::time::{Duration, SystemTime};
28
29#[derive(Debug, Clone, PartialEq, Eq)]
46pub enum LabelModifier {
47 Include(Labels),
48 Exclude(Labels),
49}
50
51impl LabelModifier {
52 pub fn labels(&self) -> &Labels {
53 match self {
54 LabelModifier::Include(l) => l,
55 LabelModifier::Exclude(l) => l,
56 }
57 }
58
59 pub fn is_include(&self) -> bool {
60 matches!(*self, LabelModifier::Include(_))
61 }
62
63 pub fn include(ls: Vec<&str>) -> Self {
64 Self::Include(Labels::new(ls))
65 }
66
67 pub fn exclude(ls: Vec<&str>) -> Self {
68 Self::Exclude(Labels::new(ls))
69 }
70}
71
72#[derive(Debug, Clone, PartialEq, Eq)]
75#[cfg_attr(feature = "ser", derive(serde::Serialize))]
76#[cfg_attr(feature = "ser", serde(rename_all = "kebab-case"))]
77pub enum VectorMatchCardinality {
78 OneToOne,
79 ManyToOne(Labels),
80 OneToMany(Labels),
81 ManyToMany, }
83
84impl VectorMatchCardinality {
85 pub fn labels(&self) -> Option<&Labels> {
86 match self {
87 VectorMatchCardinality::ManyToOne(l) => Some(l),
88 VectorMatchCardinality::OneToMany(l) => Some(l),
89 VectorMatchCardinality::ManyToMany => None,
90 VectorMatchCardinality::OneToOne => None,
91 }
92 }
93
94 pub fn many_to_one(ls: Vec<&str>) -> Self {
95 Self::ManyToOne(Labels::new(ls))
96 }
97
98 pub fn one_to_many(ls: Vec<&str>) -> Self {
99 Self::OneToMany(Labels::new(ls))
100 }
101}
102
103#[derive(Debug, Clone, PartialEq, Eq)]
105pub struct BinModifier {
106 pub card: VectorMatchCardinality,
109
110 pub matching: Option<LabelModifier>,
113 pub return_bool: bool,
115}
116
117impl fmt::Display for BinModifier {
118 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 let mut s = String::from(self.bool_str());
120
121 if let Some(matching) = &self.matching {
122 match matching {
123 LabelModifier::Include(ls) => write!(s, "on ({ls}) ")?,
124 LabelModifier::Exclude(ls) if !ls.is_empty() => write!(s, "ignoring ({ls}) ")?,
125 _ => (),
126 }
127 }
128
129 match &self.card {
130 VectorMatchCardinality::ManyToOne(ls) => write!(s, "group_left ({ls}) ")?,
131 VectorMatchCardinality::OneToMany(ls) => write!(s, "group_right ({ls}) ")?,
132 _ => (),
133 }
134
135 if s.trim().is_empty() {
136 write!(f, "")
137 } else {
138 write!(f, " {}", s.trim_end()) }
140 }
141}
142
143impl Default for BinModifier {
144 fn default() -> Self {
145 Self {
146 card: VectorMatchCardinality::OneToOne,
147 matching: None,
148 return_bool: false,
149 }
150 }
151}
152
153impl BinModifier {
154 pub fn with_card(mut self, card: VectorMatchCardinality) -> Self {
155 self.card = card;
156 self
157 }
158
159 pub fn with_matching(mut self, matching: Option<LabelModifier>) -> Self {
160 self.matching = matching;
161 self
162 }
163
164 pub fn with_return_bool(mut self, return_bool: bool) -> Self {
165 self.return_bool = return_bool;
166 self
167 }
168
169 pub fn is_labels_joint(&self) -> bool {
170 matches!(
171 (self.card.labels(), &self.matching),
172 (Some(labels), Some(matching)) if labels.is_joint(matching.labels())
173 )
174 }
175
176 pub fn intersect_labels(&self) -> Option<Vec<String>> {
177 if let Some(labels) = self.card.labels() {
178 if let Some(matching) = &self.matching {
179 return Some(labels.intersect(matching.labels()).labels);
180 }
181 };
182 None
183 }
184
185 pub fn is_matching_on(&self) -> bool {
186 matches!(&self.matching, Some(matching) if matching.is_include())
187 }
188
189 pub fn is_matching_labels_not_empty(&self) -> bool {
190 matches!(&self.matching, Some(matching) if !matching.labels().is_empty())
191 }
192
193 pub fn bool_str(&self) -> &str {
194 if self.return_bool {
195 "bool "
196 } else {
197 ""
198 }
199 }
200}
201
202#[cfg(feature = "ser")]
203pub(crate) fn serialize_grouping<S>(
204 this: &Option<LabelModifier>,
205 serializer: S,
206) -> Result<S::Ok, S::Error>
207where
208 S: serde::Serializer,
209{
210 use serde::ser::SerializeMap;
211 let mut map = serializer.serialize_map(Some(2))?;
212 match this {
213 Some(LabelModifier::Include(l)) => {
214 map.serialize_entry("grouping", l)?;
215 map.serialize_entry("without", &false)?;
216 }
217 Some(LabelModifier::Exclude(l)) => {
218 map.serialize_entry("grouping", l)?;
219 map.serialize_entry("without", &true)?;
220 }
221 None => {
222 map.serialize_entry("grouping", &(vec![] as Vec<String>))?;
223 map.serialize_entry("without", &false)?;
224 }
225 }
226
227 map.end()
228}
229
230#[cfg(feature = "ser")]
231pub(crate) fn serialize_bin_modifier<S>(
232 this: &Option<BinModifier>,
233 serializer: S,
234) -> Result<S::Ok, S::Error>
235where
236 S: serde::Serializer,
237{
238 use serde::ser::SerializeMap;
239 use serde_json::json;
240
241 let mut map = serializer.serialize_map(Some(2))?;
242
243 map.serialize_entry(
244 "bool",
245 &this.as_ref().map(|t| t.return_bool).unwrap_or(false),
246 )?;
247 if let Some(t) = this {
248 if let Some(labels) = &t.matching {
249 map.serialize_key("matching")?;
250
251 match labels {
252 LabelModifier::Include(labels) => {
253 let value = json!({
254 "card": t.card,
255 "include": [],
256 "labels": labels,
257 "on": true,
258 });
259 map.serialize_value(&value)?;
260 }
261 LabelModifier::Exclude(labels) => {
262 let value = json!({
263 "card": t.card,
264 "include": [],
265 "labels": labels,
266 "on": false,
267 });
268 map.serialize_value(&value)?;
269 }
270 }
271 } else {
272 let value = json!({
273 "card": t.card,
274 "include": [],
275 "labels": [],
276 "on": false,
277 });
278 map.serialize_entry("matching", &value)?;
279 }
280 } else {
281 map.serialize_entry("matching", &None::<bool>)?;
282 }
283
284 map.end()
285}
286
287#[cfg(feature = "ser")]
288pub(crate) fn serialize_at_modifier<S>(
289 this: &Option<AtModifier>,
290 serializer: S,
291) -> Result<S::Ok, S::Error>
292where
293 S: serde::Serializer,
294{
295 use serde::ser::SerializeMap;
296 let mut map = serializer.serialize_map(Some(2))?;
297 match this {
298 Some(AtModifier::Start) => {
299 map.serialize_entry("startOrEnd", &Some("start"))?;
300 map.serialize_entry("timestamp", &None::<u128>)?;
301 }
302 Some(AtModifier::End) => {
303 map.serialize_entry("startOrEnd", &Some("end"))?;
304 map.serialize_entry("timestamp", &None::<u128>)?;
305 }
306 Some(AtModifier::At(time)) => {
307 map.serialize_entry("startOrEnd", &None::<&str>)?;
308 map.serialize_entry(
309 "timestamp",
310 &time
311 .duration_since(SystemTime::UNIX_EPOCH)
312 .unwrap_or(Duration::ZERO)
313 .as_millis(),
314 )?;
315 }
316 None => {
317 map.serialize_entry("startOrEnd", &None::<&str>)?;
318 map.serialize_entry("timestamp", &None::<u128>)?;
319 }
320 }
321
322 map.end()
323}
324
325#[derive(Debug, Clone, PartialEq, Eq)]
326pub enum Offset {
327 Pos(Duration),
328 Neg(Duration),
329}
330
331impl Offset {
332 #[cfg(feature = "ser")]
333 pub(crate) fn as_millis(&self) -> i128 {
334 match self {
335 Self::Pos(dur) => dur.as_millis() as i128,
336 Self::Neg(dur) => -(dur.as_millis() as i128),
337 }
338 }
339
340 #[cfg(feature = "ser")]
341 pub(crate) fn serialize_offset<S>(
342 offset: &Option<Self>,
343 serializer: S,
344 ) -> Result<S::Ok, S::Error>
345 where
346 S: serde::Serializer,
347 {
348 let value = offset.as_ref().map(|o| o.as_millis()).unwrap_or(0);
349 serializer.serialize_i128(value)
350 }
351}
352
353impl fmt::Display for Offset {
354 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
355 match self {
356 Offset::Pos(dur) => write!(f, "{}", display_duration(dur)),
357 Offset::Neg(dur) => write!(f, "-{}", display_duration(dur)),
358 }
359 }
360}
361
362#[derive(Debug, Clone, PartialEq, Eq)]
363pub enum AtModifier {
364 Start,
365 End,
366 At(SystemTime),
368}
369
370impl fmt::Display for AtModifier {
371 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
372 match self {
373 AtModifier::Start => write!(f, "@ {}()", token_display(T_START)),
374 AtModifier::End => write!(f, "@ {}()", token_display(T_END)),
375 AtModifier::At(time) => {
376 let d = time
377 .duration_since(SystemTime::UNIX_EPOCH)
378 .unwrap_or(Duration::ZERO); write!(f, "@ {:.3}", d.as_secs_f64())
380 }
381 }
382 }
383}
384
385impl TryFrom<TokenId> for AtModifier {
386 type Error = String;
387
388 fn try_from(id: TokenId) -> Result<Self, Self::Error> {
389 match id {
390 T_START => Ok(AtModifier::Start),
391 T_END => Ok(AtModifier::End),
392 _ => Err(format!(
393 "invalid @ modifier preprocessor '{}', START or END is valid.",
394 token::token_display(id)
395 )),
396 }
397 }
398}
399
400impl TryFrom<Token> for AtModifier {
401 type Error = String;
402
403 fn try_from(token: Token) -> Result<Self, Self::Error> {
404 AtModifier::try_from(token.id())
405 }
406}
407
408impl TryFrom<NumberLiteral> for AtModifier {
409 type Error = String;
410
411 fn try_from(num: NumberLiteral) -> Result<Self, Self::Error> {
412 AtModifier::try_from(num.val)
413 }
414}
415
416impl TryFrom<Expr> for AtModifier {
417 type Error = String;
418
419 fn try_from(ex: Expr) -> Result<Self, Self::Error> {
420 match ex {
421 Expr::NumberLiteral(nl) => AtModifier::try_from(nl),
422 _ => Err("invalid float value after @ modifier".into()),
423 }
424 }
425}
426
427impl TryFrom<f64> for AtModifier {
428 type Error = String;
429
430 fn try_from(secs: f64) -> Result<Self, Self::Error> {
431 let err_info = format!("timestamp out of bounds for @ modifier: {secs}");
432
433 if secs.is_nan() || secs.is_infinite() || secs >= f64::MAX || secs <= f64::MIN {
434 return Err(err_info);
435 }
436 let milli = (secs * 1000f64).round().abs() as u64;
437
438 let duration = Duration::from_millis(milli);
439 let mut st = Some(SystemTime::UNIX_EPOCH);
440 if secs.is_sign_positive() {
441 st = SystemTime::UNIX_EPOCH.checked_add(duration);
442 }
443 if secs.is_sign_negative() {
444 st = SystemTime::UNIX_EPOCH.checked_sub(duration);
445 }
446
447 st.map(Self::At).ok_or(err_info)
448 }
449}
450
451#[allow(rustdoc::broken_intra_doc_links)]
454#[derive(Debug, Clone)]
455pub struct EvalStmt {
456 pub expr: Expr,
458
459 pub start: SystemTime,
462 pub end: SystemTime,
463 pub interval: Duration,
465 pub lookback_delta: Duration,
467}
468
469impl fmt::Display for EvalStmt {
470 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
471 write!(
472 f,
473 "[{}] @ [{}, {}, {}, {}]",
474 self.expr,
475 DateTime::<Utc>::from(self.start).to_rfc3339(),
476 DateTime::<Utc>::from(self.end).to_rfc3339(),
477 display_duration(&self.interval),
478 display_duration(&self.lookback_delta)
479 )
480 }
481}
482
483#[derive(Debug, Clone, PartialEq, Eq)]
491#[cfg_attr(feature = "ser", derive(serde::Serialize))]
492pub struct AggregateExpr {
493 pub op: TokenType,
495 pub expr: Box<Expr>,
497 pub param: Option<Box<Expr>>,
499 #[cfg_attr(feature = "ser", serde(flatten))]
501 #[cfg_attr(feature = "ser", serde(serialize_with = "serialize_grouping"))]
502 pub modifier: Option<LabelModifier>,
503}
504
505impl AggregateExpr {
506 fn get_op_string(&self) -> String {
507 let mut s = self.op.to_string();
508
509 if let Some(modifier) = &self.modifier {
510 match modifier {
511 LabelModifier::Exclude(ls) => write!(s, " without ({ls}) ").unwrap(),
512 LabelModifier::Include(ls) if !ls.is_empty() => write!(s, " by ({ls}) ").unwrap(),
513 _ => (),
514 }
515 }
516 s
517 }
518}
519
520impl fmt::Display for AggregateExpr {
521 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
522 write!(f, "{}", self.get_op_string())?;
523
524 write!(f, "(")?;
525 if let Some(param) = &self.param {
526 write!(f, "{param}, ")?;
527 }
528 write!(f, "{})", self.expr)?;
529
530 Ok(())
531 }
532}
533
534impl Prettier for AggregateExpr {
535 fn format(&self, level: usize, max: usize) -> String {
536 let mut s = format!("{}{}(\n", indent(level), self.get_op_string());
537 if let Some(param) = &self.param {
538 writeln!(s, "{},", param.pretty(level + 1, max)).unwrap();
539 }
540 writeln!(s, "{}", self.expr.pretty(level + 1, max)).unwrap();
541 write!(s, "{})", indent(level)).unwrap();
542 s
543 }
544}
545
546#[derive(Debug, Clone, PartialEq, Eq)]
548pub struct UnaryExpr {
549 pub expr: Box<Expr>,
550}
551
552impl fmt::Display for UnaryExpr {
553 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
554 write!(f, "-{}", self.expr)
555 }
556}
557
558impl Prettier for UnaryExpr {
559 fn pretty(&self, level: usize, max: usize) -> String {
560 format!(
561 "{}-{}",
562 indent(level),
563 self.expr.pretty(level, max).trim_start()
564 )
565 }
566}
567
568#[cfg(feature = "ser")]
569impl serde::Serialize for UnaryExpr {
570 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
571 where
572 S: serde::Serializer,
573 {
574 use serde::ser::SerializeMap;
575 let mut map = serializer.serialize_map(Some(2))?;
576 map.serialize_entry("op", "-")?;
577 map.serialize_entry("expr", &self.expr)?;
578
579 map.end()
580 }
581}
582
583#[derive(Debug, Clone, PartialEq, Eq)]
591#[cfg_attr(feature = "ser", derive(serde::Serialize))]
592pub struct BinaryExpr {
593 pub op: TokenType,
595 pub lhs: Box<Expr>,
597 pub rhs: Box<Expr>,
599 #[cfg_attr(feature = "ser", serde(flatten))]
600 #[cfg_attr(feature = "ser", serde(serialize_with = "serialize_bin_modifier"))]
601 pub modifier: Option<BinModifier>,
602}
603
604impl BinaryExpr {
605 pub fn is_matching_on(&self) -> bool {
606 matches!(&self.modifier, Some(modifier) if modifier.is_matching_on())
607 }
608
609 pub fn is_matching_labels_not_empty(&self) -> bool {
610 matches!(&self.modifier, Some(modifier) if modifier.is_matching_labels_not_empty())
611 }
612
613 pub fn return_bool(&self) -> bool {
614 matches!(&self.modifier, Some(modifier) if modifier.return_bool)
615 }
616
617 pub fn is_labels_joint(&self) -> bool {
619 matches!(&self.modifier, Some(modifier) if modifier.is_labels_joint())
620 }
621
622 pub fn intersect_labels(&self) -> Option<Vec<String>> {
624 self.modifier
625 .as_ref()
626 .and_then(|modifier| modifier.intersect_labels())
627 }
628
629 fn get_op_matching_string(&self) -> String {
630 match &self.modifier {
631 Some(modifier) => format!("{}{modifier}", self.op),
632 None => self.op.to_string(),
633 }
634 }
635}
636
637impl fmt::Display for BinaryExpr {
638 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
639 write!(
640 f,
641 "{} {} {}",
642 self.lhs,
643 self.get_op_matching_string(),
644 self.rhs
645 )
646 }
647}
648
649impl Prettier for BinaryExpr {
650 fn format(&self, level: usize, max: usize) -> String {
651 format!(
652 "{}\n{}{}\n{}",
653 self.lhs.pretty(level + 1, max),
654 indent(level),
655 self.get_op_matching_string(),
656 self.rhs.pretty(level + 1, max)
657 )
658 }
659}
660
661#[derive(Debug, Clone, PartialEq, Eq)]
662#[cfg_attr(feature = "ser", derive(serde::Serialize))]
663pub struct ParenExpr {
664 pub expr: Box<Expr>,
665}
666
667impl fmt::Display for ParenExpr {
668 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
669 write!(f, "({})", self.expr)
670 }
671}
672
673impl Prettier for ParenExpr {
674 fn format(&self, level: usize, max: usize) -> String {
675 format!(
676 "{}(\n{}\n{})",
677 indent(level),
678 self.expr.pretty(level + 1, max),
679 indent(level)
680 )
681 }
682}
683
684#[derive(Debug, Clone, PartialEq, Eq)]
689#[cfg_attr(feature = "ser", derive(serde::Serialize))]
690pub struct SubqueryExpr {
691 pub expr: Box<Expr>,
692 #[cfg_attr(feature = "ser", serde(serialize_with = "Offset::serialize_offset"))]
693 pub offset: Option<Offset>,
694 #[cfg_attr(feature = "ser", serde(flatten))]
695 #[cfg_attr(feature = "ser", serde(serialize_with = "serialize_at_modifier"))]
696 pub at: Option<AtModifier>,
697 #[cfg_attr(
698 feature = "ser",
699 serde(serialize_with = "crate::util::duration::serialize_duration")
700 )]
701 pub range: Duration,
702 #[cfg_attr(
704 feature = "ser",
705 serde(serialize_with = "crate::util::duration::serialize_duration_opt")
706 )]
707 pub step: Option<Duration>,
708}
709
710impl SubqueryExpr {
711 fn get_time_suffix_string(&self) -> String {
712 let step = match &self.step {
713 Some(step) => display_duration(step),
714 None => String::from(""),
715 };
716 let range = display_duration(&self.range);
717
718 let mut s = format!("[{range}:{step}]");
719
720 if let Some(at) = &self.at {
721 write!(s, " {at}").unwrap();
722 }
723
724 if let Some(offset) = &self.offset {
725 write!(s, " offset {offset}").unwrap();
726 }
727 s
728 }
729}
730
731impl fmt::Display for SubqueryExpr {
732 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
733 write!(f, "{}{}", self.expr, self.get_time_suffix_string())
734 }
735}
736
737impl Prettier for SubqueryExpr {
738 fn pretty(&self, level: usize, max: usize) -> String {
739 format!(
740 "{}{}",
741 self.expr.pretty(level, max),
742 self.get_time_suffix_string()
743 )
744 }
745}
746
747#[derive(Debug, Clone)]
748pub struct NumberLiteral {
749 pub val: f64,
750}
751
752impl NumberLiteral {
753 pub fn new(val: f64) -> Self {
754 Self { val }
755 }
756}
757
758impl PartialEq for NumberLiteral {
759 fn eq(&self, other: &Self) -> bool {
760 self.val == other.val || self.val.is_nan() && other.val.is_nan()
761 }
762}
763
764impl Eq for NumberLiteral {}
765
766impl Neg for NumberLiteral {
767 type Output = Self;
768
769 fn neg(self) -> Self::Output {
770 NumberLiteral { val: -self.val }
771 }
772}
773
774impl fmt::Display for NumberLiteral {
775 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
776 if self.val == f64::INFINITY {
777 write!(f, "Inf")
778 } else if self.val == f64::NEG_INFINITY {
779 write!(f, "-Inf")
780 } else if f64::is_nan(self.val) {
781 write!(f, "NaN")
782 } else {
783 write!(f, "{}", self.val)
784 }
785 }
786}
787
788#[cfg(feature = "ser")]
789impl serde::Serialize for NumberLiteral {
790 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
791 where
792 S: serde::Serializer,
793 {
794 use serde::ser::SerializeMap;
795 let mut map = serializer.serialize_map(Some(1))?;
796 map.serialize_entry("val", &self.to_string())?;
797
798 map.end()
799 }
800}
801
802impl Prettier for NumberLiteral {
803 fn needs_split(&self, _max: usize) -> bool {
804 false
805 }
806}
807
808#[derive(Debug, Clone, PartialEq, Eq)]
809#[cfg_attr(feature = "ser", derive(serde::Serialize))]
810pub struct StringLiteral {
811 pub val: String,
812}
813
814impl fmt::Display for StringLiteral {
815 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
816 write!(f, "\"{}\"", self.val)
817 }
818}
819
820impl Prettier for StringLiteral {
821 fn needs_split(&self, _max: usize) -> bool {
822 false
823 }
824}
825
826#[derive(Debug, Clone, PartialEq, Eq)]
827#[cfg_attr(feature = "ser", derive(serde::Serialize))]
828pub struct VectorSelector {
829 pub name: Option<String>,
830 #[cfg_attr(feature = "ser", serde(flatten))]
831 pub matchers: Matchers,
832 #[cfg_attr(feature = "ser", serde(serialize_with = "Offset::serialize_offset"))]
833 pub offset: Option<Offset>,
834 #[cfg_attr(feature = "ser", serde(flatten))]
835 #[cfg_attr(feature = "ser", serde(serialize_with = "serialize_at_modifier"))]
836 pub at: Option<AtModifier>,
837}
838
839impl VectorSelector {
840 pub fn new(name: Option<String>, matchers: Matchers) -> Self {
841 VectorSelector {
842 name,
843 matchers,
844 offset: None,
845 at: None,
846 }
847 }
848}
849
850impl Default for VectorSelector {
851 fn default() -> Self {
852 Self {
853 name: None,
854 matchers: Matchers::empty(),
855 offset: None,
856 at: None,
857 }
858 }
859}
860
861impl From<String> for VectorSelector {
862 fn from(name: String) -> Self {
863 VectorSelector {
864 name: Some(name),
865 offset: None,
866 at: None,
867 matchers: Matchers::empty(),
868 }
869 }
870}
871
872impl From<&str> for VectorSelector {
892 fn from(name: &str) -> Self {
893 VectorSelector::from(name.to_string())
894 }
895}
896
897impl Neg for VectorSelector {
898 type Output = UnaryExpr;
899
900 fn neg(self) -> Self::Output {
901 let ex = Expr::VectorSelector(self);
902 UnaryExpr { expr: Box::new(ex) }
903 }
904}
905
906impl fmt::Display for VectorSelector {
907 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
908 if let Some(name) = &self.name {
909 write!(f, "{name}")?;
910 }
911 let matchers = &self.matchers.to_string();
912 if !matchers.is_empty() {
913 write!(f, "{{{matchers}}}")?;
914 }
915 if let Some(at) = &self.at {
916 write!(f, " {at}")?;
917 }
918 if let Some(offset) = &self.offset {
919 write!(f, " offset {offset}")?;
920 }
921 Ok(())
922 }
923}
924
925impl Prettier for VectorSelector {
926 fn needs_split(&self, _max: usize) -> bool {
927 false
928 }
929}
930
931#[derive(Debug, Clone, PartialEq, Eq)]
932#[cfg_attr(feature = "ser", derive(serde::Serialize))]
933pub struct MatrixSelector {
934 #[cfg_attr(feature = "ser", serde(flatten))]
935 pub vs: VectorSelector,
936 #[cfg_attr(
937 feature = "ser",
938 serde(serialize_with = "crate::util::duration::serialize_duration")
939 )]
940 pub range: Duration,
941}
942
943impl fmt::Display for MatrixSelector {
944 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
945 if let Some(name) = &self.vs.name {
946 write!(f, "{name}")?;
947 }
948
949 let matchers = &self.vs.matchers.to_string();
950 if !matchers.is_empty() {
951 write!(f, "{{{matchers}}}")?;
952 }
953
954 write!(f, "[{}]", display_duration(&self.range))?;
955
956 if let Some(at) = &self.vs.at {
957 write!(f, " {at}")?;
958 }
959
960 if let Some(offset) = &self.vs.offset {
961 write!(f, " offset {offset}")?;
962 }
963
964 Ok(())
965 }
966}
967
968impl Prettier for MatrixSelector {
969 fn needs_split(&self, _max: usize) -> bool {
970 false
971 }
972}
973
974#[derive(Debug, Clone, PartialEq, Eq)]
1014#[cfg_attr(feature = "ser", derive(serde::Serialize))]
1015pub struct Call {
1016 pub func: Function,
1017 #[cfg_attr(feature = "ser", serde(flatten))]
1018 pub args: FunctionArgs,
1019}
1020
1021impl fmt::Display for Call {
1022 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1023 write!(f, "{}({})", self.func.name, self.args)
1024 }
1025}
1026
1027impl Prettier for Call {
1028 fn format(&self, level: usize, max: usize) -> String {
1029 format!(
1030 "{}{}(\n{}\n{})",
1031 indent(level),
1032 self.func.name,
1033 self.args.pretty(level + 1, max),
1034 indent(level)
1035 )
1036 }
1037}
1038
1039#[derive(Debug, Clone)]
1041pub struct Extension {
1042 pub expr: Arc<dyn ExtensionExpr>,
1043}
1044
1045pub trait ExtensionExpr: std::fmt::Debug + Send + Sync {
1047 fn as_any(&self) -> &dyn std::any::Any;
1048
1049 fn name(&self) -> &str;
1050
1051 fn value_type(&self) -> ValueType;
1052
1053 fn children(&self) -> &[Expr];
1054}
1055
1056impl PartialEq for Extension {
1057 fn eq(&self, other: &Self) -> bool {
1058 format!("{self:?}") == format!("{other:?}")
1059 }
1060}
1061
1062impl Eq for Extension {}
1063
1064#[derive(Debug, Clone, PartialEq, Eq)]
1065#[cfg_attr(feature = "ser", derive(serde::Serialize))]
1066#[cfg_attr(feature = "ser", serde(tag = "type", rename_all = "camelCase"))]
1067pub enum Expr {
1068 #[cfg_attr(feature = "ser", serde(rename = "aggregation"))]
1070 Aggregate(AggregateExpr),
1071
1072 #[cfg_attr(feature = "ser", serde(rename = "unaryExpr"))]
1075 Unary(UnaryExpr),
1076
1077 #[cfg_attr(feature = "ser", serde(rename = "binaryExpr"))]
1079 Binary(BinaryExpr),
1080
1081 #[cfg_attr(feature = "ser", serde(rename = "parenExpr"))]
1084 Paren(ParenExpr),
1085
1086 Subquery(SubqueryExpr),
1088
1089 NumberLiteral(NumberLiteral),
1091
1092 StringLiteral(StringLiteral),
1094
1095 VectorSelector(VectorSelector),
1097
1098 MatrixSelector(MatrixSelector),
1100
1101 Call(Call),
1103
1104 #[cfg_attr(feature = "ser", serde(skip))]
1107 Extension(Extension),
1108}
1109
1110impl Expr {
1111 pub(crate) fn new_vector_selector(
1112 name: Option<String>,
1113 matchers: Matchers,
1114 ) -> Result<Self, String> {
1115 let vs = VectorSelector::new(name, matchers);
1116 Ok(Self::VectorSelector(vs))
1117 }
1118
1119 pub(crate) fn new_unary_expr(expr: Expr) -> Result<Self, String> {
1120 match expr {
1121 Expr::StringLiteral(_) => Err("unary expression only allowed on expressions of type scalar or vector, got: string".into()),
1122 Expr::MatrixSelector(_) => Err("unary expression only allowed on expressions of type scalar or vector, got: matrix".into()),
1123 _ => Ok(-expr),
1124 }
1125 }
1126
1127 pub(crate) fn new_subquery_expr(
1128 expr: Expr,
1129 range: Duration,
1130 step: Option<Duration>,
1131 ) -> Result<Self, String> {
1132 let se = Expr::Subquery(SubqueryExpr {
1133 expr: Box::new(expr),
1134 offset: None,
1135 at: None,
1136 range,
1137 step,
1138 });
1139 Ok(se)
1140 }
1141
1142 pub(crate) fn new_paren_expr(expr: Expr) -> Result<Self, String> {
1143 let ex = Expr::Paren(ParenExpr {
1144 expr: Box::new(expr),
1145 });
1146 Ok(ex)
1147 }
1148
1149 pub(crate) fn new_matrix_selector(expr: Expr, range: Duration) -> Result<Self, String> {
1151 match expr {
1152 Expr::VectorSelector(VectorSelector {
1153 offset: Some(_), ..
1154 }) => Err("no offset modifiers allowed before range".into()),
1155 Expr::VectorSelector(VectorSelector { at: Some(_), .. }) => {
1156 Err("no @ modifiers allowed before range".into())
1157 }
1158 Expr::VectorSelector(vs) => {
1159 let ms = Expr::MatrixSelector(MatrixSelector { vs, range });
1160 Ok(ms)
1161 }
1162 _ => Err("ranges only allowed for vector selectors".into()),
1163 }
1164 }
1165
1166 pub(crate) fn at_expr(self, at: AtModifier) -> Result<Self, String> {
1167 let already_set_err = Err("@ <timestamp> may not be set multiple times".into());
1168 match self {
1169 Expr::VectorSelector(mut vs) => match vs.at {
1170 None => {
1171 vs.at = Some(at);
1172 Ok(Expr::VectorSelector(vs))
1173 }
1174 Some(_) => already_set_err,
1175 },
1176 Expr::MatrixSelector(mut ms) => match ms.vs.at {
1177 None => {
1178 ms.vs.at = Some(at);
1179 Ok(Expr::MatrixSelector(ms))
1180 }
1181 Some(_) => already_set_err,
1182 },
1183 Expr::Subquery(mut s) => match s.at {
1184 None => {
1185 s.at = Some(at);
1186 Ok(Expr::Subquery(s))
1187 }
1188 Some(_) => already_set_err,
1189 },
1190 _ => {
1191 Err("@ modifier must be preceded by an vector selector or matrix selector or a subquery".into())
1192 }
1193 }
1194 }
1195
1196 pub(crate) fn offset_expr(self, offset: Offset) -> Result<Self, String> {
1198 let already_set_err = Err("offset may not be set multiple times".into());
1199 match self {
1200 Expr::VectorSelector(mut vs) => match vs.offset {
1201 None => {
1202 vs.offset = Some(offset);
1203 Ok(Expr::VectorSelector(vs))
1204 }
1205 Some(_) => already_set_err,
1206 },
1207 Expr::MatrixSelector(mut ms) => match ms.vs.offset {
1208 None => {
1209 ms.vs.offset = Some(offset);
1210 Ok(Expr::MatrixSelector(ms))
1211 }
1212 Some(_) => already_set_err,
1213 },
1214 Expr::Subquery(mut s) => match s.offset {
1215 None => {
1216 s.offset = Some(offset);
1217 Ok(Expr::Subquery(s))
1218 }
1219 Some(_) => already_set_err,
1220 },
1221 _ => {
1222 Err("offset modifier must be preceded by an vector selector or matrix selector or a subquery".into())
1223 }
1224 }
1225 }
1226
1227 pub(crate) fn new_call(func: Function, args: FunctionArgs) -> Result<Expr, String> {
1228 Ok(Expr::Call(Call { func, args }))
1229 }
1230
1231 pub(crate) fn new_binary_expr(
1232 lhs: Expr,
1233 op: TokenId,
1234 modifier: Option<BinModifier>,
1235 rhs: Expr,
1236 ) -> Result<Expr, String> {
1237 let ex = BinaryExpr {
1238 op: TokenType::new(op),
1239 lhs: Box::new(lhs),
1240 rhs: Box::new(rhs),
1241 modifier,
1242 };
1243 Ok(Expr::Binary(ex))
1244 }
1245
1246 pub(crate) fn new_aggregate_expr(
1247 op: TokenId,
1248 modifier: Option<LabelModifier>,
1249 args: FunctionArgs,
1250 ) -> Result<Expr, String> {
1251 let op = TokenType::new(op);
1252 if args.is_empty() {
1253 return Err(format!(
1254 "no arguments for aggregate expression '{op}' provided"
1255 ));
1256 }
1257 let mut desired_args_count = 1;
1258 let mut param = None;
1259 if op.is_aggregator_with_param() {
1260 desired_args_count = 2;
1261 param = args.first();
1262 }
1263 if args.len() != desired_args_count {
1264 return Err(format!(
1265 "wrong number of arguments for aggregate expression provided, expected {}, got {}",
1266 desired_args_count,
1267 args.len()
1268 ));
1269 }
1270
1271 match args.last() {
1272 Some(expr) => Ok(Expr::Aggregate(AggregateExpr {
1273 op,
1274 expr,
1275 param,
1276 modifier,
1277 })),
1278 None => Err(
1279 "aggregate operation needs a single instant vector parameter, but found none"
1280 .into(),
1281 ),
1282 }
1283 }
1284
1285 pub fn value_type(&self) -> ValueType {
1286 match self {
1287 Expr::Aggregate(_) => ValueType::Vector,
1288 Expr::Unary(ex) => ex.expr.value_type(),
1289 Expr::Binary(ex) => {
1290 if ex.lhs.value_type() == ValueType::Scalar
1291 && ex.rhs.value_type() == ValueType::Scalar
1292 {
1293 ValueType::Scalar
1294 } else {
1295 ValueType::Vector
1296 }
1297 }
1298 Expr::Paren(ex) => ex.expr.value_type(),
1299 Expr::Subquery(_) => ValueType::Matrix,
1300 Expr::NumberLiteral(_) => ValueType::Scalar,
1301 Expr::StringLiteral(_) => ValueType::String,
1302 Expr::VectorSelector(_) => ValueType::Vector,
1303 Expr::MatrixSelector(_) => ValueType::Matrix,
1304 Expr::Call(ex) => ex.func.return_type,
1305 Expr::Extension(ex) => ex.expr.value_type(),
1306 }
1307 }
1308
1309 pub(crate) fn scalar_value(&self) -> Option<f64> {
1311 match self {
1312 Expr::NumberLiteral(nl) => Some(nl.val),
1313 _ => None,
1314 }
1315 }
1316
1317 pub fn prettify(&self) -> String {
1318 self.pretty(0, MAX_CHARACTERS_PER_LINE)
1319 }
1320}
1321
1322impl From<String> for Expr {
1323 fn from(val: String) -> Self {
1324 Expr::StringLiteral(StringLiteral { val })
1325 }
1326}
1327
1328impl From<&str> for Expr {
1329 fn from(s: &str) -> Self {
1330 Expr::StringLiteral(StringLiteral { val: s.into() })
1331 }
1332}
1333
1334impl From<f64> for Expr {
1335 fn from(val: f64) -> Self {
1336 Expr::NumberLiteral(NumberLiteral { val })
1337 }
1338}
1339
1340impl From<VectorSelector> for Expr {
1356 fn from(vs: VectorSelector) -> Self {
1357 Expr::VectorSelector(vs)
1358 }
1359}
1360
1361impl Neg for Expr {
1362 type Output = Self;
1363
1364 fn neg(self) -> Self::Output {
1365 match self {
1366 Expr::NumberLiteral(nl) => Expr::NumberLiteral(-nl),
1367 _ => Expr::Unary(UnaryExpr {
1368 expr: Box::new(self),
1369 }),
1370 }
1371 }
1372}
1373
1374impl fmt::Display for Expr {
1375 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1376 match self {
1377 Expr::Aggregate(ex) => write!(f, "{ex}"),
1378 Expr::Unary(ex) => write!(f, "{ex}"),
1379 Expr::Binary(ex) => write!(f, "{ex}"),
1380 Expr::Paren(ex) => write!(f, "{ex}"),
1381 Expr::Subquery(ex) => write!(f, "{ex}"),
1382 Expr::NumberLiteral(ex) => write!(f, "{ex}"),
1383 Expr::StringLiteral(ex) => write!(f, "{ex}"),
1384 Expr::VectorSelector(ex) => write!(f, "{ex}"),
1385 Expr::MatrixSelector(ex) => write!(f, "{ex}"),
1386 Expr::Call(ex) => write!(f, "{ex}"),
1387 Expr::Extension(ext) => write!(f, "{ext:?}"),
1388 }
1389 }
1390}
1391
1392impl Prettier for Expr {
1393 fn pretty(&self, level: usize, max: usize) -> String {
1394 match self {
1395 Expr::Aggregate(ex) => ex.pretty(level, max),
1396 Expr::Unary(ex) => ex.pretty(level, max),
1397 Expr::Binary(ex) => ex.pretty(level, max),
1398 Expr::Paren(ex) => ex.pretty(level, max),
1399 Expr::Subquery(ex) => ex.pretty(level, max),
1400 Expr::NumberLiteral(ex) => ex.pretty(level, max),
1401 Expr::StringLiteral(ex) => ex.pretty(level, max),
1402 Expr::VectorSelector(ex) => ex.pretty(level, max),
1403 Expr::MatrixSelector(ex) => ex.pretty(level, max),
1404 Expr::Call(ex) => ex.pretty(level, max),
1405 Expr::Extension(ext) => format!("{ext:?}"),
1406 }
1407 }
1408}
1409
1410pub(crate) fn check_ast(expr: Expr) -> Result<Expr, String> {
1413 match expr {
1414 Expr::Binary(ex) => check_ast_for_binary_expr(ex),
1415 Expr::Aggregate(ex) => check_ast_for_aggregate_expr(ex),
1416 Expr::Call(ex) => check_ast_for_call(ex),
1417 Expr::Unary(ex) => check_ast_for_unary(ex),
1418 Expr::Subquery(ex) => check_ast_for_subquery(ex),
1419 Expr::VectorSelector(ex) => check_ast_for_vector_selector(ex),
1420 Expr::Paren(_) => Ok(expr),
1421 Expr::NumberLiteral(_) => Ok(expr),
1422 Expr::StringLiteral(_) => Ok(expr),
1423 Expr::MatrixSelector(_) => Ok(expr),
1424 Expr::Extension(_) => Ok(expr),
1425 }
1426}
1427
1428fn expect_type(
1429 expected: ValueType,
1430 actual: Option<ValueType>,
1431 context: &str,
1432) -> Result<bool, String> {
1433 match actual {
1434 Some(actual) => {
1435 if actual == expected {
1436 Ok(true)
1437 } else {
1438 Err(format!(
1439 "expected type {expected} in {context}, got {actual}"
1440 ))
1441 }
1442 }
1443 None => Err(format!("expected type {expected} in {context}, got None")),
1444 }
1445}
1446
1447fn check_ast_for_binary_expr(mut ex: BinaryExpr) -> Result<Expr, String> {
1450 if !ex.op.is_operator() {
1451 return Err(format!(
1452 "binary expression does not support operator '{}'",
1453 ex.op
1454 ));
1455 }
1456
1457 if ex.return_bool() && !ex.op.is_comparison_operator() {
1458 return Err("bool modifier can only be used on comparison operators".into());
1459 }
1460
1461 if ex.op.is_comparison_operator()
1462 && ex.lhs.value_type() == ValueType::Scalar
1463 && ex.rhs.value_type() == ValueType::Scalar
1464 && !ex.return_bool()
1465 {
1466 return Err("comparisons between scalars must use BOOL modifier".into());
1467 }
1468
1469 if ex.is_matching_on() && ex.is_labels_joint() {
1472 if let Some(labels) = ex.intersect_labels() {
1473 if let Some(label) = labels.first() {
1474 return Err(format!(
1475 "label '{label}' must not occur in ON and GROUP clause at once"
1476 ));
1477 }
1478 };
1479 }
1480
1481 if ex.op.is_set_operator() {
1482 if ex.lhs.value_type() == ValueType::Scalar || ex.rhs.value_type() == ValueType::Scalar {
1483 return Err(format!(
1484 "set operator '{}' not allowed in binary scalar expression",
1485 ex.op
1486 ));
1487 }
1488
1489 if ex.lhs.value_type() == ValueType::Vector && ex.rhs.value_type() == ValueType::Vector {
1490 if let Some(ref modifier) = ex.modifier {
1491 if matches!(modifier.card, VectorMatchCardinality::OneToMany(_))
1492 || matches!(modifier.card, VectorMatchCardinality::ManyToOne(_))
1493 {
1494 return Err(format!("no grouping allowed for '{}' operation", ex.op));
1495 }
1496 };
1497 }
1498
1499 match &mut ex.modifier {
1500 Some(modifier) => {
1501 if modifier.card == VectorMatchCardinality::OneToOne {
1502 modifier.card = VectorMatchCardinality::ManyToMany;
1503 }
1504 }
1505 None => {
1506 ex.modifier =
1507 Some(BinModifier::default().with_card(VectorMatchCardinality::ManyToMany));
1508 }
1509 }
1510 }
1511
1512 if ex.lhs.value_type() != ValueType::Scalar && ex.lhs.value_type() != ValueType::Vector {
1513 return Err("binary expression must contain only scalar and instant vector types".into());
1514 }
1515 if ex.rhs.value_type() != ValueType::Scalar && ex.rhs.value_type() != ValueType::Vector {
1516 return Err("binary expression must contain only scalar and instant vector types".into());
1517 }
1518
1519 if (ex.lhs.value_type() != ValueType::Vector || ex.rhs.value_type() != ValueType::Vector)
1520 && ex.is_matching_labels_not_empty()
1521 {
1522 return Err("vector matching only allowed between vectors".into());
1523 }
1524
1525 Ok(Expr::Binary(ex))
1526}
1527
1528fn check_ast_for_aggregate_expr(ex: AggregateExpr) -> Result<Expr, String> {
1529 if !ex.op.is_aggregator() {
1530 return Err(format!(
1531 "aggregation operator expected in aggregation expression but got '{}'",
1532 ex.op
1533 ));
1534 }
1535
1536 expect_type(
1537 ValueType::Vector,
1538 Some(ex.expr.value_type()),
1539 "aggregation expression",
1540 )?;
1541
1542 if matches!(ex.op.id(), T_TOPK | T_BOTTOMK | T_QUANTILE) {
1543 expect_type(
1544 ValueType::Scalar,
1545 ex.param.as_ref().map(|ex| ex.value_type()),
1546 "aggregation expression",
1547 )?;
1548 }
1549
1550 if ex.op.id() == T_COUNT_VALUES {
1551 expect_type(
1552 ValueType::String,
1553 ex.param.as_ref().map(|ex| ex.value_type()),
1554 "aggregation expression",
1555 )?;
1556 }
1557
1558 Ok(Expr::Aggregate(ex))
1559}
1560
1561fn check_ast_for_call(ex: Call) -> Result<Expr, String> {
1562 let expected_args_len = ex.func.arg_types.len();
1563 let name = ex.func.name;
1564 let actual_args_len = ex.args.len();
1565
1566 if ex.func.variadic {
1567 let expected_args_len_without_default = expected_args_len - 1;
1568 if expected_args_len_without_default > actual_args_len {
1569 return Err(format!(
1570 "expected at least {expected_args_len_without_default} argument(s) in call to '{name}', got {actual_args_len}"
1571 ));
1572 }
1573
1574 if actual_args_len > expected_args_len
1577 && name.ne("label_join")
1578 && name.ne("sort_by_label")
1579 && name.ne("sort_by_label_desc")
1580 {
1581 return Err(format!(
1582 "expected at most {expected_args_len} argument(s) in call to '{name}', got {actual_args_len}"
1583 ));
1584 }
1585 }
1586
1587 if !ex.func.variadic && expected_args_len != actual_args_len {
1588 return Err(format!(
1589 "expected {expected_args_len} argument(s) in call to '{name}', got {actual_args_len}"
1590 ));
1591 }
1592
1593 if name.eq("exp") {
1595 if let Some(val) = ex.args.first().and_then(|ex| ex.scalar_value()) {
1596 if val.is_nan() || val.is_infinite() {
1597 return Ok(Expr::Call(ex));
1598 }
1599 }
1600 } else if name.eq("ln") || name.eq("log2") || name.eq("log10") {
1601 if let Some(val) = ex.args.first().and_then(|ex| ex.scalar_value()) {
1602 if val.is_nan() || val.is_infinite() || val <= 0.0 {
1603 return Ok(Expr::Call(ex));
1604 }
1605 }
1606 }
1607
1608 for (mut idx, actual_arg) in ex.args.args.iter().enumerate() {
1609 if idx >= ex.func.arg_types.len() {
1611 idx = ex.func.arg_types.len() - 1;
1612 }
1613
1614 expect_type(
1615 ex.func.arg_types[idx],
1616 Some(actual_arg.value_type()),
1617 &format!("call to function '{name}'"),
1618 )?;
1619 }
1620
1621 Ok(Expr::Call(ex))
1622}
1623
1624fn check_ast_for_unary(ex: UnaryExpr) -> Result<Expr, String> {
1625 let value_type = ex.expr.value_type();
1626 if value_type != ValueType::Scalar && value_type != ValueType::Vector {
1627 return Err(format!(
1628 "unary expression only allowed on expressions of type scalar or vector, got {value_type}"
1629 ));
1630 }
1631
1632 Ok(Expr::Unary(ex))
1633}
1634
1635fn check_ast_for_subquery(ex: SubqueryExpr) -> Result<Expr, String> {
1636 let value_type = ex.expr.value_type();
1637 if value_type != ValueType::Vector {
1638 return Err(format!(
1639 "subquery is only allowed on vector, got {value_type} instead"
1640 ));
1641 }
1642
1643 Ok(Expr::Subquery(ex))
1644}
1645
1646fn check_ast_for_vector_selector(ex: VectorSelector) -> Result<Expr, String> {
1647 match ex.name {
1648 Some(ref name) => match ex.matchers.find_matcher_value(METRIC_NAME) {
1649 Some(val) => Err(format!(
1650 "metric name must not be set twice: '{name}' or '{val}'"
1651 )),
1652 None => Ok(Expr::VectorSelector(ex)),
1653 },
1654 None if ex.matchers.is_empty_matchers() => {
1655 Err("vector selector must contain at least one non-empty matcher".into())
1658 }
1659 _ => Ok(Expr::VectorSelector(ex)),
1660 }
1661}
1662
1663#[cfg(test)]
1664mod tests {
1665 use super::*;
1666 use crate::label::{MatchOp, Matcher};
1667
1668 #[test]
1669 fn test_valid_at_modifier() {
1670 let cases = vec![
1671 (0.0, 0),
1673 (1000.3, 1000300), (1000.9, 1000900), (1000.9991, 1000999), (1000.9999, 1001000), (-1000.3, 1000300), (-1000.9, 1000900), ];
1680
1681 for (secs, elapsed) in cases {
1682 match AtModifier::try_from(secs).unwrap() {
1683 AtModifier::At(st) => {
1684 if secs.is_sign_positive() || secs == 0.0 {
1685 assert_eq!(
1686 elapsed,
1687 st.duration_since(SystemTime::UNIX_EPOCH)
1688 .unwrap()
1689 .as_millis()
1690 )
1691 } else if secs.is_sign_negative() {
1692 assert_eq!(
1693 elapsed,
1694 SystemTime::UNIX_EPOCH
1695 .duration_since(st)
1696 .unwrap()
1697 .as_millis()
1698 )
1699 }
1700 }
1701 _ => panic!(),
1702 }
1703 }
1704
1705 assert_eq!(
1706 AtModifier::try_from(Expr::from(1.0)),
1707 AtModifier::try_from(1.0),
1708 );
1709 }
1710
1711 #[test]
1712 fn test_invalid_at_modifier() {
1713 let cases = vec![
1714 f64::MAX,
1715 f64::MIN,
1716 f64::NAN,
1717 f64::INFINITY,
1718 f64::NEG_INFINITY,
1719 ];
1720
1721 for secs in cases {
1722 assert!(AtModifier::try_from(secs).is_err())
1723 }
1724
1725 assert_eq!(
1726 AtModifier::try_from(token::T_ADD),
1727 Err("invalid @ modifier preprocessor '+', START or END is valid.".into())
1728 );
1729
1730 assert_eq!(
1731 AtModifier::try_from(Expr::from("string literal")),
1732 Err("invalid float value after @ modifier".into())
1733 );
1734 }
1735
1736 #[test]
1737 fn test_binary_labels() {
1738 assert_eq!(
1739 &Labels::new(vec!["foo", "bar"]),
1740 LabelModifier::Include(Labels::new(vec!["foo", "bar"])).labels()
1741 );
1742
1743 assert_eq!(
1744 &Labels::new(vec!["foo", "bar"]),
1745 LabelModifier::Exclude(Labels::new(vec!["foo", "bar"])).labels()
1746 );
1747
1748 assert_eq!(
1749 &Labels::new(vec!["foo", "bar"]),
1750 VectorMatchCardinality::OneToMany(Labels::new(vec!["foo", "bar"]))
1751 .labels()
1752 .unwrap()
1753 );
1754
1755 assert_eq!(
1756 &Labels::new(vec!["foo", "bar"]),
1757 VectorMatchCardinality::ManyToOne(Labels::new(vec!["foo", "bar"]))
1758 .labels()
1759 .unwrap()
1760 );
1761
1762 assert_eq!(VectorMatchCardinality::OneToOne.labels(), None);
1763 assert_eq!(VectorMatchCardinality::ManyToMany.labels(), None);
1764 }
1765
1766 #[test]
1767 fn test_neg() {
1768 assert_eq!(
1769 -VectorSelector::from("foo"),
1770 UnaryExpr {
1771 expr: Box::new(Expr::from(VectorSelector::from("foo")))
1772 }
1773 )
1774 }
1775
1776 #[test]
1777 fn test_scalar_value() {
1778 assert_eq!(Some(1.0), Expr::from(1.0).scalar_value());
1779 assert_eq!(None, Expr::from("1.0").scalar_value());
1780 }
1781
1782 #[test]
1783 fn test_at_expr() {
1784 assert_eq!(
1785 "@ <timestamp> may not be set multiple times",
1786 Expr::from(VectorSelector::from("foo"))
1787 .at_expr(AtModifier::try_from(1.0).unwrap())
1788 .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1789 .unwrap_err()
1790 );
1791
1792 assert_eq!(
1793 "@ <timestamp> may not be set multiple times",
1794 Expr::new_matrix_selector(
1795 Expr::from(VectorSelector::from("foo")),
1796 Duration::from_secs(1),
1797 )
1798 .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1799 .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1800 .unwrap_err()
1801 );
1802
1803 assert_eq!(
1804 "@ <timestamp> may not be set multiple times",
1805 Expr::new_subquery_expr(
1806 Expr::from(VectorSelector::from("foo")),
1807 Duration::from_secs(1),
1808 None,
1809 )
1810 .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1811 .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1812 .unwrap_err()
1813 )
1814 }
1815
1816 #[test]
1817 fn test_offset_expr() {
1818 assert_eq!(
1819 "offset may not be set multiple times",
1820 Expr::from(VectorSelector::from("foo"))
1821 .offset_expr(Offset::Pos(Duration::from_secs(1000)))
1822 .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1823 .unwrap_err()
1824 );
1825
1826 assert_eq!(
1827 "offset may not be set multiple times",
1828 Expr::new_matrix_selector(
1829 Expr::from(VectorSelector::from("foo")),
1830 Duration::from_secs(1),
1831 )
1832 .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1833 .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1834 .unwrap_err()
1835 );
1836
1837 assert_eq!(
1838 "offset may not be set multiple times",
1839 Expr::new_subquery_expr(
1840 Expr::from(VectorSelector::from("foo")),
1841 Duration::from_secs(1),
1842 None,
1843 )
1844 .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1845 .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1846 .unwrap_err()
1847 );
1848 }
1849
1850 #[test]
1851 fn test_expr_to_string() {
1852 let mut cases = vec![
1853 ("1", "1"),
1854 ("- 1", "-1"),
1855 ("+ 1", "1"),
1856 ("Inf", "Inf"),
1857 ("inf", "Inf"),
1858 ("+Inf", "Inf"),
1859 ("- Inf", "-Inf"),
1860 (".5", "0.5"),
1861 ("5.", "5"),
1862 ("123.4567", "123.4567"),
1863 ("5e-3", "0.005"),
1864 ("5e3", "5000"),
1865 ("0xc", "12"),
1866 ("0755", "493"),
1867 ("08", "8"),
1868 ("+5.5e-3", "0.0055"),
1869 ("-0755", "-493"),
1870 ("NaN", "NaN"),
1871 ("NAN", "NaN"),
1872 ("- 1^2", "-1 ^ 2"),
1873 ("+1 + -2 * 1", "1 + -2 * 1"),
1874 ("1 + 2/(3*1)", "1 + 2 / (3 * 1)"),
1875 ("foo*sum", "foo * sum"),
1876 ("foo * on(test,blub) bar", "foo * on (test, blub) bar"),
1877 (
1878 r#"up{job="hi", instance="in"} offset 5m @ 100"#,
1879 r#"up{instance="in",job="hi"} @ 100.000 offset 5m"#,
1880 ),
1881 (
1882 r#"up{job="hi", instance="in"}"#,
1883 r#"up{instance="in",job="hi"}"#,
1884 ),
1885 ("sum (up) by (job,instance)", "sum by (job, instance) (up)"),
1886 (
1887 "foo / on(test,blub) group_left(bar) bar",
1888 "foo / on (test, blub) group_left (bar) bar",
1889 ),
1890 (
1891 "foo / on(test,blub) group_right(bar) bar",
1892 "foo / on (test, blub) group_right (bar) bar",
1893 ),
1894 (
1895 r#"foo{a="b",foo!="bar",test=~"test",bar!~"baz"}"#,
1896 r#"foo{a="b",bar!~"baz",foo!="bar",test=~"test"}"#,
1897 ),
1898 (
1899 r#"{__name__=~"foo.+",__name__=~".*bar"}"#,
1900 r#"{__name__=~".*bar",__name__=~"foo.+"}"#,
1901 ),
1902 (
1903 r#"test{a="b"}[5y] OFFSET 3d"#,
1904 r#"test{a="b"}[5y] offset 3d"#,
1905 ),
1906 (
1907 r#"{a="b"}[5y] OFFSET 3d"#,
1908 r#"{a="b"}[5y] offset 3d"#,
1909 ),
1910 (
1911 "sum(some_metric) without(and, by, avg, count, alert, annotations)",
1912 "sum without (and, by, avg, count, alert, annotations) (some_metric)",
1913 ),
1914 (
1915 r#"floor(some_metric{foo!="bar"})"#,
1916 r#"floor(some_metric{foo!="bar"})"#,
1917 ),
1918 (
1919 "sum(rate(http_request_duration_seconds[10m])) / count(rate(http_request_duration_seconds[10m]))",
1920 "sum(rate(http_request_duration_seconds[10m])) / count(rate(http_request_duration_seconds[10m]))",
1921 ),
1922 ("rate(some_metric[5m])", "rate(some_metric[5m])"),
1923 ("round(some_metric,5)", "round(some_metric, 5)"),
1924 (
1925 r#"absent(sum(nonexistent{job="myjob"}))"#,
1926 r#"absent(sum(nonexistent{job="myjob"}))"#,
1927 ),
1928 (
1929 "histogram_quantile(0.9,rate(http_request_duration_seconds_bucket[10m]))",
1930 "histogram_quantile(0.9, rate(http_request_duration_seconds_bucket[10m]))",
1931 ),
1932 (
1933 "histogram_quantile(0.9,sum(rate(http_request_duration_seconds_bucket[10m])) by(job,le))",
1934 "histogram_quantile(0.9, sum by (job, le) (rate(http_request_duration_seconds_bucket[10m])))",
1935 ),
1936 (
1937 r#"label_join(up{job="api-server",src1="a",src2="b",src3="c"}, "foo", ",", "src1", "src2", "src3")"#,
1938 r#"label_join(up{job="api-server",src1="a",src2="b",src3="c"}, "foo", ",", "src1", "src2", "src3")"#,
1939 ),
1940 (
1941 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s] @ 100"#,
1942 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s] @ 100.000"#,
1943 ),
1944 (
1945 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s]"#,
1946 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s]"#,
1947 ),
1948 (
1949 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] offset 4m)[4m:3s]"#,
1950 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] offset 4m)[4m:3s]"#,
1951 ),
1952 ("some_metric OFFSET 1m [10m:5s]", "some_metric offset 1m[10m:5s]"),
1953 ("some_metric @123 [10m:5s]", "some_metric @ 123.000[10m:5s]"),
1954 ("some_metric <= 1ms", "some_metric <= 0.001"),
1955 ];
1956
1957 let mut cases1 = vec![
1959 (
1960 r#"sum by() (task:errors:rate10s{job="s"})"#,
1961 r#"sum(task:errors:rate10s{job="s"})"#,
1962 ),
1963 (
1964 r#"sum by(code) (task:errors:rate10s{job="s"})"#,
1965 r#"sum by (code) (task:errors:rate10s{job="s"})"#,
1966 ),
1967 (
1968 r#"sum without() (task:errors:rate10s{job="s"})"#,
1969 r#"sum without () (task:errors:rate10s{job="s"})"#,
1970 ),
1971 (
1972 r#"sum without(instance) (task:errors:rate10s{job="s"})"#,
1973 r#"sum without (instance) (task:errors:rate10s{job="s"})"#,
1974 ),
1975 (
1976 r#"topk(5, task:errors:rate10s{job="s"})"#,
1977 r#"topk(5, task:errors:rate10s{job="s"})"#,
1978 ),
1979 (
1980 r#"count_values("value", task:errors:rate10s{job="s"})"#,
1981 r#"count_values("value", task:errors:rate10s{job="s"})"#,
1982 ),
1983 ("a - on() c", "a - on () c"),
1984 ("a - on(b) c", "a - on (b) c"),
1985 ("a - on(b) group_left(x) c", "a - on (b) group_left (x) c"),
1986 (
1987 "a - on(b) group_left(x, y) c",
1988 "a - on (b) group_left (x, y) c",
1989 ),
1990 ("a - on(b) group_left c", "a - on (b) group_left () c"),
1991 ("a - ignoring(b) c", "a - ignoring (b) c"),
1992 ("a - ignoring() c", "a - c"),
1993 ("up > bool 0", "up > bool 0"),
1994 ("a offset 1m", "a offset 1m"),
1995 ("a offset -7m", "a offset -7m"),
1996 (r#"a{c="d"}[5m] offset 1m"#, r#"a{c="d"}[5m] offset 1m"#),
1997 ("a[5m] offset 1m", "a[5m] offset 1m"),
1998 ("a[12m] offset -3m", "a[12m] offset -3m"),
1999 ("a[1h:5m] offset 1m", "a[1h:5m] offset 1m"),
2000 (r#"{__name__="a"}"#, r#"{__name__="a"}"#),
2001 (r#"a{b!="c"}[1m]"#, r#"a{b!="c"}[1m]"#),
2002 (r#"a{b=~"c"}[1m]"#, r#"a{b=~"c"}[1m]"#),
2003 (r#"a{b!~"c"}[1m]"#, r#"a{b!~"c"}[1m]"#),
2004 ("a @ 10", "a @ 10.000"),
2005 ("a[1m] @ 10", "a[1m] @ 10.000"),
2006 ("a @ start()", "a @ start()"),
2007 ("a @ end()", "a @ end()"),
2008 ("a[1m] @ start()", "a[1m] @ start()"),
2009 ("a[1m] @ end()", "a[1m] @ end()"),
2010 ];
2011
2012 let mut cases2 = vec![
2014 (
2015 r#"test{a="b"}[5y] OFFSET 3d"#,
2016 r#"test{a="b"}[5y] offset 3d"#,
2017 ),
2018 (
2019 r#"test{a="b"}[5m] OFFSET 3600"#,
2020 r#"test{a="b"}[5m] offset 1h"#,
2021 ),
2022 ("foo[3ms] @ 2.345", "foo[3ms] @ 2.345"),
2023 ("foo[4s180ms] @ 2.345", "foo[4s180ms] @ 2.345"),
2024 ("foo[4.18] @ 2.345", "foo[4s180ms] @ 2.345"),
2025 ("foo[4s18ms] @ 2.345", "foo[4s18ms] @ 2.345"),
2026 ("foo[4.018] @ 2.345", "foo[4s18ms] @ 2.345"),
2027 ("test[5]", "test[5s]"),
2028 ("some_metric[5m] @ 1m", "some_metric[5m] @ 60.000"),
2029 ("metric @ 100s", "metric @ 100.000"),
2030 ("metric @ 1m40s", "metric @ 100.000"),
2031 ("metric @ 100 offset 50", "metric @ 100.000 offset 50s"),
2032 ("metric offset 50 @ 100", "metric @ 100.000 offset 50s"),
2033 ("metric @ 0 offset -50", "metric @ 0.000 offset -50s"),
2034 ("metric offset -50 @ 0", "metric @ 0.000 offset -50s"),
2035 (
2036 r#"sum_over_time(metric{job="1"}[100] @ 100 offset 50)"#,
2037 r#"sum_over_time(metric{job="1"}[1m40s] @ 100.000 offset 50s)"#,
2038 ),
2039 (
2040 r#"sum_over_time(metric{job="1"}[100] offset 50s @ 100)"#,
2041 r#"sum_over_time(metric{job="1"}[1m40s] @ 100.000 offset 50s)"#,
2042 ),
2043 (
2044 r#"sum_over_time(metric{job="1"}[100] @ 100) + label_replace(sum_over_time(metric{job="2"}[100] @ 100), "job", "1", "", "")"#,
2045 r#"sum_over_time(metric{job="1"}[1m40s] @ 100.000) + label_replace(sum_over_time(metric{job="2"}[1m40s] @ 100.000), "job", "1", "", "")"#,
2046 ),
2047 (
2048 r#"sum_over_time(metric{job="1"}[100:1] offset 20 @ 100)"#,
2049 r#"sum_over_time(metric{job="1"}[1m40s:1s] @ 100.000 offset 20s)"#,
2050 ),
2051 ];
2052
2053 cases.append(&mut cases1);
2054 cases.append(&mut cases2);
2055 for (input, expected) in cases {
2056 let expr = crate::parser::parse(input).unwrap();
2057 assert_eq!(expected, expr.to_string())
2058 }
2059 }
2060
2061 #[test]
2062 fn test_vector_selector_to_string() {
2063 let cases = vec![
2064 (VectorSelector::default(), ""),
2065 (VectorSelector::from("foobar"), "foobar"),
2066 (
2067 {
2068 let name = Some(String::from("foobar"));
2069 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "a", "x"));
2070 VectorSelector::new(name, matchers)
2071 },
2072 r#"foobar{a="x"}"#,
2073 ),
2074 (
2075 {
2076 let matchers = Matchers::new(vec![
2077 Matcher::new(MatchOp::Equal, "a", "x"),
2078 Matcher::new(MatchOp::Equal, "b", "y"),
2079 ]);
2080 VectorSelector::new(None, matchers)
2081 },
2082 r#"{a="x",b="y"}"#,
2083 ),
2084 (
2085 {
2086 let matchers =
2087 Matchers::one(Matcher::new(MatchOp::Equal, METRIC_NAME, "foobar"));
2088 VectorSelector::new(None, matchers)
2089 },
2090 r#"{__name__="foobar"}"#,
2091 ),
2092 ];
2093
2094 for (vs, expect) in cases {
2095 assert_eq!(expect, vs.to_string())
2096 }
2097 }
2098
2099 #[test]
2100 fn test_aggregate_expr_pretty() {
2101 let cases = vec![
2102 ("sum(foo)", "sum(foo)"),
2103 (
2104 r#"sum by() (task:errors:rate10s{job="s"})"#,
2105 r#"sum(
2106 task:errors:rate10s{job="s"}
2107)"#,
2108 ),
2109 (
2110 r#"sum without(job,foo) (task:errors:rate10s{job="s"})"#,
2111 r#"sum without (job, foo) (
2112 task:errors:rate10s{job="s"}
2113)"#,
2114 ),
2115 (
2116 r#"sum(task:errors:rate10s{job="s"}) without(job,foo)"#,
2117 r#"sum without (job, foo) (
2118 task:errors:rate10s{job="s"}
2119)"#,
2120 ),
2121 (
2122 r#"sum by(job,foo) (task:errors:rate10s{job="s"})"#,
2123 r#"sum by (job, foo) (
2124 task:errors:rate10s{job="s"}
2125)"#,
2126 ),
2127 (
2128 r#"sum (task:errors:rate10s{job="s"}) by(job,foo)"#,
2129 r#"sum by (job, foo) (
2130 task:errors:rate10s{job="s"}
2131)"#,
2132 ),
2133 (
2134 r#"topk(10, ask:errors:rate10s{job="s"})"#,
2135 r#"topk(
2136 10,
2137 ask:errors:rate10s{job="s"}
2138)"#,
2139 ),
2140 (
2141 r#"sum by(job,foo) (sum by(job,foo) (task:errors:rate10s{job="s"}))"#,
2142 r#"sum by (job, foo) (
2143 sum by (job, foo) (
2144 task:errors:rate10s{job="s"}
2145 )
2146)"#,
2147 ),
2148 (
2149 r#"sum by(job,foo) (sum by(job,foo) (sum by(job,foo) (task:errors:rate10s{job="s"})))"#,
2150 r#"sum by (job, foo) (
2151 sum by (job, foo) (
2152 sum by (job, foo) (
2153 task:errors:rate10s{job="s"}
2154 )
2155 )
2156)"#,
2157 ),
2158 (
2159 r#"sum by(job,foo)
2160(sum by(job,foo) (task:errors:rate10s{job="s"}))"#,
2161 r#"sum by (job, foo) (
2162 sum by (job, foo) (
2163 task:errors:rate10s{job="s"}
2164 )
2165)"#,
2166 ),
2167 (
2168 r#"sum by(job,foo)
2169(sum(task:errors:rate10s{job="s"}) without(job,foo))"#,
2170 r#"sum by (job, foo) (
2171 sum without (job, foo) (
2172 task:errors:rate10s{job="s"}
2173 )
2174)"#,
2175 ),
2176 (
2177 r#"sum by(job,foo) # Comment 1.
2178(sum by(job,foo) ( # Comment 2.
2179task:errors:rate10s{job="s"}))"#,
2180 r#"sum by (job, foo) (
2181 sum by (job, foo) (
2182 task:errors:rate10s{job="s"}
2183 )
2184)"#,
2185 ),
2186 ];
2187
2188 for (input, expect) in cases {
2189 let expr = crate::parser::parse(input);
2190 assert_eq!(expect, expr.unwrap().pretty(0, 10));
2191 }
2192 }
2193
2194 #[test]
2195 fn test_binary_expr_pretty() {
2196 let cases = vec![
2197 ("a+b", "a + b"),
2198 (
2199 "a == bool 1",
2200 " a
2201== bool
2202 1",
2203 ),
2204 (
2205 "a == 1024000",
2206 " a
2207==
2208 1024000",
2209 ),
2210 (
2211 "a + ignoring(job) b",
2212 " a
2213+ ignoring (job)
2214 b",
2215 ),
2216 (
2217 "foo_1 + foo_2",
2218 " foo_1
2219+
2220 foo_2",
2221 ),
2222 (
2223 "foo_1 + foo_2 + foo_3",
2224 " foo_1
2225 +
2226 foo_2
2227+
2228 foo_3",
2229 ),
2230 (
2231 "foo + baar + foo_3",
2232 " foo + baar
2233+
2234 foo_3",
2235 ),
2236 (
2237 "foo_1 + foo_2 + foo_3 + foo_4",
2238 " foo_1
2239 +
2240 foo_2
2241 +
2242 foo_3
2243+
2244 foo_4",
2245 ),
2246 (
2247 "foo_1 + ignoring(foo) foo_2 + ignoring(job) group_left foo_3 + on(instance) group_right foo_4",
2248
2249 " foo_1
2250 + ignoring (foo)
2251 foo_2
2252 + ignoring (job) group_left ()
2253 foo_3
2254+ on (instance) group_right ()
2255 foo_4",
2256 ),
2257 ];
2258
2259 for (input, expect) in cases {
2260 let expr = crate::parser::parse(input);
2261 assert_eq!(expect, expr.unwrap().pretty(0, 10));
2262 }
2263 }
2264
2265 #[test]
2266 fn test_call_expr_pretty() {
2267 let cases = vec![
2268 (
2269 "rate(foo[1m])",
2270 "rate(
2271 foo[1m]
2272)",
2273 ),
2274 (
2275 "sum_over_time(foo[1m])",
2276 "sum_over_time(
2277 foo[1m]
2278)",
2279 ),
2280 (
2281 "rate(long_vector_selector[10m:1m] @ start() offset 1m)",
2282 "rate(
2283 long_vector_selector[10m:1m] @ start() offset 1m
2284)",
2285 ),
2286 (
2287 "histogram_quantile(0.9, rate(foo[1m]))",
2288 "histogram_quantile(
2289 0.9,
2290 rate(
2291 foo[1m]
2292 )
2293)",
2294 ),
2295 (
2296 "histogram_quantile(0.9, rate(foo[1m] @ start()))",
2297 "histogram_quantile(
2298 0.9,
2299 rate(
2300 foo[1m] @ start()
2301 )
2302)",
2303 ),
2304 (
2305 "max_over_time(rate(demo_api_request_duration_seconds_count[1m])[1m:] @ start() offset 1m)",
2306 "max_over_time(
2307 rate(
2308 demo_api_request_duration_seconds_count[1m]
2309 )[1m:] @ start() offset 1m
2310)",
2311 ),
2312 (
2313 r#"label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*")"#,
2314 r#"label_replace(
2315 up{job="api-server",service="a:c"},
2316 "foo",
2317 "$1",
2318 "service",
2319 "(.*):.*"
2320)"#,
2321 ),
2322 (
2323 r#"label_replace(label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*"), "foo", "$1", "service", "(.*):.*")"#,
2324 r#"label_replace(
2325 label_replace(
2326 up{job="api-server",service="a:c"},
2327 "foo",
2328 "$1",
2329 "service",
2330 "(.*):.*"
2331 ),
2332 "foo",
2333 "$1",
2334 "service",
2335 "(.*):.*"
2336)"#,
2337 ),
2338 ];
2339
2340 for (input, expect) in cases {
2341 let expr = crate::parser::parse(input);
2342 assert_eq!(expect, expr.unwrap().pretty(0, 10));
2343 }
2344 }
2345
2346 #[test]
2347 fn test_paren_expr_pretty() {
2348 let cases = vec![
2349 ("(foo)", "(foo)"),
2350 (
2351 "(_foo_long_)",
2352 "(
2353 _foo_long_
2354)",
2355 ),
2356 (
2357 "((foo_long))",
2358 "(
2359 (foo_long)
2360)",
2361 ),
2362 (
2363 "((_foo_long_))",
2364 "(
2365 (
2366 _foo_long_
2367 )
2368)",
2369 ),
2370 (
2371 "(((foo_long)))",
2372 "(
2373 (
2374 (foo_long)
2375 )
2376)",
2377 ),
2378 ("(1 + 2)", "(1 + 2)"),
2379 (
2380 "(foo + bar)",
2381 "(
2382 foo + bar
2383)",
2384 ),
2385 (
2386 "(foo_long + bar_long)",
2387 "(
2388 foo_long
2389 +
2390 bar_long
2391)",
2392 ),
2393 (
2394 "(foo_long + bar_long + bar_2_long)",
2395 "(
2396 foo_long
2397 +
2398 bar_long
2399 +
2400 bar_2_long
2401)",
2402 ),
2403 (
2404 "((foo_long + bar_long) + bar_2_long)",
2405 "(
2406 (
2407 foo_long
2408 +
2409 bar_long
2410 )
2411 +
2412 bar_2_long
2413)",
2414 ),
2415 (
2416 "(1111 + 2222)",
2417 "(
2418 1111
2419 +
2420 2222
2421)",
2422 ),
2423 (
2424 "(sum_over_time(foo[1m]))",
2425 "(
2426 sum_over_time(
2427 foo[1m]
2428 )
2429)",
2430 ),
2431 (
2432 r#"(label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*"))"#,
2433 r#"(
2434 label_replace(
2435 up{job="api-server",service="a:c"},
2436 "foo",
2437 "$1",
2438 "service",
2439 "(.*):.*"
2440 )
2441)"#,
2442 ),
2443 (
2444 r#"(label_replace(label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*"), "foo", "$1", "service", "(.*):.*"))"#,
2445 r#"(
2446 label_replace(
2447 label_replace(
2448 up{job="api-server",service="a:c"},
2449 "foo",
2450 "$1",
2451 "service",
2452 "(.*):.*"
2453 ),
2454 "foo",
2455 "$1",
2456 "service",
2457 "(.*):.*"
2458 )
2459)"#,
2460 ),
2461 (
2462 r#"(label_replace(label_replace((up{job="api-server",service="a:c"}), "foo", "$1", "service", "(.*):.*"), "foo", "$1", "service", "(.*):.*"))"#,
2463 r#"(
2464 label_replace(
2465 label_replace(
2466 (
2467 up{job="api-server",service="a:c"}
2468 ),
2469 "foo",
2470 "$1",
2471 "service",
2472 "(.*):.*"
2473 ),
2474 "foo",
2475 "$1",
2476 "service",
2477 "(.*):.*"
2478 )
2479)"#,
2480 ),
2481 ];
2482
2483 for (input, expect) in cases {
2484 let expr = crate::parser::parse(input);
2485 assert_eq!(expect, expr.unwrap().pretty(0, 10));
2486 }
2487 }
2488
2489 #[test]
2490 fn test_unary_expr_pretty() {
2491 let cases = vec![
2492 ("-1", "-1"),
2493 ("-vector_selector", "-vector_selector"),
2494 (
2495 "(-vector_selector)",
2496 "(
2497 -vector_selector
2498)",
2499 ),
2500 (
2501 "-histogram_quantile(0.9,rate(foo[1m]))",
2502 "-histogram_quantile(
2503 0.9,
2504 rate(
2505 foo[1m]
2506 )
2507)",
2508 ),
2509 (
2510 "-histogram_quantile(0.99, sum by (le) (rate(foo[1m])))",
2511 "-histogram_quantile(
2512 0.99,
2513 sum by (le) (
2514 rate(
2515 foo[1m]
2516 )
2517 )
2518)",
2519 ),
2520 (
2521 "-histogram_quantile(0.9, -rate(foo[1m] @ start()))",
2522 "-histogram_quantile(
2523 0.9,
2524 -rate(
2525 foo[1m] @ start()
2526 )
2527)",
2528 ),
2529 (
2530 "(-histogram_quantile(0.9, -rate(foo[1m] @ start())))",
2531 "(
2532 -histogram_quantile(
2533 0.9,
2534 -rate(
2535 foo[1m] @ start()
2536 )
2537 )
2538)",
2539 ),
2540 ];
2541
2542 for (input, expect) in cases {
2543 let expr = crate::parser::parse(input);
2544 assert_eq!(expect, expr.unwrap().pretty(0, 10));
2545 }
2546 }
2547
2548 #[test]
2549 fn test_expr_pretty() {
2550 let cases = vec![
2552 (
2553 r#"(node_filesystem_avail_bytes{job="node",fstype!=""} / node_filesystem_size_bytes{job="node",fstype!=""} * 100 < 40 and predict_linear(node_filesystem_avail_bytes{job="node",fstype!=""}[6h], 24*60*60) < 0 and node_filesystem_readonly{job="node",fstype!=""} == 0)"#,
2554 r#"(
2555 node_filesystem_avail_bytes{fstype!="",job="node"}
2556 /
2557 node_filesystem_size_bytes{fstype!="",job="node"}
2558 *
2559 100
2560 <
2561 40
2562 and
2563 predict_linear(
2564 node_filesystem_avail_bytes{fstype!="",job="node"}[6h],
2565 24 * 60
2566 *
2567 60
2568 )
2569 <
2570 0
2571 and
2572 node_filesystem_readonly{fstype!="",job="node"}
2573 ==
2574 0
2575)"#,
2576 ),
2577 (
2578 r#"(node_filesystem_avail_bytes{job="node",fstype!=""} / node_filesystem_size_bytes{job="node",fstype!=""} * 100 < 20 and predict_linear(node_filesystem_avail_bytes{job="node",fstype!=""}[6h], 4*60*60) < 0 and node_filesystem_readonly{job="node",fstype!=""} == 0)"#,
2579 r#"(
2580 node_filesystem_avail_bytes{fstype!="",job="node"}
2581 /
2582 node_filesystem_size_bytes{fstype!="",job="node"}
2583 *
2584 100
2585 <
2586 20
2587 and
2588 predict_linear(
2589 node_filesystem_avail_bytes{fstype!="",job="node"}[6h],
2590 4 * 60
2591 *
2592 60
2593 )
2594 <
2595 0
2596 and
2597 node_filesystem_readonly{fstype!="",job="node"}
2598 ==
2599 0
2600)"#,
2601 ),
2602 (
2603 r#"(node_timex_offset_seconds > 0.05 and deriv(node_timex_offset_seconds[5m]) >= 0) or (node_timex_offset_seconds < -0.05 and deriv(node_timex_offset_seconds[5m]) <= 0)"#,
2604 r#" (
2605 node_timex_offset_seconds
2606 >
2607 0.05
2608 and
2609 deriv(
2610 node_timex_offset_seconds[5m]
2611 )
2612 >=
2613 0
2614 )
2615or
2616 (
2617 node_timex_offset_seconds
2618 <
2619 -0.05
2620 and
2621 deriv(
2622 node_timex_offset_seconds[5m]
2623 )
2624 <=
2625 0
2626 )"#,
2627 ),
2628 (
2629 r#"1 - ((node_memory_MemAvailable_bytes{job="node"} or (node_memory_Buffers_bytes{job="node"} + node_memory_Cached_bytes{job="node"} + node_memory_MemFree_bytes{job="node"} + node_memory_Slab_bytes{job="node"}) ) / node_memory_MemTotal_bytes{job="node"})"#,
2630 r#" 1
2631-
2632 (
2633 (
2634 node_memory_MemAvailable_bytes{job="node"}
2635 or
2636 (
2637 node_memory_Buffers_bytes{job="node"}
2638 +
2639 node_memory_Cached_bytes{job="node"}
2640 +
2641 node_memory_MemFree_bytes{job="node"}
2642 +
2643 node_memory_Slab_bytes{job="node"}
2644 )
2645 )
2646 /
2647 node_memory_MemTotal_bytes{job="node"}
2648 )"#,
2649 ),
2650 (
2651 r#"min by (job, integration) (rate(alertmanager_notifications_failed_total{job="alertmanager", integration=~".*"}[5m]) / rate(alertmanager_notifications_total{job="alertmanager", integration="~.*"}[5m])) > 0.01"#,
2652 r#" min by (job, integration) (
2653 rate(
2654 alertmanager_notifications_failed_total{integration=~".*",job="alertmanager"}[5m]
2655 )
2656 /
2657 rate(
2658 alertmanager_notifications_total{integration="~.*",job="alertmanager"}[5m]
2659 )
2660 )
2661>
2662 0.01"#,
2663 ),
2664 (
2665 r#"(count by (job) (changes(process_start_time_seconds{job="alertmanager"}[10m]) > 4) / count by (job) (up{job="alertmanager"})) >= 0.5"#,
2666 r#" (
2667 count by (job) (
2668 changes(
2669 process_start_time_seconds{job="alertmanager"}[10m]
2670 )
2671 >
2672 4
2673 )
2674 /
2675 count by (job) (
2676 up{job="alertmanager"}
2677 )
2678 )
2679>=
2680 0.5"#,
2681 ),
2682 ];
2683
2684 for (input, expect) in cases {
2685 let expr = crate::parser::parse(input);
2686 assert_eq!(expect, expr.unwrap().pretty(0, 10));
2687 }
2688 }
2689
2690 #[test]
2691 fn test_step_invariant_pretty() {
2692 let cases = vec![
2693 ("a @ 1", "a @ 1.000"),
2694 ("a @ start()", "a @ start()"),
2695 ("vector_selector @ start()", "vector_selector @ start()"),
2696 ];
2697
2698 for (input, expect) in cases {
2699 let expr = crate::parser::parse(input);
2700 assert_eq!(expect, expr.unwrap().pretty(0, 10));
2701 }
2702 }
2703
2704 #[test]
2705 fn test_prettify() {
2706 let cases = vec![
2707 ("vector_selector", "vector_selector"),
2708 (
2709 r#"vector_selector{fooooooooooooooooo="barrrrrrrrrrrrrrrrrrr",barrrrrrrrrrrrrrrrrrr="fooooooooooooooooo",process_name="alertmanager"}"#,
2710 r#"vector_selector{barrrrrrrrrrrrrrrrrrr="fooooooooooooooooo",fooooooooooooooooo="barrrrrrrrrrrrrrrrrrr",process_name="alertmanager"}"#,
2711 ),
2712 (
2713 r#"matrix_selector{fooooooooooooooooo="barrrrrrrrrrrrrrrrrrr",barrrrrrrrrrrrrrrrrrr="fooooooooooooooooo",process_name="alertmanager"}[1y2w3d]"#,
2714 r#"matrix_selector{barrrrrrrrrrrrrrrrrrr="fooooooooooooooooo",fooooooooooooooooo="barrrrrrrrrrrrrrrrrrr",process_name="alertmanager"}[382d]"#,
2715 ),
2716 ];
2717
2718 for (input, expect) in cases {
2719 assert_eq!(expect, crate::parser::parse(input).unwrap().prettify());
2720 }
2721 }
2722
2723 #[test]
2724 fn test_eval_stmt_to_string() {
2725 let query = r#"http_requests_total{job="apiserver", handler="/api/comments"}[5m]"#;
2726 let start = "2024-10-08T07:15:00.022978+00:00";
2727 let end = "2024-10-08T07:15:30.012978+00:00";
2728 let expect = r#"[http_requests_total{handler="/api/comments",job="apiserver"}[5m]] @ [2024-10-08T07:15:00.022978+00:00, 2024-10-08T07:15:30.012978+00:00, 1m, 5m]"#;
2729
2730 let stmt = EvalStmt {
2731 expr: crate::parser::parse(query).unwrap(),
2732 start: DateTime::parse_from_rfc3339(start)
2733 .unwrap()
2734 .with_timezone(&Utc)
2735 .into(),
2736 end: DateTime::parse_from_rfc3339(end)
2737 .unwrap()
2738 .with_timezone(&Utc)
2739 .into(),
2740 interval: Duration::from_secs(60),
2741 lookback_delta: Duration::from_secs(300),
2742 };
2743
2744 assert_eq!(expect, stmt.to_string());
2745 }
2746}