Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • SubconsciousCompute/mquery
1 result
Show changes
Commits on Source (2)
//! Aggregate query functions (includes PromQL aggregation operators)
use super::{basic_fn, QryFunc};
use super::{basic_fn, qry_fn, QryFunc};
use crate::{
query::{
ops::{
......@@ -133,7 +133,7 @@ pub fn count_values<'a>(
label: &'_ str,
vec_expr: impl Operable + 'static,
) -> AggrFunc<'a, impl Fn(&mut fmt::Formatter) -> fmt::Result + '_> {
QryFunc::new(move |f| write!(f, r#"count_values("{label}", {vec_expr})"#)).into()
qry_fn!(count_values, r#""{label}", {vec_expr}"#).into()
}
/// The topk aggregate operator/function
......@@ -142,7 +142,7 @@ pub fn topk<'a>(
k: usize,
vec_expr: impl Operable + 'static,
) -> AggrFunc<'a, impl Fn(&mut fmt::Formatter) -> fmt::Result> {
QryFunc::new(move |f| write!(f, "topk({k}, {vec_expr})")).into()
qry_fn!(topk, "{k}, {vec_expr}").into()
}
/// The bottomk aggregate operator/function
......@@ -151,7 +151,7 @@ pub fn bottomk<'a>(
k: usize,
vec_expr: impl Operable + 'static,
) -> AggrFunc<'a, impl Fn(&mut fmt::Formatter) -> fmt::Result> {
QryFunc::new(move |f| write!(f, "bottomk({k}, {vec_expr})")).into()
qry_fn!(bottomk, "{k}, {vec_expr}").into()
}
/// The bottomk aggregate operator/function (phi value should always be >= 0 and <= 1)
......@@ -160,7 +160,7 @@ pub fn quantile<'a>(
phi: f32,
vec_expr: impl Operable + 'static,
) -> AggrFunc<'a, impl Fn(&mut fmt::Formatter) -> fmt::Result> {
QryFunc::new(move |f| write!(f, "quantile({phi}, {vec_expr})")).into()
qry_fn!(quantile, "{phi}, {vec_expr}").into()
}
#[cfg(test)]
......@@ -171,20 +171,14 @@ mod tests {
#[test]
fn by_mod() {
let agr = AggrFunc {
inner: QryFunc::new(|f| f.write_str("func(x)")),
mod_type: Default::default(),
};
let agr: AggrFunc<_> = qry_fn!(func, "x").into();
let by_str = agr.by(["label", "label2"]).to_string();
assert_eq!(by_str, "func(x) by (label,label2)");
}
#[test]
fn without_mod() {
let agr = AggrFunc {
inner: QryFunc::new(|f| f.write_str("func(x)")),
mod_type: Default::default(),
};
let agr: AggrFunc<_> = qry_fn!(func, "x").into();
let by_str = agr.without(["label", "label2"]).to_string();
assert_eq!(by_str, "func(x) without (label,label2)");
}
......
......@@ -2,9 +2,10 @@
use core::fmt;
use crate::query::ops::Operable;
use super::QryFunc;
use crate::query::{
fns::{qry_fn, QryFunc},
ops::Operable,
};
/// MetricsQL's label_map query function
pub fn mql_label_map<'a>(
......@@ -12,13 +13,11 @@ pub fn mql_label_map<'a>(
label: &'a str,
src_dst_pairs: &'a [&'a str],
) -> QryFunc<impl Fn(&mut fmt::Formatter) -> fmt::Result + 'a> {
QryFunc::new(move |f| {
write!(
f,
"label_map({qry_expr},\"{label}\",\"{pairs}\")",
pairs = src_dst_pairs.join("\",\"")
)
})
qry_fn!(
label_map,
"{qry_expr},\"{label}\",\"{pairs}\"",
pairs = src_dst_pairs.join("\",\"")
)
}
fn basic_label_fn<'a>(
......@@ -26,13 +25,10 @@ fn basic_label_fn<'a>(
qry_expr: impl Operable + 'a,
labels: &'a [&'a str],
) -> QryFunc<impl Fn(&mut fmt::Formatter) -> fmt::Result + 'a> {
QryFunc::new(move |f| {
write!(
f,
"{fn_name}({qry_expr},\"{labels}\")",
labels = labels.join("\",\"")
)
})
qry_fn!(var: fn_name,
"{qry_expr},\"{labels}\"",
labels = labels.join("\",\"")
)
}
/// MetricsQL's sort_by_label query function
......
......@@ -22,23 +22,46 @@ pub mod rollup;
#[cfg(feature = "metricsql")]
pub mod transform;
// This macro takes a name and formatting arguments which are directly passed to the `write` macro
// and constructs a QryFunc type. The name is generally provided directly as tokens (not as a quoted string).
// However, variables can be passed to the name field by specifying `var: var_name`
macro_rules! qry_fn {
(var: $name: ident, { $($func: tt)+ }) => {
QryFunc::new($name, move $($func)+)
};
(var: $name: ident, $($fmt: tt)+) => {
QryFunc::new($name, move |f| write!(f, $($fmt)+))
};
($name: tt, { $($func: tt)+ }) => {
QryFunc::new(stringify!($name), move $($func)+)
};
($name: tt, $($fmt: tt)+) => {
QryFunc::new(stringify!($name), move |f| write!(f, $($fmt)+))
};
}
pub(crate) use qry_fn;
/// Type that represents a query function. Meant to be constructed through the query functions provided in the [`fns`](crate::query::fns) module.
///
/// This internally holds an actual function (closure), that acts as a type that implements the `Display` trait.
#[derive(Debug, Clone)]
pub struct QryFunc<F: Fn(&mut fmt::Formatter) -> fmt::Result> {
inner: F,
name: &'static str,
args: F,
}
impl<F: Fn(&mut fmt::Formatter) -> fmt::Result> QryFunc<F> {
fn new(func: F) -> Self {
Self { inner: func }
fn new(name: &'static str, func: F) -> Self {
Self { name, args: func }
}
}
impl<F: Fn(&mut fmt::Formatter) -> fmt::Result> Display for QryFunc<F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(self.inner)(f)
write!(f, "{name}(", name = self.name)?; // write name and the starting parenthesis
(self.args)(f)?; // write formatted arguments
f.write_str(")") // closing parenthesis
}
}
......@@ -58,5 +81,34 @@ fn basic_fn(
name: &'static str,
expr: impl Operable + 'static,
) -> QryFunc<impl Fn(&mut fmt::Formatter) -> fmt::Result + '_> {
QryFunc::new(move |f| write!(f, "{name}({expr})"))
qry_fn!(var: name, "{expr}")
}
#[cfg(test)]
mod tests {
use super::QryFunc;
#[test]
fn func_format() {
let func = QryFunc::new("function", |f| f.write_str("arg1, arg2")).to_string();
assert_eq!(func, "function(arg1, arg2)")
}
#[test]
fn func_macro() {
// Basic usage
let func = qry_fn!(name, "args").to_string();
assert_eq!(func, "name(args)");
// Custom internal fn
let func = qry_fn!(name, { |f| f.write_str("args") }).to_string();
assert_eq!(func, "name(args)");
// With Variables
let x = "name";
let func = qry_fn!(var: x, "args").to_string();
assert_eq!(func, "name(args)");
// Custom with Variables
let x = "name";
let func = qry_fn!(var: x, { |f| f.write_str("args") }).to_string();
assert_eq!(func, "name(args)");
}
}
......@@ -2,7 +2,7 @@ use core::fmt;
use crate::query::ops::Operable;
use super::{basic_fn, QryFunc};
use super::{basic_fn, qry_fn, QryFunc};
/// The avg_over_time rollup query function
#[inline]
......@@ -50,7 +50,7 @@ pub fn quantile_over_time(
phi: f32,
range_vec: impl Operable + 'static,
) -> QryFunc<impl Fn(&mut fmt::Formatter) -> fmt::Result> {
QryFunc::new(move |f| write!(f, "quantile_over_time({phi},{range_vec})"))
qry_fn!(quantile_over_time, "{phi},{range_vec}")
}
/// The stddev_over_time rollup query function
......
......@@ -2,7 +2,7 @@ use core::fmt;
use crate::query::ops::Operable;
use super::QryFunc;
use super::{qry_fn, QryFunc};
/// MetricsQL `limit_offset` query function
pub fn mql_limit_offset(
......@@ -10,24 +10,22 @@ pub fn mql_limit_offset(
offset: usize,
qry_expr: impl Operable,
) -> QryFunc<impl Fn(&mut fmt::Formatter) -> fmt::Result> {
QryFunc::new(move |f| write!(f, "limit_offset({limit},{offset},{qry_expr})"))
qry_fn!(limit_offset, "{limit},{offset},{qry_expr}")
}
/// MetricsQL `union` query function
pub fn mql_union(
qry_expressions: &[impl Operable],
) -> QryFunc<impl Fn(&mut fmt::Formatter) -> fmt::Result + '_> {
QryFunc::new(|f| {
write!(
f,
"union({queries})",
queries = qry_expressions
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(",")
)
})
qry_fn!(
union,
"{queries}",
queries = qry_expressions
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(",")
)
}
#[cfg(test)]
......