From f68a2adf315fa3de2f01f9298d898911b6e4b1a2 Mon Sep 17 00:00:00 2001 From: yuanbohan Date: Fri, 7 Jul 2023 18:43:58 +0800 Subject: [PATCH 1/5] fix: set metric name twice --- src/parser/ast.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/parser/ast.rs b/src/parser/ast.rs index bcfeb93..de4ba4b 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -976,16 +976,13 @@ fn check_ast_for_call(ex: Call) -> Result { } // special cases from https://prometheus.io/docs/prometheus/latest/querying/functions - if name.eq_ignore_ascii_case("exp") { + if name.eq("exp") { if let Some(val) = ex.args.first().and_then(|ex| ex.scalar_value()) { if val.is_nan() || val.is_infinite() { return Ok(Expr::Call(ex)); } } - } else if name.eq_ignore_ascii_case("ln") - || name.eq_ignore_ascii_case("log2") - || name.eq_ignore_ascii_case("log10") - { + } else if name.eq("ln") || name.eq("log2") || name.eq("log10") { if let Some(val) = ex.args.first().and_then(|ex| ex.scalar_value()) { if val.is_nan() || val.is_infinite() || val <= 0.0 { return Ok(Expr::Call(ex)); @@ -1038,14 +1035,15 @@ fn check_ast_for_vector_selector(ex: VectorSelector) -> Result { return Err("vector selector must contain at least one non-empty matcher".into()); } - let mut du = ex.matchers.find_matchers(METRIC_NAME); - if du.len() >= 2 { - // this is to ensure that the err information can be predicted with fixed order - du.sort(); - return Err(format!( - "metric name must not be set twice: '{}' or '{}'", - du[0], du[1] - )); + if ex.name.is_some() { + let name_matchers = ex.matchers.find_matchers(METRIC_NAME); + if name_matchers.len() > 0 { + return Err(format!( + "metric name must not be set twice: '{}' or '{}'", + ex.name.unwrap(), + name_matchers[0] + )); + } } Ok(Expr::VectorSelector(ex)) From b92b92b9815bc3e96b119842d8e64a8d241d5a24 Mon Sep 17 00:00:00 2001 From: yuanbohan Date: Sat, 8 Jul 2023 00:05:00 +0800 Subject: [PATCH 2/5] fix: support multiple __name__ matcher --- src/label/matcher.rs | 15 +- src/parser/ast.rs | 44 +++--- src/parser/parse.rs | 318 +++++++++++++++++++++++-------------------- src/parser/promql.y | 15 +- 4 files changed, 201 insertions(+), 191 deletions(-) diff --git a/src/label/matcher.rs b/src/label/matcher.rs index 25418b8..d90f85e 100644 --- a/src/label/matcher.rs +++ b/src/label/matcher.rs @@ -136,13 +136,14 @@ impl Matchers { self.matchers.is_empty() || self.matchers.iter().all(|m| m.is_match("")) } - /// find all the matchers whose name equals the specified name. - pub fn find_matchers(&self, name: &str) -> Vec<&String> { - self.matchers - .iter() - .filter(|m| m.name.eq_ignore_ascii_case(name)) - .map(|m| &m.value) - .collect() + /// find the matcher's value whose name equals the specified name. + pub fn find_matcher(&self, name: &str) -> Option { + for m in &self.matchers { + if m.name.eq(name) { + return Some(m.value.clone()); + } + } + None } } diff --git a/src/parser/ast.rs b/src/parser/ast.rs index de4ba4b..0ba46a1 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::label::{Labels, Matcher, Matchers, METRIC_NAME}; +use crate::label::{Labels, Matchers, METRIC_NAME}; use crate::parser::token::{ self, token_display, T_BOTTOMK, T_COUNT_VALUES, T_END, T_QUANTILE, T_START, T_TOPK, }; @@ -369,12 +369,11 @@ pub struct VectorSelector { impl From for VectorSelector { fn from(name: String) -> Self { - let matcher = Matcher::new_eq_metric_matcher(name.clone()); VectorSelector { name: Some(name), offset: None, at: None, - matchers: Matchers::one(matcher), + matchers: Matchers::empty(), } } } @@ -386,15 +385,14 @@ impl From for VectorSelector { /// Basic usage: /// /// ``` rust -/// use promql_parser::parser::{Expr, VectorSelector}; -/// use promql_parser::label::{MatchOp, Matcher, Matchers}; +/// use promql_parser::label::Matchers; +/// use promql_parser::parser::VectorSelector; /// -/// let matcher = Matcher::new_eq_metric_matcher(String::from("foo")); /// let vs = VectorSelector { /// name: Some(String::from("foo")), /// offset: None, /// at: None, -/// matchers: Matchers::one(matcher), +/// matchers: Matchers::empty(), /// }; /// /// assert_eq!(VectorSelector::from("foo"), vs); @@ -768,12 +766,11 @@ impl From for Expr { /// Basic usage: /// /// ``` rust +/// use promql_parser::label::Matchers; /// use promql_parser::parser::{Expr, VectorSelector}; -/// use promql_parser::label::{MatchOp, Matcher, Matchers}; /// /// let name = String::from("foo"); -/// let matcher = Matcher::new_eq_metric_matcher(name.clone()); -/// let vs = Expr::new_vector_selector(Some(name), Matchers::one(matcher)); +/// let vs = Expr::new_vector_selector(Some(name), Matchers::empty()); /// /// assert_eq!(Expr::from(VectorSelector::from("foo")), vs.unwrap()); /// ``` @@ -1029,24 +1026,21 @@ fn check_ast_for_subquery(ex: SubqueryExpr) -> Result { } fn check_ast_for_vector_selector(ex: VectorSelector) -> Result { - // A Vector selector must contain at least one non-empty matcher to prevent - // implicit selection of all metrics (e.g. by a typo). - if ex.matchers.is_empty_matchers() { - return Err("vector selector must contain at least one non-empty matcher".into()); - } - - if ex.name.is_some() { - let name_matchers = ex.matchers.find_matchers(METRIC_NAME); - if name_matchers.len() > 0 { - return Err(format!( + match ex.name { + Some(ref name) => match ex.matchers.find_matcher(METRIC_NAME) { + Some(val) => Err(format!( "metric name must not be set twice: '{}' or '{}'", - ex.name.unwrap(), - name_matchers[0] - )); + name, val + )), + None => Ok(Expr::VectorSelector(ex)), + }, + None if ex.matchers.is_empty_matchers() => { + // When name is None, a vector selector must contain at least one non-empty matcher + // to prevent implicit selection of all metrics (e.g. by a typo). + Err("vector selector must contain at least one non-empty matcher".into()) } + _ => Ok(Expr::VectorSelector(ex)), } - - Ok(Expr::VectorSelector(ex)) } #[cfg(test)] diff --git a/src/parser/parse.rs b/src/parser/parse.rs index 9991411..8f9edb5 100644 --- a/src/parser/parse.rs +++ b/src/parser/parse.rs @@ -36,7 +36,7 @@ pub fn parse(input: &str) -> Result { mod tests { use regex::Regex; - use crate::label::{MatchOp, Matcher, Matchers}; + use crate::label::{MatchOp, Matcher, Matchers, METRIC_NAME}; use crate::parser::function::get_function; use crate::parser::{ token, AtModifier as At, BinModifier, Expr, FunctionArgs, LabelModifier, Offset, @@ -647,10 +647,11 @@ mod tests { r#"method_code:http_errors:rate5m{code="500"} / ignoring(code) method:http_requests:rate5m"#, { let name = String::from("method_code:http_errors:rate5m"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new(MatchOp::Equal, String::from("code"), String::from("500")), - ])); + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("code"), + String::from("500"), + )); let lhs = Expr::new_vector_selector(Some(name), matchers).unwrap(); Expr::new_binary_expr( lhs, @@ -875,33 +876,31 @@ mod tests { Expr::from(VectorSelector::from("foo")).at_expr(At::try_from(-33f64).unwrap()), ), (r#"foo:bar{a="bc"}"#, { - let name = String::from("foo:bar"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new(MatchOp::Equal, String::from("a"), String::from("bc")), - ])); - Expr::new_vector_selector(Some(name), matchers) + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("a"), + String::from("bc"), + )); + Expr::new_vector_selector(Some(String::from("foo:bar")), matchers) }), (r#"foo{NaN='bc'}"#, { - let name = String::from("foo"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new(MatchOp::Equal, String::from("NaN"), String::from("bc")), - ])); - Expr::new_vector_selector(Some(name), matchers) + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("NaN"), + String::from("bc"), + )); + Expr::new_vector_selector(Some(String::from("foo")), matchers) }), (r#"foo{bar='}'}"#, { - let name = String::from("foo"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new(MatchOp::Equal, String::from("bar"), String::from("}")), - ])); - Expr::new_vector_selector(Some(name), matchers) + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("bar"), + String::from("}"), + )); + Expr::new_vector_selector(Some(String::from("foo")), matchers) }), (r#"foo{a="b", foo!="bar", test=~"test", bar!~"baz"}"#, { - let name = String::from("foo"); let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), Matcher::new(MatchOp::Equal, String::from("a"), String::from("b")), Matcher::new(MatchOp::NotEqual, String::from("foo"), String::from("bar")), Matcher::new_matcher( @@ -917,12 +916,11 @@ mod tests { ) .unwrap(), ])); - Expr::new_vector_selector(Some(name), matchers) + Expr::new_vector_selector(Some(String::from("foo")), matchers) }), (r#"foo{a="b", foo!="bar", test=~"test", bar!~"baz",}"#, { let name = String::from("foo"); let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), Matcher::new(MatchOp::Equal, String::from("a"), String::from("b")), Matcher::new(MatchOp::NotEqual, String::from("foo"), String::from("bar")), Matcher::new_matcher( @@ -940,6 +938,31 @@ mod tests { ])); Expr::new_vector_selector(Some(name), matchers) }), + // the following multiple __name__ matcher test cases are not from prometheus + (r#"{__name__="foo",__name__="bar"}"#, { + let matchers = Matchers::new(HashSet::from([ + Matcher::new_eq_metric_matcher(String::from("foo")), + Matcher::new_eq_metric_matcher(String::from("bar")), + ])); + Expr::new_vector_selector(None, matchers) + }), + (r#"{__name__=~"foo.+",__name__=~".*bar"}"#, { + let matchers = Matchers::new(HashSet::from([ + Matcher::new_matcher( + token::T_EQL_REGEX, + String::from(METRIC_NAME), + String::from("foo.+"), + ) + .unwrap(), + Matcher::new_matcher( + token::T_EQL_REGEX, + String::from(METRIC_NAME), + String::from(".*bar"), + ) + .unwrap(), + ])); + Expr::new_vector_selector(None, matchers) + }), ]; assert_cases(Case::new_result_cases(cases)); @@ -992,7 +1015,7 @@ mod tests { ), ( r#"foo{__name__="bar"}"#, - "metric name must not be set twice: 'bar' or 'foo'", + "metric name must not be set twice: 'foo' or 'bar'", ), ( "foo{__name__= =}", @@ -1080,25 +1103,25 @@ mod tests { .and_then(|ex| ex.offset_expr(Offset::Pos(duration::WEEK_DURATION * 2))), ), (r#"test{a="b"}[5y] OFFSET 3d"#, { - let name = String::from("test"); - let name_matcher = Matcher::new_eq_metric_matcher(name.clone()); - let label_matcher = - Matcher::new(MatchOp::Equal, String::from("a"), String::from("b")); Expr::new_vector_selector( - Some(name), - Matchers::new(HashSet::from([name_matcher, label_matcher])), + Some(String::from("test")), + Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("a"), + String::from("b"), + )), ) .and_then(|ex| Expr::new_matrix_selector(ex, duration::YEAR_DURATION * 5)) .and_then(|ex| ex.offset_expr(Offset::Pos(duration::DAY_DURATION * 3))) }), (r#"test{a="b"}[5y] @ 1603774699"#, { - let name = String::from("test"); - let name_matcher = Matcher::new_eq_metric_matcher(name.clone()); - let label_matcher = - Matcher::new(MatchOp::Equal, String::from("a"), String::from("b")); Expr::new_vector_selector( - Some(name), - Matchers::new(HashSet::from([name_matcher, label_matcher])), + Some(String::from("test")), + Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("a"), + String::from("b"), + )), ) .and_then(|ex| Expr::new_matrix_selector(ex, duration::YEAR_DURATION * 5)) .and_then(|ex| ex.at_expr(At::try_from(1603774699_f64).unwrap())) @@ -1299,10 +1322,11 @@ mod tests { ), (r#"floor(some_metric{foo!="bar"})"#, { let name = String::from("some_metric"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new(MatchOp::NotEqual, String::from("foo"), String::from("bar")), - ])); + let matchers = Matchers::one(Matcher::new( + MatchOp::NotEqual, + String::from("foo"), + String::from("bar"), + )); let ex = Expr::new_vector_selector(Some(name), matchers).unwrap(); Expr::new_call(get_function("floor").unwrap(), FunctionArgs::new_args(ex)) }), @@ -1329,17 +1353,17 @@ mod tests { // cases from https://prometheus.io/docs/prometheus/latest/querying/functions (r#"absent(nonexistent{job="myjob"})"#, { let name = String::from("nonexistent"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new(MatchOp::Equal, String::from("job"), String::from("myjob")), - ])); + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("job"), + String::from("myjob"), + )); let ex = Expr::new_vector_selector(Some(name), matchers).unwrap(); Expr::new_call(get_function("absent").unwrap(), FunctionArgs::new_args(ex)) }), (r#"absent(nonexistent{job="myjob",instance=~".*"})"#, { let name = String::from("nonexistent"); let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), Matcher::new(MatchOp::Equal, String::from("job"), String::from("myjob")), Matcher::new( MatchOp::Re(Regex::new(".*").unwrap()), @@ -1353,10 +1377,11 @@ mod tests { }), (r#"absent(sum(nonexistent{job="myjob"}))"#, { let name = String::from("nonexistent"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new(MatchOp::Equal, String::from("job"), String::from("myjob")), - ])); + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("job"), + String::from("myjob"), + )); Expr::new_vector_selector(Some(name), matchers) .and_then(|ex| { Expr::new_aggregate_expr(token::T_SUM, None, FunctionArgs::new_args(ex)) @@ -1367,10 +1392,11 @@ mod tests { }), (r#"absent_over_time(nonexistent{job="myjob"}[1h])"#, { let name = String::from("nonexistent"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new(MatchOp::Equal, String::from("job"), String::from("myjob")), - ])); + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("job"), + String::from("myjob"), + )); Expr::new_vector_selector(Some(name), matchers) .and_then(|ex| Expr::new_matrix_selector(ex, duration::HOUR_DURATION)) .and_then(|ex| { @@ -1385,7 +1411,6 @@ mod tests { { let name = String::from("nonexistent"); let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), Matcher::new(MatchOp::Equal, String::from("job"), String::from("myjob")), Matcher::new( MatchOp::Re(Regex::new(".*").unwrap()), @@ -1405,10 +1430,11 @@ mod tests { ), (r#"delta(cpu_temp_celsius{host="zeus"}[2h])"#, { let name = String::from("cpu_temp_celsius"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new(MatchOp::Equal, String::from("host"), String::from("zeus")), - ])); + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("host"), + String::from("zeus"), + )); Expr::new_vector_selector(Some(name), matchers) .and_then(|ex| Expr::new_matrix_selector(ex, duration::HOUR_DURATION * 2)) .and_then(|ex| { @@ -1517,14 +1543,11 @@ mod tests { ), (r#"increase(http_requests_total{job="api-server"}[5m])"#, { let name = String::from("http_requests_total"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new( - MatchOp::Equal, - String::from("job"), - String::from("api-server"), - ), - ])); + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("job"), + String::from("api-server"), + )); Expr::new_vector_selector(Some(name), matchers) .and_then(|ex| Expr::new_matrix_selector(ex, duration::MINUTE_DURATION * 5)) .and_then(|ex| { @@ -1536,14 +1559,11 @@ mod tests { }), (r#"irate(http_requests_total{job="api-server"}[5m])"#, { let name = String::from("http_requests_total"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new( - MatchOp::Equal, - String::from("job"), - String::from("api-server"), - ), - ])); + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("job"), + String::from("api-server"), + )); Expr::new_vector_selector(Some(name), matchers) .and_then(|ex| Expr::new_matrix_selector(ex, duration::MINUTE_DURATION * 5)) .and_then(|ex| { @@ -1555,7 +1575,6 @@ mod tests { { let name = String::from("up"); let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), Matcher::new(MatchOp::Equal, String::from("src1"), String::from("a")), Matcher::new(MatchOp::Equal, String::from("src2"), String::from("b")), Matcher::new(MatchOp::Equal, String::from("src3"), String::from("c")), @@ -1583,7 +1602,6 @@ mod tests { { let name = String::from("up"); let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), Matcher::new(MatchOp::Equal, String::from("service"), String::from("a:c")), Matcher::new( MatchOp::Equal, @@ -1762,12 +1780,12 @@ mod tests { fn test_subquery() { let cases = vec![ (r#"foo{bar="baz"}[10m:6s]"#, { - let name = String::from("foo"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new(MatchOp::Equal, String::from("bar"), String::from("baz")), - ])); - Expr::new_vector_selector(Some(name), matchers).and_then(|ex| { + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("bar"), + String::from("baz"), + )); + Expr::new_vector_selector(Some(String::from("foo")), matchers).and_then(|ex| { Expr::new_subquery_expr( ex, duration::MINUTE_DURATION * 10, @@ -1776,12 +1794,12 @@ mod tests { }) }), (r#"foo{bar="baz"}[10m5s:1h6ms]"#, { - let name = String::from("foo"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new(MatchOp::Equal, String::from("bar"), String::from("baz")), - ])); - Expr::new_vector_selector(Some(name), matchers).and_then(|ex| { + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("bar"), + String::from("baz"), + )); + Expr::new_vector_selector(Some(String::from("foo")), matchers).and_then(|ex| { Expr::new_subquery_expr( ex, duration::MINUTE_DURATION * 10 + duration::SECOND_DURATION * 5, @@ -1794,12 +1812,12 @@ mod tests { Expr::new_subquery_expr(ex, duration::MINUTE_DURATION * 10, None) }), (r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:5s])"#, { - let name = String::from("foo"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new(MatchOp::Equal, String::from("bar"), String::from("baz")), - ])); - Expr::new_vector_selector(Some(name), matchers) + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("bar"), + String::from("baz"), + )); + Expr::new_vector_selector(Some(String::from("foo")), matchers) .and_then(|ex| Expr::new_matrix_selector(ex, Duration::from_secs(2))) .and_then(|ex| { Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex)) @@ -1819,12 +1837,12 @@ mod tests { }) }), (r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s]"#, { - let name = String::from("foo"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new(MatchOp::Equal, String::from("bar"), String::from("baz")), - ])); - Expr::new_vector_selector(Some(name), matchers) + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("bar"), + String::from("baz"), + )); + Expr::new_vector_selector(Some(String::from("foo")), matchers) .and_then(|ex| Expr::new_matrix_selector(ex, Duration::from_secs(2))) .and_then(|ex| { Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex)) @@ -1847,12 +1865,12 @@ mod tests { ( r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] offset 4m)[4m:3s]"#, { - let name = String::from("foo"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new(MatchOp::Equal, String::from("bar"), String::from("baz")), - ])); - Expr::new_vector_selector(Some(name), matchers) + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("bar"), + String::from("baz"), + )); + Expr::new_vector_selector(Some(String::from("foo")), matchers) .and_then(|ex| Expr::new_matrix_selector(ex, Duration::from_secs(2))) .and_then(|ex| { Expr::new_call( @@ -1882,12 +1900,12 @@ mod tests { ( r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] @ 1603775091)[4m:3s]"#, { - let name = String::from("foo"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new(MatchOp::Equal, String::from("bar"), String::from("baz")), - ])); - Expr::new_vector_selector(Some(name), matchers) + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("bar"), + String::from("baz"), + )); + Expr::new_vector_selector(Some(String::from("foo")), matchers) .and_then(|ex| Expr::new_matrix_selector(ex, Duration::from_secs(2))) .and_then(|ex| { Expr::new_call( @@ -1917,12 +1935,12 @@ mod tests { ( r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] @ -160377509)[4m:3s]"#, { - let name = String::from("foo"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new(MatchOp::Equal, String::from("bar"), String::from("baz")), - ])); - Expr::new_vector_selector(Some(name), matchers) + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("bar"), + String::from("baz"), + )); + Expr::new_vector_selector(Some(String::from("foo")), matchers) .and_then(|ex| Expr::new_matrix_selector(ex, Duration::from_secs(2))) .and_then(|ex| { Expr::new_call( @@ -2032,45 +2050,43 @@ mod tests { .and_then(|ex| ex.offset_expr(Offset::Pos(duration::MINUTE_DURATION))), ), (r#"(foo + bar{nm="val"})[5m:]"#, { - let name = String::from("bar"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new(MatchOp::Equal, String::from("nm"), String::from("val")), - ])); - + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("nm"), + String::from("val"), + )); Expr::new_binary_expr( Expr::from(VectorSelector::from("foo")), token::T_ADD, None, - Expr::new_vector_selector(Some(name), matchers).unwrap(), + Expr::new_vector_selector(Some(String::from("bar")), matchers).unwrap(), ) .and_then(|ex| Expr::new_paren_expr(ex)) .and_then(|ex| Expr::new_subquery_expr(ex, duration::MINUTE_DURATION * 5, None)) }), (r#"(foo + bar{nm="val"})[5m:] offset 10m"#, { - let name = String::from("bar"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new(MatchOp::Equal, String::from("nm"), String::from("val")), - ])); - + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("nm"), + String::from("val"), + )); Expr::new_binary_expr( Expr::from(VectorSelector::from("foo")), token::T_ADD, None, - Expr::new_vector_selector(Some(name), matchers).unwrap(), + Expr::new_vector_selector(Some(String::from("bar")), matchers).unwrap(), ) .and_then(|ex| Expr::new_paren_expr(ex)) .and_then(|ex| Expr::new_subquery_expr(ex, duration::MINUTE_DURATION * 5, None)) .and_then(|ex| ex.offset_expr(Offset::Pos(duration::MINUTE_DURATION * 10))) }), (r#"(foo + bar{nm="val"} @ 1234)[5m:] @ 1603775019"#, { - let name = String::from("bar"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new(MatchOp::Equal, String::from("nm"), String::from("val")), - ])); - let rhs = Expr::new_vector_selector(Some(name), matchers) + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("nm"), + String::from("val"), + )); + let rhs = Expr::new_vector_selector(Some(String::from("bar")), matchers) .and_then(|ex| ex.at_expr(At::try_from(1234_f64).unwrap())) .unwrap(); @@ -2149,18 +2165,20 @@ mod tests { ("end", Ok(Expr::from(VectorSelector::from("end")))), (r#"start{end="foo"}"#, { let name = String::from("start"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new(MatchOp::Equal, String::from("end"), String::from("foo")), - ])); + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("end"), + String::from("foo"), + )); Expr::new_vector_selector(Some(name), matchers) }), (r#"end{start="foo"}"#, { let name = String::from("end"); - let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(name.clone()), - Matcher::new(MatchOp::Equal, String::from("start"), String::from("foo")), - ])); + let matchers = Matchers::one(Matcher::new( + MatchOp::Equal, + String::from("start"), + String::from("foo"), + )); Expr::new_vector_selector(Some(name), matchers) }), ("foo unless on(start) bar", { diff --git a/src/parser/promql.y b/src/parser/promql.y index 8d4bc1b..8125ebb 100644 --- a/src/parser/promql.y +++ b/src/parser/promql.y @@ -389,19 +389,16 @@ unary_expr -> Result: vector_selector -> Result: metric_identifier label_matchers { - let name = $1?.val; - let matcher = Matcher::new_eq_metric_matcher(name.clone()); - let matchers = $2?.append(matcher); - Expr::new_vector_selector(Some(name), matchers) + Expr::new_vector_selector(Some($1?.val), $2?) } | metric_identifier { - let name = $1?.val; - let matcher = Matcher::new_eq_metric_matcher(name.clone()); - let matchers = Matchers::empty().append(matcher); - Expr::new_vector_selector(Some(name), matchers) + Expr::new_vector_selector(Some($1?.val), Matchers::empty()) + } + | label_matchers + { + Expr::new_vector_selector(None, $1?) } - | label_matchers { Expr::new_vector_selector(None, $1?) } ; label_matchers -> Result: From 405ef3ab01e0ed17cac87f7411374f8fd1b1ad6f Mon Sep 17 00:00:00 2001 From: yuanbohan Date: Sat, 8 Jul 2023 00:26:51 +0800 Subject: [PATCH 3/5] doc: update prometheus compatible version --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1dba4f4..994859d 100644 --- a/README.md +++ b/README.md @@ -38,9 +38,8 @@ AST: VectorSelector(VectorSelector { name: Some("http_requests_total"), matchers ## PromQL compliance -This crate declares compatible with [prometheus 0372e25][prom-0372e25], which is -prometheus release 2.40 at Nov 29, 2022. Any revision on PromQL after this -commit is not guaranteed. +This crate declares compatible with [prometheus v2.45.0][prom-v2.45.0], which is +released at 2023-06-23. Any revision on PromQL after this commit is not guaranteed. ## Community Extensions @@ -74,5 +73,5 @@ Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be licensed as above, without any additional terms or conditions. -[prom-0372e25]: https://github.com/prometheus/prometheus/tree/0372e259baf014bbade3134fd79bcdfd8cbdef2c +[prom-v2.45.0]: https://github.com/prometheus/prometheus/tree/v2.45.0 [querying-prometheus]: https://prometheus.io/docs/prometheus/latest/querying/basics/ From f8e5430977d90cac8db1670d7502ad5d69fcc54a Mon Sep 17 00:00:00 2001 From: yuanbohan Date: Mon, 10 Jul 2023 10:28:48 +0800 Subject: [PATCH 4/5] misc: use &str instead of String to make code cleaner --- src/label/matcher.rs | 226 +++++++++++++++---------------------------- src/parser/parse.rs | 198 ++++++++----------------------------- 2 files changed, 120 insertions(+), 304 deletions(-) diff --git a/src/label/matcher.rs b/src/label/matcher.rs index d90f85e..5f56762 100644 --- a/src/label/matcher.rs +++ b/src/label/matcher.rs @@ -15,7 +15,6 @@ use std::collections::HashSet; use std::hash::{Hash, Hasher}; -use crate::label::METRIC_NAME; use crate::parser::token::{TokenId, T_EQL, T_EQL_REGEX, T_NEQ, T_NEQ_REGEX}; use regex::Regex; @@ -61,16 +60,11 @@ pub struct Matcher { } impl Matcher { - pub fn new(op: MatchOp, name: String, value: String) -> Self { - Self { op, name, value } - } - - /// build a matcher instance with default metric name and Equal operation - pub fn new_eq_metric_matcher(value: String) -> Self { + pub fn new(op: MatchOp, name: &str, value: &str) -> Self { Self { - op: MatchOp::Equal, - name: METRIC_NAME.into(), - value, + op, + name: name.into(), + value: value.into(), } } @@ -85,19 +79,21 @@ impl Matcher { } pub fn new_matcher(id: TokenId, name: String, value: String) -> Result { - match id { - T_EQL => Ok(Matcher::new(MatchOp::Equal, name, value)), - T_NEQ => Ok(Matcher::new(MatchOp::NotEqual, name, value)), + let op = match id { + T_EQL => Ok(MatchOp::Equal), + T_NEQ => Ok(MatchOp::NotEqual), T_EQL_REGEX => { let re = Regex::new(&value).map_err(|_| format!("illegal regex for {}", &value))?; - Ok(Matcher::new(MatchOp::Re(re), name, value)) + Ok(MatchOp::Re(re)) } T_NEQ_REGEX => { let re = Regex::new(&value).map_err(|_| format!("illegal regex for {}", &value))?; - Ok(Matcher::new(MatchOp::NotRe(re), name, value)) + Ok(MatchOp::NotRe(re)) } _ => Err(format!("invalid match op {id}")), - } + }; + + op.map(|op| Matcher { op, name, value }) } } @@ -221,68 +217,56 @@ mod tests { #[test] fn test_matcher_hash() { assert_eq!( - hash(Matcher::new(MatchOp::Equal, "name".into(), "value".into())), - hash(Matcher::new(MatchOp::Equal, "name".into(), "value".into())), + hash(Matcher::new(MatchOp::Equal, "name", "value")), + hash(Matcher::new(MatchOp::Equal, "name", "value")), ); assert_eq!( - hash(Matcher::new( - MatchOp::NotEqual, - "name".into(), - "value".into() - )), - hash(Matcher::new( - MatchOp::NotEqual, - "name".into(), - "value".into() - )), + hash(Matcher::new(MatchOp::NotEqual, "name", "value")), + hash(Matcher::new(MatchOp::NotEqual, "name", "value")), ); assert_eq!( hash(Matcher::new( MatchOp::Re(Regex::new("\\s+").unwrap()), - "name".into(), - "\\s+".into() + "name", + "\\s+" )), hash(Matcher::new( MatchOp::Re(Regex::new("\\s+").unwrap()), - "name".into(), - "\\s+".into() + "name", + "\\s+" )), ); assert_eq!( hash(Matcher::new( MatchOp::NotRe(Regex::new("\\s+").unwrap()), - "name".into(), - "\\s+".into() + "name", + "\\s+" )), hash(Matcher::new( MatchOp::NotRe(Regex::new("\\s+").unwrap()), - "name".into(), - "\\s+".into() + "name", + "\\s+" )), ); assert_ne!( - hash(Matcher::new(MatchOp::Equal, "name".into(), "value".into())), - hash(Matcher::new( - MatchOp::NotEqual, - "name".into(), - "value".into() - )), + hash(Matcher::new(MatchOp::Equal, "name", "value")), + hash(Matcher::new(MatchOp::NotEqual, "name", "value")), ); assert_ne!( hash(Matcher::new( MatchOp::Re(Regex::new("\\s+").unwrap()), - "name".into(), - "\\s+".into() + "name", + "\\s+" )), hash(Matcher::new( MatchOp::NotRe(Regex::new("\\s+").unwrap()), - "name".into(), - "\\s+".into() + "name", + "\\s+" )), ); } @@ -290,12 +274,12 @@ mod tests { #[test] fn test_matcher_eq_ne() { let op = MatchOp::Equal; - let matcher = Matcher::new(op, "name".into(), "up".into()); + let matcher = Matcher::new(op, "name", "up"); assert!(matcher.is_match("up")); assert!(!matcher.is_match("down")); let op = MatchOp::NotEqual; - let matcher = Matcher::new(op, "name".into(), "up".into()); + let matcher = Matcher::new(op, "name", "up"); assert!(matcher.is_match("foo")); assert!(matcher.is_match("bar")); assert!(!matcher.is_match("up")); @@ -303,10 +287,10 @@ mod tests { #[test] fn test_matcher_re() { - let value = "api/v1/.*".to_string(); + let value = "api/v1/.*"; let re = Regex::new(&value).unwrap(); let op = MatchOp::Re(re); - let matcher = Matcher::new(op, "name".into(), value); + let matcher = Matcher::new(op, "name", value); assert!(matcher.is_match("api/v1/query")); assert!(matcher.is_match("api/v1/range_query")); assert!(!matcher.is_match("api/v2")); @@ -315,112 +299,72 @@ mod tests { #[test] fn test_eq_matcher_equality() { assert_eq!( - Matcher::new(MatchOp::Equal, String::from("code"), String::from("200")), - Matcher::new(MatchOp::Equal, String::from("code"), String::from("200")) + Matcher::new(MatchOp::Equal, "code", "200"), + Matcher::new(MatchOp::Equal, "code", "200") ); assert_ne!( - Matcher::new(MatchOp::Equal, String::from("code"), String::from("200")), - Matcher::new(MatchOp::Equal, String::from("code"), String::from("201")) + Matcher::new(MatchOp::Equal, "code", "200"), + Matcher::new(MatchOp::Equal, "code", "201") ); assert_ne!( - Matcher::new(MatchOp::Equal, String::from("code"), String::from("200")), - Matcher::new(MatchOp::NotEqual, String::from("code"), String::from("200")) + Matcher::new(MatchOp::Equal, "code", "200"), + Matcher::new(MatchOp::NotEqual, "code", "200") ); } #[test] fn test_ne_matcher_equality() { assert_eq!( - Matcher::new(MatchOp::NotEqual, String::from("code"), String::from("200")), - Matcher::new(MatchOp::NotEqual, String::from("code"), String::from("200")) + Matcher::new(MatchOp::NotEqual, "code", "200"), + Matcher::new(MatchOp::NotEqual, "code", "200") ); assert_ne!( - Matcher::new(MatchOp::NotEqual, String::from("code"), String::from("200")), - Matcher::new(MatchOp::NotEqual, String::from("code"), String::from("201")) + Matcher::new(MatchOp::NotEqual, "code", "200"), + Matcher::new(MatchOp::NotEqual, "code", "201") ); assert_ne!( - Matcher::new(MatchOp::NotEqual, String::from("code"), String::from("200")), - Matcher::new(MatchOp::Equal, String::from("code"), String::from("200")) + Matcher::new(MatchOp::NotEqual, "code", "200"), + Matcher::new(MatchOp::Equal, "code", "200") ); } #[test] fn test_re_matcher_equality() { assert_eq!( - Matcher::new( - MatchOp::Re(Regex::new("2??").unwrap()), - String::from("code"), - String::from("2??"), - ), - Matcher::new( - MatchOp::Re(Regex::new("2??").unwrap()), - String::from("code"), - String::from("2??"), - ) + Matcher::new(MatchOp::Re(Regex::new("2??").unwrap()), "code", "2??",), + Matcher::new(MatchOp::Re(Regex::new("2??").unwrap()), "code", "2??",) ); assert_ne!( - Matcher::new( - MatchOp::Re(Regex::new("2??").unwrap()), - String::from("code"), - String::from("2??"), - ), - Matcher::new( - MatchOp::Re(Regex::new("2??").unwrap()), - String::from("code"), - String::from("2*?"), - ) + Matcher::new(MatchOp::Re(Regex::new("2??").unwrap()), "code", "2??",), + Matcher::new(MatchOp::Re(Regex::new("2??").unwrap()), "code", "2*?",) ); assert_ne!( - Matcher::new( - MatchOp::Re(Regex::new("2??").unwrap()), - String::from("code"), - String::from("2??"), - ), - Matcher::new(MatchOp::Equal, String::from("code"), String::from("2??")) + Matcher::new(MatchOp::Re(Regex::new("2??").unwrap()), "code", "2??",), + Matcher::new(MatchOp::Equal, "code", "2??") ); } #[test] fn test_not_re_matcher_equality() { assert_eq!( - Matcher::new( - MatchOp::NotRe(Regex::new("2??").unwrap()), - String::from("code"), - String::from("2??"), - ), - Matcher::new( - MatchOp::NotRe(Regex::new("2??").unwrap()), - String::from("code"), - String::from("2??"), - ) + Matcher::new(MatchOp::NotRe(Regex::new("2??").unwrap()), "code", "2??",), + Matcher::new(MatchOp::NotRe(Regex::new("2??").unwrap()), "code", "2??",) ); assert_ne!( - Matcher::new( - MatchOp::NotRe(Regex::new("2??").unwrap()), - String::from("code"), - String::from("2??"), - ), - Matcher::new( - MatchOp::NotRe(Regex::new("2?*").unwrap()), - String::from("code"), - String::from("2*?"), - ) + Matcher::new(MatchOp::NotRe(Regex::new("2??").unwrap()), "code", "2??",), + Matcher::new(MatchOp::NotRe(Regex::new("2?*").unwrap()), "code", "2*?",) ); assert_ne!( - Matcher::new( - MatchOp::NotRe(Regex::new("2??").unwrap()), - String::from("code"), - String::from("2??"), - ), - Matcher::new(MatchOp::Equal, String::from("code"), String::from("2??")) + Matcher::new(MatchOp::NotRe(Regex::new("2??").unwrap()), "code", "2??",), + Matcher::new(MatchOp::Equal, "code", "2??") ); } @@ -428,62 +372,50 @@ mod tests { fn test_matchers_equality() { assert_eq!( Matchers::empty() - .append(Matcher::new(MatchOp::Equal, "name1".into(), "val1".into())) - .append(Matcher::new(MatchOp::Equal, "name1".into(), "val1".into())) - .append(Matcher::new(MatchOp::Equal, "name2".into(), "val2".into())), + .append(Matcher::new(MatchOp::Equal, "name1", "val1")) + .append(Matcher::new(MatchOp::Equal, "name1", "val1")) + .append(Matcher::new(MatchOp::Equal, "name2", "val2")), Matchers::empty() - .append(Matcher::new(MatchOp::Equal, "name1".into(), "val1".into())) - .append(Matcher::new(MatchOp::Equal, "name2".into(), "val2".into())) + .append(Matcher::new(MatchOp::Equal, "name1", "val1")) + .append(Matcher::new(MatchOp::Equal, "name2", "val2")) ); assert_ne!( - Matchers::empty().append(Matcher::new(MatchOp::Equal, "name1".into(), "val1".into())), - Matchers::empty().append(Matcher::new(MatchOp::Equal, "name2".into(), "val2".into())) + Matchers::empty().append(Matcher::new(MatchOp::Equal, "name1", "val1")), + Matchers::empty().append(Matcher::new(MatchOp::Equal, "name2", "val2")) ); assert_ne!( - Matchers::empty().append(Matcher::new(MatchOp::Equal, "name1".into(), "val1".into())), - Matchers::empty().append(Matcher::new( - MatchOp::NotEqual, - "name1".into(), - "val1".into() - )) + Matchers::empty().append(Matcher::new(MatchOp::Equal, "name1", "val1")), + Matchers::empty().append(Matcher::new(MatchOp::NotEqual, "name1", "val1")) ); assert_eq!( Matchers::empty() - .append(Matcher::new(MatchOp::Equal, "name1".into(), "val1".into())) - .append(Matcher::new( - MatchOp::NotEqual, - "name2".into(), - "val2".into() - )) + .append(Matcher::new(MatchOp::Equal, "name1", "val1")) + .append(Matcher::new(MatchOp::NotEqual, "name2", "val2")) .append(Matcher::new( MatchOp::Re(Regex::new("\\d+").unwrap()), - "name2".into(), - "\\d+".into() + "name2", + "\\d+" )) .append(Matcher::new( MatchOp::NotRe(Regex::new("\\d+").unwrap()), - "name2".into(), - "\\d+".into() + "name2", + "\\d+" )), Matchers::empty() - .append(Matcher::new(MatchOp::Equal, "name1".into(), "val1".into())) - .append(Matcher::new( - MatchOp::NotEqual, - "name2".into(), - "val2".into() - )) + .append(Matcher::new(MatchOp::Equal, "name1", "val1")) + .append(Matcher::new(MatchOp::NotEqual, "name2", "val2")) .append(Matcher::new( MatchOp::Re(Regex::new("\\d+").unwrap()), - "name2".into(), - "\\d+".into() + "name2", + "\\d+" )) .append(Matcher::new( MatchOp::NotRe(Regex::new("\\d+").unwrap()), - "name2".into(), - "\\d+".into() + "name2", + "\\d+" )) ); } diff --git a/src/parser/parse.rs b/src/parser/parse.rs index 8f9edb5..b2ad088 100644 --- a/src/parser/parse.rs +++ b/src/parser/parse.rs @@ -647,11 +647,7 @@ mod tests { r#"method_code:http_errors:rate5m{code="500"} / ignoring(code) method:http_requests:rate5m"#, { let name = String::from("method_code:http_errors:rate5m"); - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("code"), - String::from("500"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "code", "500")); let lhs = Expr::new_vector_selector(Some(name), matchers).unwrap(); Expr::new_binary_expr( lhs, @@ -876,33 +872,21 @@ mod tests { Expr::from(VectorSelector::from("foo")).at_expr(At::try_from(-33f64).unwrap()), ), (r#"foo:bar{a="bc"}"#, { - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("a"), - String::from("bc"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "a", "bc")); Expr::new_vector_selector(Some(String::from("foo:bar")), matchers) }), (r#"foo{NaN='bc'}"#, { - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("NaN"), - String::from("bc"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "NaN", "bc")); Expr::new_vector_selector(Some(String::from("foo")), matchers) }), (r#"foo{bar='}'}"#, { - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("bar"), - String::from("}"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "}")); Expr::new_vector_selector(Some(String::from("foo")), matchers) }), (r#"foo{a="b", foo!="bar", test=~"test", bar!~"baz"}"#, { let matchers = Matchers::new(HashSet::from([ - Matcher::new(MatchOp::Equal, String::from("a"), String::from("b")), - Matcher::new(MatchOp::NotEqual, String::from("foo"), String::from("bar")), + Matcher::new(MatchOp::Equal, "a", "b"), + Matcher::new(MatchOp::NotEqual, "foo", "bar"), Matcher::new_matcher( token::T_EQL_REGEX, String::from("test"), @@ -921,8 +905,8 @@ mod tests { (r#"foo{a="b", foo!="bar", test=~"test", bar!~"baz",}"#, { let name = String::from("foo"); let matchers = Matchers::new(HashSet::from([ - Matcher::new(MatchOp::Equal, String::from("a"), String::from("b")), - Matcher::new(MatchOp::NotEqual, String::from("foo"), String::from("bar")), + Matcher::new(MatchOp::Equal, "a", "b"), + Matcher::new(MatchOp::NotEqual, "foo", "bar"), Matcher::new_matcher( token::T_EQL_REGEX, String::from("test"), @@ -941,8 +925,8 @@ mod tests { // the following multiple __name__ matcher test cases are not from prometheus (r#"{__name__="foo",__name__="bar"}"#, { let matchers = Matchers::new(HashSet::from([ - Matcher::new_eq_metric_matcher(String::from("foo")), - Matcher::new_eq_metric_matcher(String::from("bar")), + Matcher::new(MatchOp::Equal, METRIC_NAME, "foo"), + Matcher::new(MatchOp::Equal, METRIC_NAME, "bar"), ])); Expr::new_vector_selector(None, matchers) }), @@ -1105,11 +1089,7 @@ mod tests { (r#"test{a="b"}[5y] OFFSET 3d"#, { Expr::new_vector_selector( Some(String::from("test")), - Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("a"), - String::from("b"), - )), + Matchers::one(Matcher::new(MatchOp::Equal, "a", "b")), ) .and_then(|ex| Expr::new_matrix_selector(ex, duration::YEAR_DURATION * 5)) .and_then(|ex| ex.offset_expr(Offset::Pos(duration::DAY_DURATION * 3))) @@ -1117,11 +1097,7 @@ mod tests { (r#"test{a="b"}[5y] @ 1603774699"#, { Expr::new_vector_selector( Some(String::from("test")), - Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("a"), - String::from("b"), - )), + Matchers::one(Matcher::new(MatchOp::Equal, "a", "b")), ) .and_then(|ex| Expr::new_matrix_selector(ex, duration::YEAR_DURATION * 5)) .and_then(|ex| ex.at_expr(At::try_from(1603774699_f64).unwrap())) @@ -1322,11 +1298,7 @@ mod tests { ), (r#"floor(some_metric{foo!="bar"})"#, { let name = String::from("some_metric"); - let matchers = Matchers::one(Matcher::new( - MatchOp::NotEqual, - String::from("foo"), - String::from("bar"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::NotEqual, "foo", "bar")); let ex = Expr::new_vector_selector(Some(name), matchers).unwrap(); Expr::new_call(get_function("floor").unwrap(), FunctionArgs::new_args(ex)) }), @@ -1353,23 +1325,15 @@ mod tests { // cases from https://prometheus.io/docs/prometheus/latest/querying/functions (r#"absent(nonexistent{job="myjob"})"#, { let name = String::from("nonexistent"); - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("job"), - String::from("myjob"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "job", "myjob")); let ex = Expr::new_vector_selector(Some(name), matchers).unwrap(); Expr::new_call(get_function("absent").unwrap(), FunctionArgs::new_args(ex)) }), (r#"absent(nonexistent{job="myjob",instance=~".*"})"#, { let name = String::from("nonexistent"); let matchers = Matchers::new(HashSet::from([ - Matcher::new(MatchOp::Equal, String::from("job"), String::from("myjob")), - Matcher::new( - MatchOp::Re(Regex::new(".*").unwrap()), - String::from("instance"), - String::from(".*"), - ), + Matcher::new(MatchOp::Equal, "job", "myjob"), + Matcher::new(MatchOp::Re(Regex::new(".*").unwrap()), "instance", ".*"), ])); Expr::new_vector_selector(Some(name), matchers).and_then(|ex| { Expr::new_call(get_function("absent").unwrap(), FunctionArgs::new_args(ex)) @@ -1377,11 +1341,7 @@ mod tests { }), (r#"absent(sum(nonexistent{job="myjob"}))"#, { let name = String::from("nonexistent"); - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("job"), - String::from("myjob"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "job", "myjob")); Expr::new_vector_selector(Some(name), matchers) .and_then(|ex| { Expr::new_aggregate_expr(token::T_SUM, None, FunctionArgs::new_args(ex)) @@ -1392,11 +1352,7 @@ mod tests { }), (r#"absent_over_time(nonexistent{job="myjob"}[1h])"#, { let name = String::from("nonexistent"); - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("job"), - String::from("myjob"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "job", "myjob")); Expr::new_vector_selector(Some(name), matchers) .and_then(|ex| Expr::new_matrix_selector(ex, duration::HOUR_DURATION)) .and_then(|ex| { @@ -1411,12 +1367,8 @@ mod tests { { let name = String::from("nonexistent"); let matchers = Matchers::new(HashSet::from([ - Matcher::new(MatchOp::Equal, String::from("job"), String::from("myjob")), - Matcher::new( - MatchOp::Re(Regex::new(".*").unwrap()), - String::from("instance"), - String::from(".*"), - ), + Matcher::new(MatchOp::Equal, "job", "myjob"), + Matcher::new(MatchOp::Re(Regex::new(".*").unwrap()), "instance", ".*"), ])); Expr::new_vector_selector(Some(name), matchers) .and_then(|ex| Expr::new_matrix_selector(ex, duration::HOUR_DURATION)) @@ -1430,11 +1382,7 @@ mod tests { ), (r#"delta(cpu_temp_celsius{host="zeus"}[2h])"#, { let name = String::from("cpu_temp_celsius"); - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("host"), - String::from("zeus"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "host", "zeus")); Expr::new_vector_selector(Some(name), matchers) .and_then(|ex| Expr::new_matrix_selector(ex, duration::HOUR_DURATION * 2)) .and_then(|ex| { @@ -1543,11 +1491,7 @@ mod tests { ), (r#"increase(http_requests_total{job="api-server"}[5m])"#, { let name = String::from("http_requests_total"); - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("job"), - String::from("api-server"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "job", "api-server")); Expr::new_vector_selector(Some(name), matchers) .and_then(|ex| Expr::new_matrix_selector(ex, duration::MINUTE_DURATION * 5)) .and_then(|ex| { @@ -1559,11 +1503,7 @@ mod tests { }), (r#"irate(http_requests_total{job="api-server"}[5m])"#, { let name = String::from("http_requests_total"); - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("job"), - String::from("api-server"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "job", "api-server")); Expr::new_vector_selector(Some(name), matchers) .and_then(|ex| Expr::new_matrix_selector(ex, duration::MINUTE_DURATION * 5)) .and_then(|ex| { @@ -1575,14 +1515,10 @@ mod tests { { let name = String::from("up"); let matchers = Matchers::new(HashSet::from([ - Matcher::new(MatchOp::Equal, String::from("src1"), String::from("a")), - Matcher::new(MatchOp::Equal, String::from("src2"), String::from("b")), - Matcher::new(MatchOp::Equal, String::from("src3"), String::from("c")), - Matcher::new( - MatchOp::Equal, - String::from("job"), - String::from("api-server"), - ), + Matcher::new(MatchOp::Equal, "src1", "a"), + Matcher::new(MatchOp::Equal, "src2", "b"), + Matcher::new(MatchOp::Equal, "src3", "c"), + Matcher::new(MatchOp::Equal, "job", "api-server"), ])); Expr::new_vector_selector(Some(name), matchers).and_then(|ex| { Expr::new_call( @@ -1602,12 +1538,8 @@ mod tests { { let name = String::from("up"); let matchers = Matchers::new(HashSet::from([ - Matcher::new(MatchOp::Equal, String::from("service"), String::from("a:c")), - Matcher::new( - MatchOp::Equal, - String::from("job"), - String::from("api-server"), - ), + Matcher::new(MatchOp::Equal, "service", "a:c"), + Matcher::new(MatchOp::Equal, "job", "api-server"), ])); Expr::new_vector_selector(Some(name), matchers).and_then(|ex| { Expr::new_call( @@ -1780,11 +1712,7 @@ mod tests { fn test_subquery() { let cases = vec![ (r#"foo{bar="baz"}[10m:6s]"#, { - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("bar"), - String::from("baz"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "baz")); Expr::new_vector_selector(Some(String::from("foo")), matchers).and_then(|ex| { Expr::new_subquery_expr( ex, @@ -1794,11 +1722,7 @@ mod tests { }) }), (r#"foo{bar="baz"}[10m5s:1h6ms]"#, { - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("bar"), - String::from("baz"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "baz")); Expr::new_vector_selector(Some(String::from("foo")), matchers).and_then(|ex| { Expr::new_subquery_expr( ex, @@ -1812,11 +1736,7 @@ mod tests { Expr::new_subquery_expr(ex, duration::MINUTE_DURATION * 10, None) }), (r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:5s])"#, { - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("bar"), - String::from("baz"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "baz")); Expr::new_vector_selector(Some(String::from("foo")), matchers) .and_then(|ex| Expr::new_matrix_selector(ex, Duration::from_secs(2))) .and_then(|ex| { @@ -1837,11 +1757,7 @@ mod tests { }) }), (r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s]"#, { - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("bar"), - String::from("baz"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "baz")); Expr::new_vector_selector(Some(String::from("foo")), matchers) .and_then(|ex| Expr::new_matrix_selector(ex, Duration::from_secs(2))) .and_then(|ex| { @@ -1865,11 +1781,7 @@ mod tests { ( r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] offset 4m)[4m:3s]"#, { - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("bar"), - String::from("baz"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "baz")); Expr::new_vector_selector(Some(String::from("foo")), matchers) .and_then(|ex| Expr::new_matrix_selector(ex, Duration::from_secs(2))) .and_then(|ex| { @@ -1900,11 +1812,7 @@ mod tests { ( r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] @ 1603775091)[4m:3s]"#, { - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("bar"), - String::from("baz"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "baz")); Expr::new_vector_selector(Some(String::from("foo")), matchers) .and_then(|ex| Expr::new_matrix_selector(ex, Duration::from_secs(2))) .and_then(|ex| { @@ -1935,11 +1843,7 @@ mod tests { ( r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] @ -160377509)[4m:3s]"#, { - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("bar"), - String::from("baz"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "baz")); Expr::new_vector_selector(Some(String::from("foo")), matchers) .and_then(|ex| Expr::new_matrix_selector(ex, Duration::from_secs(2))) .and_then(|ex| { @@ -2050,11 +1954,7 @@ mod tests { .and_then(|ex| ex.offset_expr(Offset::Pos(duration::MINUTE_DURATION))), ), (r#"(foo + bar{nm="val"})[5m:]"#, { - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("nm"), - String::from("val"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "nm", "val")); Expr::new_binary_expr( Expr::from(VectorSelector::from("foo")), token::T_ADD, @@ -2065,11 +1965,7 @@ mod tests { .and_then(|ex| Expr::new_subquery_expr(ex, duration::MINUTE_DURATION * 5, None)) }), (r#"(foo + bar{nm="val"})[5m:] offset 10m"#, { - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("nm"), - String::from("val"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "nm", "val")); Expr::new_binary_expr( Expr::from(VectorSelector::from("foo")), token::T_ADD, @@ -2081,11 +1977,7 @@ mod tests { .and_then(|ex| ex.offset_expr(Offset::Pos(duration::MINUTE_DURATION * 10))) }), (r#"(foo + bar{nm="val"} @ 1234)[5m:] @ 1603775019"#, { - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("nm"), - String::from("val"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "nm", "val")); let rhs = Expr::new_vector_selector(Some(String::from("bar")), matchers) .and_then(|ex| ex.at_expr(At::try_from(1234_f64).unwrap())) .unwrap(); @@ -2165,20 +2057,12 @@ mod tests { ("end", Ok(Expr::from(VectorSelector::from("end")))), (r#"start{end="foo"}"#, { let name = String::from("start"); - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("end"), - String::from("foo"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "end", "foo")); Expr::new_vector_selector(Some(name), matchers) }), (r#"end{start="foo"}"#, { let name = String::from("end"); - let matchers = Matchers::one(Matcher::new( - MatchOp::Equal, - String::from("start"), - String::from("foo"), - )); + let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "start", "foo")); Expr::new_vector_selector(Some(name), matchers) }), ("foo unless on(start) bar", { From 6cd29f7423a9e7d9416074dded6c40024dcec122 Mon Sep 17 00:00:00 2001 From: yuanbohan Date: Mon, 10 Jul 2023 10:38:33 +0800 Subject: [PATCH 5/5] chore: update version to 0.1.3 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index d3047e4..ccb4cf5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "promql-parser" readme = "README.md" description = "Parse PromQL query into AST" repository = "https://github.com/GreptimeTeam/promql-parser" -version = "0.1.2" +version = "0.1.3" edition = "2021" authors = ["The GreptimeDB Project Developers"] keywords = ["prometheus", "promql", "parser"]