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