mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-10-28 22:56:19 +00:00
feat: support PromQL function vector (#3036)
* produce vector plan Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * work with OR Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * apply review sugg Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * move common const strings to common_query Signed-off-by: Ruihang Xia <waynestxia@gmail.com> * add comment for GREPTIME_COUNT Signed-off-by: Ruihang Xia <waynestxia@gmail.com> --------- Signed-off-by: Ruihang Xia <waynestxia@gmail.com>
This commit is contained in:
Generated
+1
@@ -6558,6 +6558,7 @@ dependencies = [
|
||||
"common-catalog",
|
||||
"common-error",
|
||||
"common-macro",
|
||||
"common-query",
|
||||
"common-recordbatch",
|
||||
"common-telemetry",
|
||||
"datafusion",
|
||||
|
||||
@@ -18,3 +18,10 @@ pub use crate::columnar_value::ColumnarValue;
|
||||
pub use crate::function::*;
|
||||
pub use crate::logical_plan::{create_udf, AggregateFunction, Expr, ScalarUdf};
|
||||
pub use crate::signature::{Signature, TypeSignature, Volatility};
|
||||
|
||||
/// Default timestamp column name for Prometheus metrics.
|
||||
pub const GREPTIME_TIMESTAMP: &str = "greptime_timestamp";
|
||||
/// Default value column name for Prometheus metrics.
|
||||
pub const GREPTIME_VALUE: &str = "greptime_value";
|
||||
/// Default counter column name for OTLP metrics.
|
||||
pub const GREPTIME_COUNT: &str = "greptime_count";
|
||||
|
||||
@@ -13,6 +13,7 @@ catalog.workspace = true
|
||||
common-catalog.workspace = true
|
||||
common-error.workspace = true
|
||||
common-macro.workspace = true
|
||||
common-query.workspace = true
|
||||
common-recordbatch.workspace = true
|
||||
common-telemetry.workspace = true
|
||||
datafusion.workspace = true
|
||||
|
||||
@@ -104,8 +104,8 @@ impl EmptyMetric {
|
||||
.map(|expr| {
|
||||
physical_planner.create_physical_expr(
|
||||
expr,
|
||||
&self.result_schema,
|
||||
&ArrowSchema::from(self.result_schema.as_ref()),
|
||||
&self.time_index_schema,
|
||||
&ArrowSchema::from(self.time_index_schema.as_ref()),
|
||||
session_state,
|
||||
)
|
||||
})
|
||||
|
||||
+166
-66
@@ -19,6 +19,7 @@ use std::time::UNIX_EPOCH;
|
||||
|
||||
use async_recursion::async_recursion;
|
||||
use catalog::table_source::DfTableSourceProvider;
|
||||
use common_query::prelude::GREPTIME_VALUE;
|
||||
use datafusion::common::{DFSchemaRef, OwnedTableReference, Result as DfResult};
|
||||
use datafusion::datasource::DefaultTableSource;
|
||||
use datafusion::logical_expr::expr::{AggregateFunction, Alias, ScalarFunction, ScalarUDF};
|
||||
@@ -36,8 +37,9 @@ use datatypes::arrow::datatypes::DataType as ArrowDataType;
|
||||
use promql_parser::label::{MatchOp, Matcher, Matchers, METRIC_NAME};
|
||||
use promql_parser::parser::{
|
||||
token, AggregateExpr, BinModifier, BinaryExpr as PromBinaryExpr, Call, EvalStmt,
|
||||
Expr as PromExpr, Function, LabelModifier, MatrixSelector, NumberLiteral, Offset, ParenExpr,
|
||||
StringLiteral, SubqueryExpr, TokenType, UnaryExpr, VectorMatchCardinality, VectorSelector,
|
||||
Expr as PromExpr, Function, FunctionArgs as PromFunctionArgs, LabelModifier, MatrixSelector,
|
||||
NumberLiteral, Offset, ParenExpr, StringLiteral, SubqueryExpr, TokenType, UnaryExpr,
|
||||
VectorMatchCardinality, VectorSelector,
|
||||
};
|
||||
use snafu::{ensure, OptionExt, ResultExt};
|
||||
use table::table::adapter::DfTableProviderAdapter;
|
||||
@@ -63,6 +65,8 @@ use crate::functions::{
|
||||
const SPECIAL_TIME_FUNCTION: &str = "time";
|
||||
/// `histogram_quantile` function in PromQL
|
||||
const SPECIAL_HISTOGRAM_QUANTILE: &str = "histogram_quantile";
|
||||
/// `vector` function in PromQL
|
||||
const SPECIAL_VECTOR_FUNCTION: &str = "vector";
|
||||
/// `le` column for conventional histogram.
|
||||
const LE_COLUMN_NAME: &str = "le";
|
||||
|
||||
@@ -289,13 +293,13 @@ impl PromPlanner {
|
||||
let left_field_columns = self.ctx.field_columns.clone();
|
||||
let left_table_ref: OwnedTableReference =
|
||||
self.ctx.table_name.clone().unwrap_or_default().into();
|
||||
let left_tag_cols = self.ctx.tag_columns.clone();
|
||||
let left_context = self.ctx.clone();
|
||||
|
||||
let right_input = self.prom_expr_to_plan(*rhs.clone()).await?;
|
||||
let right_field_columns = self.ctx.field_columns.clone();
|
||||
let right_table_ref: OwnedTableReference =
|
||||
self.ctx.table_name.clone().unwrap_or_default().into();
|
||||
let right_tag_cols = self.ctx.tag_columns.clone();
|
||||
let right_context = self.ctx.clone();
|
||||
|
||||
// TODO(ruihang): avoid join if left and right are the same table
|
||||
|
||||
@@ -304,8 +308,8 @@ impl PromPlanner {
|
||||
return self.set_op_on_non_field_columns(
|
||||
left_input,
|
||||
right_input,
|
||||
left_tag_cols,
|
||||
right_tag_cols,
|
||||
left_context,
|
||||
right_context,
|
||||
*op,
|
||||
modifier,
|
||||
);
|
||||
@@ -463,57 +467,14 @@ impl PromPlanner {
|
||||
})
|
||||
}
|
||||
PromExpr::Call(Call { func, args }) => {
|
||||
if func.name == SPECIAL_HISTOGRAM_QUANTILE {
|
||||
if args.args.len() != 2 {
|
||||
return FunctionInvalidArgumentSnafu {
|
||||
fn_name: SPECIAL_HISTOGRAM_QUANTILE.to_string(),
|
||||
}
|
||||
.fail();
|
||||
}
|
||||
let phi = Self::try_build_float_literal(&args.args[0]).with_context(|| {
|
||||
FunctionInvalidArgumentSnafu {
|
||||
fn_name: SPECIAL_HISTOGRAM_QUANTILE.to_string(),
|
||||
}
|
||||
})?;
|
||||
let input = args.args[1].as_ref().clone();
|
||||
let input_plan = self.prom_expr_to_plan(input).await?;
|
||||
|
||||
if !self.ctx.has_le_tag() {
|
||||
return ColumnNotFoundSnafu {
|
||||
col: LE_COLUMN_NAME.to_string(),
|
||||
}
|
||||
.fail();
|
||||
}
|
||||
let time_index_column =
|
||||
self.ctx.time_index_column.clone().with_context(|| {
|
||||
TimeIndexNotFoundSnafu {
|
||||
table: self.ctx.table_name.clone().unwrap_or_default(),
|
||||
}
|
||||
})?;
|
||||
// FIXME(ruihang): support multi fields
|
||||
let field_column = self
|
||||
.ctx
|
||||
.field_columns
|
||||
.first()
|
||||
.with_context(|| FunctionInvalidArgumentSnafu {
|
||||
fn_name: SPECIAL_HISTOGRAM_QUANTILE.to_string(),
|
||||
})?
|
||||
.clone();
|
||||
|
||||
return Ok(LogicalPlan::Extension(Extension {
|
||||
node: Arc::new(
|
||||
HistogramFold::new(
|
||||
LE_COLUMN_NAME.to_string(),
|
||||
field_column,
|
||||
time_index_column,
|
||||
phi,
|
||||
input_plan,
|
||||
)
|
||||
.context(DataFusionPlanningSnafu)?,
|
||||
),
|
||||
}));
|
||||
// some special functions that are not expression but a plan
|
||||
match func.name {
|
||||
SPECIAL_HISTOGRAM_QUANTILE => return self.create_histogram_plan(args).await,
|
||||
SPECIAL_VECTOR_FUNCTION => return self.create_vector_plan(args).await,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// transform function arguments
|
||||
let args = self.create_function_args(&args.args)?;
|
||||
let input = if let Some(prom_expr) = args.input {
|
||||
self.prom_expr_to_plan(prom_expr).await?
|
||||
@@ -1303,6 +1264,93 @@ impl PromPlanner {
|
||||
Ok(exprs)
|
||||
}
|
||||
|
||||
/// Create a [SPECIAL_HISTOGRAM_QUANTILE] plan.
|
||||
async fn create_histogram_plan(&mut self, args: &PromFunctionArgs) -> Result<LogicalPlan> {
|
||||
if args.args.len() != 2 {
|
||||
return FunctionInvalidArgumentSnafu {
|
||||
fn_name: SPECIAL_HISTOGRAM_QUANTILE.to_string(),
|
||||
}
|
||||
.fail();
|
||||
}
|
||||
let phi = Self::try_build_float_literal(&args.args[0]).with_context(|| {
|
||||
FunctionInvalidArgumentSnafu {
|
||||
fn_name: SPECIAL_HISTOGRAM_QUANTILE.to_string(),
|
||||
}
|
||||
})?;
|
||||
let input = args.args[1].as_ref().clone();
|
||||
let input_plan = self.prom_expr_to_plan(input).await?;
|
||||
|
||||
if !self.ctx.has_le_tag() {
|
||||
return ColumnNotFoundSnafu {
|
||||
col: LE_COLUMN_NAME.to_string(),
|
||||
}
|
||||
.fail();
|
||||
}
|
||||
let time_index_column =
|
||||
self.ctx
|
||||
.time_index_column
|
||||
.clone()
|
||||
.with_context(|| TimeIndexNotFoundSnafu {
|
||||
table: self.ctx.table_name.clone().unwrap_or_default(),
|
||||
})?;
|
||||
// FIXME(ruihang): support multi fields
|
||||
let field_column = self
|
||||
.ctx
|
||||
.field_columns
|
||||
.first()
|
||||
.with_context(|| FunctionInvalidArgumentSnafu {
|
||||
fn_name: SPECIAL_HISTOGRAM_QUANTILE.to_string(),
|
||||
})?
|
||||
.clone();
|
||||
|
||||
Ok(LogicalPlan::Extension(Extension {
|
||||
node: Arc::new(
|
||||
HistogramFold::new(
|
||||
LE_COLUMN_NAME.to_string(),
|
||||
field_column,
|
||||
time_index_column,
|
||||
phi,
|
||||
input_plan,
|
||||
)
|
||||
.context(DataFusionPlanningSnafu)?,
|
||||
),
|
||||
}))
|
||||
}
|
||||
|
||||
/// Create a [SPECIAL_VECTOR_FUNCTION] plan
|
||||
async fn create_vector_plan(&mut self, args: &PromFunctionArgs) -> Result<LogicalPlan> {
|
||||
if args.args.len() != 1 {
|
||||
return FunctionInvalidArgumentSnafu {
|
||||
fn_name: SPECIAL_VECTOR_FUNCTION.to_string(),
|
||||
}
|
||||
.fail();
|
||||
}
|
||||
let lit = Self::try_build_float_literal(&args.args[0]).with_context(|| {
|
||||
FunctionInvalidArgumentSnafu {
|
||||
fn_name: SPECIAL_VECTOR_FUNCTION.to_string(),
|
||||
}
|
||||
})?;
|
||||
|
||||
// reuse `SPECIAL_TIME_FUNCTION` as name of time index column
|
||||
self.ctx.time_index_column = Some(SPECIAL_TIME_FUNCTION.to_string());
|
||||
self.ctx.table_name = Some(String::new());
|
||||
self.ctx.tag_columns = vec![];
|
||||
self.ctx.field_columns = vec![GREPTIME_VALUE.to_string()];
|
||||
Ok(LogicalPlan::Extension(Extension {
|
||||
node: Arc::new(
|
||||
EmptyMetric::new(
|
||||
self.ctx.start,
|
||||
self.ctx.end,
|
||||
self.ctx.interval,
|
||||
SPECIAL_TIME_FUNCTION.to_string(),
|
||||
GREPTIME_VALUE.to_string(),
|
||||
Some(DfExpr::Literal(ScalarValue::Float64(Some(lit)))),
|
||||
)
|
||||
.context(DataFusionPlanningSnafu)?,
|
||||
),
|
||||
}))
|
||||
}
|
||||
|
||||
/// Try to build a DataFusion Literal Expression from PromQL Expr, return
|
||||
/// `None` if the input is not a literal expression.
|
||||
fn try_build_literal_expr(expr: &PromExpr) -> Option<DfExpr> {
|
||||
@@ -1491,19 +1539,35 @@ impl PromPlanner {
|
||||
|
||||
/// Build a set operator (AND/OR/UNLESS)
|
||||
fn set_op_on_non_field_columns(
|
||||
&self,
|
||||
&mut self,
|
||||
left: LogicalPlan,
|
||||
right: LogicalPlan,
|
||||
left_tag_cols: Vec<String>,
|
||||
right_tag_cols: Vec<String>,
|
||||
left_context: PromPlannerContext,
|
||||
right_context: PromPlannerContext,
|
||||
op: TokenType,
|
||||
modifier: &Option<BinModifier>,
|
||||
) -> Result<LogicalPlan> {
|
||||
let mut left_tag_col_set = left_tag_cols.into_iter().collect::<HashSet<_>>();
|
||||
let mut right_tag_col_set = right_tag_cols.into_iter().collect::<HashSet<_>>();
|
||||
let mut left_tag_col_set = left_context
|
||||
.tag_columns
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<HashSet<_>>();
|
||||
let mut right_tag_col_set = right_context
|
||||
.tag_columns
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<HashSet<_>>();
|
||||
|
||||
if matches!(op.id(), token::T_LOR) {
|
||||
return self.or_operator(left, right, left_tag_col_set, right_tag_col_set, modifier);
|
||||
return self.or_operator(
|
||||
left,
|
||||
right,
|
||||
left_tag_col_set,
|
||||
right_tag_col_set,
|
||||
left_context,
|
||||
right_context,
|
||||
modifier,
|
||||
);
|
||||
}
|
||||
|
||||
// apply modifier
|
||||
@@ -1585,19 +1649,24 @@ impl PromPlanner {
|
||||
.build()
|
||||
.context(DataFusionPlanningSnafu),
|
||||
token::T_LOR => {
|
||||
self.or_operator(left, right, left_tag_col_set, right_tag_col_set, modifier)
|
||||
// OR is handled at the beginning of this function, as it cannot
|
||||
// be expressed using JOIN like AND and UNLESS.
|
||||
unreachable!()
|
||||
}
|
||||
_ => UnexpectedTokenSnafu { token: op }.fail(),
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(ruihang): change function name
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn or_operator(
|
||||
&self,
|
||||
&mut self,
|
||||
left: LogicalPlan,
|
||||
right: LogicalPlan,
|
||||
left_tag_cols_set: HashSet<String>,
|
||||
right_tag_cols_set: HashSet<String>,
|
||||
left_context: PromPlannerContext,
|
||||
right_context: PromPlannerContext,
|
||||
modifier: &Option<BinModifier>,
|
||||
) -> Result<LogicalPlan> {
|
||||
// prepare hash sets
|
||||
@@ -1623,18 +1692,37 @@ impl PromPlanner {
|
||||
.as_ref()
|
||||
.map(|r| r.to_string())
|
||||
.unwrap_or_default();
|
||||
let left_time_index_column =
|
||||
left_context
|
||||
.time_index_column
|
||||
.clone()
|
||||
.with_context(|| TimeIndexNotFoundSnafu {
|
||||
table: left_qualifier_string.clone(),
|
||||
})?;
|
||||
let right_time_index_column =
|
||||
right_context
|
||||
.time_index_column
|
||||
.clone()
|
||||
.with_context(|| TimeIndexNotFoundSnafu {
|
||||
table: right_qualifier_string.clone(),
|
||||
})?;
|
||||
|
||||
// step 0: fill all columns in output schema
|
||||
let all_columns_set = left
|
||||
let mut all_columns_set = left
|
||||
.schema()
|
||||
.fields()
|
||||
.iter()
|
||||
.chain(right.schema().fields().iter())
|
||||
.map(|field| field.name().clone())
|
||||
.collect::<HashSet<_>>();
|
||||
// remove time index column
|
||||
all_columns_set.remove(&left_time_index_column);
|
||||
all_columns_set.remove(&right_time_index_column);
|
||||
let mut all_columns = all_columns_set.into_iter().collect::<Vec<_>>();
|
||||
// sort to ensure the generated schema is not volatile
|
||||
all_columns.sort_unstable();
|
||||
// use left time index column name as the result time index column name
|
||||
all_columns.insert(0, left_time_index_column.clone());
|
||||
|
||||
// step 1: align schema using project, fill non-exist columns with null
|
||||
let left_proj_exprs = all_columns.iter().map(|col| {
|
||||
@@ -1644,13 +1732,21 @@ impl PromPlanner {
|
||||
DfExpr::Column(Column::new(left_qualifier.clone(), col))
|
||||
}
|
||||
});
|
||||
let right_proj_exprs = all_columns.iter().map(|col| {
|
||||
let right_time_index_expr = DfExpr::Column(Column::new(
|
||||
right_qualifier.clone(),
|
||||
right_time_index_column,
|
||||
))
|
||||
.alias(left_time_index_column.clone());
|
||||
let right_proj_exprs_without_time_index = all_columns.iter().skip(1).map(|col| {
|
||||
if tags_not_in_right.contains(col) {
|
||||
DfExpr::Literal(ScalarValue::Utf8(None)).alias(col.to_string())
|
||||
} else {
|
||||
DfExpr::Column(Column::new(right_qualifier.clone(), col))
|
||||
}
|
||||
});
|
||||
let right_proj_exprs = [right_time_index_expr]
|
||||
.into_iter()
|
||||
.chain(right_proj_exprs_without_time_index);
|
||||
|
||||
let left_projected = LogicalPlanBuilder::from(left)
|
||||
.project(left_proj_exprs)
|
||||
@@ -1691,13 +1787,17 @@ impl PromPlanner {
|
||||
left_projected,
|
||||
right_projected,
|
||||
match_columns,
|
||||
self.ctx.time_index_column.clone().unwrap(),
|
||||
left_time_index_column.clone(),
|
||||
schema,
|
||||
);
|
||||
let result = LogicalPlan::Extension(Extension {
|
||||
node: Arc::new(union_distinct_on),
|
||||
});
|
||||
|
||||
// step 4: update context
|
||||
self.ctx.time_index_column = Some(left_time_index_column);
|
||||
self.ctx.tag_columns = all_tags.into_iter().collect();
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ use common_datasource::file_format::{infer_schemas, FileFormat, Format};
|
||||
use common_datasource::lister::{Lister, Source};
|
||||
use common_datasource::object_store::build_backend;
|
||||
use common_datasource::util::find_dir_and_filename;
|
||||
use common_query::prelude::GREPTIME_TIMESTAMP;
|
||||
use common_query::Output;
|
||||
use common_recordbatch::{RecordBatch, RecordBatches};
|
||||
use common_time::Timestamp;
|
||||
@@ -57,8 +58,6 @@ const NULLABLE_YES: &str = "YES";
|
||||
const NULLABLE_NO: &str = "NO";
|
||||
const PRI_KEY: &str = "PRI";
|
||||
|
||||
const GREPTIME_TIMESTAMP: &str = "greptime_timestamp";
|
||||
|
||||
static DESCRIBE_TABLE_OUTPUT_SCHEMA: Lazy<Arc<Schema>> = Lazy::new(|| {
|
||||
Arc::new(Schema::new(vec![
|
||||
ColumnSchema::new(
|
||||
|
||||
@@ -22,6 +22,7 @@ use common_catalog::consts::DEFAULT_SCHEMA_NAME;
|
||||
use common_catalog::parse_catalog_and_schema_from_db_string;
|
||||
use common_error::ext::ErrorExt;
|
||||
use common_error::status_code::StatusCode;
|
||||
use common_query::prelude::{GREPTIME_TIMESTAMP, GREPTIME_VALUE};
|
||||
use common_query::Output;
|
||||
use common_recordbatch::RecordBatches;
|
||||
use common_time::util::{current_time_rfc3339, yesterday_rfc3339};
|
||||
@@ -43,7 +44,7 @@ use snafu::{Location, OptionExt, ResultExt};
|
||||
use crate::error::{
|
||||
CollectRecordbatchSnafu, Error, InternalSnafu, InvalidQuerySnafu, Result, UnexpectedResultSnafu,
|
||||
};
|
||||
use crate::prom_store::{FIELD_COLUMN_NAME, METRIC_NAME_LABEL, TIMESTAMP_COLUMN_NAME};
|
||||
use crate::prom_store::METRIC_NAME_LABEL;
|
||||
use crate::prometheus_handler::PrometheusHandlerRef;
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq)]
|
||||
@@ -499,8 +500,8 @@ pub async fn labels_query(
|
||||
}
|
||||
}
|
||||
|
||||
let _ = labels.remove(TIMESTAMP_COLUMN_NAME);
|
||||
let _ = labels.remove(FIELD_COLUMN_NAME);
|
||||
let _ = labels.remove(GREPTIME_TIMESTAMP);
|
||||
let _ = labels.remove(GREPTIME_VALUE);
|
||||
|
||||
let mut sorted_labels: Vec<String> = labels.into_iter().collect();
|
||||
sorted_labels.sort();
|
||||
|
||||
@@ -22,6 +22,7 @@ use std::sync::Arc;
|
||||
|
||||
use api::v1::RowInsertRequests;
|
||||
use async_trait::async_trait;
|
||||
use common_query::prelude::{GREPTIME_TIMESTAMP, GREPTIME_VALUE};
|
||||
use common_runtime::Runtime;
|
||||
use common_telemetry::logging::error;
|
||||
use futures::StreamExt;
|
||||
@@ -31,7 +32,6 @@ use self::codec::DataPoint;
|
||||
use crate::error::Result;
|
||||
use crate::opentsdb::connection::Connection;
|
||||
use crate::opentsdb::handler::Handler;
|
||||
use crate::prom_store::{FIELD_COLUMN_NAME, TIMESTAMP_COLUMN_NAME};
|
||||
use crate::query_handler::OpentsdbProtocolHandlerRef;
|
||||
use crate::row_writer::{self, MultiTableData};
|
||||
use crate::server::{AbortableStream, BaseTcpServer, Server};
|
||||
@@ -151,11 +151,11 @@ pub fn data_point_to_grpc_row_insert_requests(
|
||||
row_writer::write_tags(table_data, tags.into_iter(), &mut one_row)?;
|
||||
|
||||
// value
|
||||
row_writer::write_f64(table_data, FIELD_COLUMN_NAME, value, &mut one_row)?;
|
||||
row_writer::write_f64(table_data, GREPTIME_VALUE, value, &mut one_row)?;
|
||||
// timestamp
|
||||
row_writer::write_ts_millis(
|
||||
table_data,
|
||||
TIMESTAMP_COLUMN_NAME,
|
||||
GREPTIME_TIMESTAMP,
|
||||
Some(timestamp),
|
||||
&mut one_row,
|
||||
)?;
|
||||
|
||||
@@ -13,12 +13,10 @@
|
||||
// limitations under the License.
|
||||
|
||||
use api::v1::{column, Column, ColumnDataType, InsertRequest as GrpcInsertRequest, SemanticType};
|
||||
use common_query::prelude::{GREPTIME_TIMESTAMP, GREPTIME_VALUE};
|
||||
|
||||
use crate::error::{self, Result};
|
||||
|
||||
pub const OPENTSDB_TIMESTAMP_COLUMN_NAME: &str = "greptime_timestamp";
|
||||
pub const OPENTSDB_FIELD_COLUMN_NAME: &str = "greptime_value";
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DataPoint {
|
||||
metric: String,
|
||||
@@ -131,7 +129,7 @@ impl DataPoint {
|
||||
let mut columns = Vec::with_capacity(2 + self.tags.len());
|
||||
|
||||
let ts_column = Column {
|
||||
column_name: OPENTSDB_TIMESTAMP_COLUMN_NAME.to_string(),
|
||||
column_name: GREPTIME_TIMESTAMP.to_string(),
|
||||
values: Some(column::Values {
|
||||
timestamp_millisecond_values: vec![self.ts_millis],
|
||||
..Default::default()
|
||||
@@ -143,7 +141,7 @@ impl DataPoint {
|
||||
columns.push(ts_column);
|
||||
|
||||
let field_column = Column {
|
||||
column_name: OPENTSDB_FIELD_COLUMN_NAME.to_string(),
|
||||
column_name: GREPTIME_VALUE.to_string(),
|
||||
values: Some(column::Values {
|
||||
f64_values: vec![self.value],
|
||||
..Default::default()
|
||||
@@ -269,7 +267,7 @@ mod test {
|
||||
assert_eq!(row_count, 1);
|
||||
assert_eq!(columns.len(), 4);
|
||||
|
||||
assert_eq!(columns[0].column_name, OPENTSDB_TIMESTAMP_COLUMN_NAME);
|
||||
assert_eq!(columns[0].column_name, GREPTIME_TIMESTAMP);
|
||||
assert_eq!(
|
||||
columns[0]
|
||||
.values
|
||||
@@ -279,7 +277,7 @@ mod test {
|
||||
vec![1000]
|
||||
);
|
||||
|
||||
assert_eq!(columns[1].column_name, OPENTSDB_FIELD_COLUMN_NAME);
|
||||
assert_eq!(columns[1].column_name, GREPTIME_VALUE);
|
||||
assert_eq!(columns[1].values.as_ref().unwrap().f64_values, vec![1.0]);
|
||||
|
||||
assert_eq!(columns[2].column_name, "tagk1");
|
||||
|
||||
@@ -15,7 +15,3 @@
|
||||
pub mod metrics;
|
||||
pub mod plugin;
|
||||
pub mod trace;
|
||||
|
||||
const GREPTIME_TIMESTAMP: &str = "greptime_timestamp";
|
||||
const GREPTIME_VALUE: &str = "greptime_value";
|
||||
const GREPTIME_COUNT: &str = "greptime_count";
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
|
||||
use api::v1::{RowInsertRequests, Value};
|
||||
use common_grpc::writer::Precision;
|
||||
use common_query::prelude::{GREPTIME_COUNT, GREPTIME_TIMESTAMP, GREPTIME_VALUE};
|
||||
use opentelemetry_proto::tonic::collector::metrics::v1::ExportMetricsServiceRequest;
|
||||
use opentelemetry_proto::tonic::common::v1::{any_value, KeyValue};
|
||||
use opentelemetry_proto::tonic::metrics::v1::{metric, number_data_point, *};
|
||||
|
||||
use super::{GREPTIME_COUNT, GREPTIME_TIMESTAMP, GREPTIME_VALUE};
|
||||
use crate::error::Result;
|
||||
use crate::row_writer::{self, MultiTableData, TableData};
|
||||
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
use api::v1::value::ValueData;
|
||||
use api::v1::{ColumnDataType, RowInsertRequests};
|
||||
use common_grpc::writer::Precision;
|
||||
use common_query::prelude::{GREPTIME_TIMESTAMP, GREPTIME_VALUE};
|
||||
use opentelemetry_proto::tonic::collector::trace::v1::ExportTraceServiceRequest;
|
||||
|
||||
use self::span::{parse_span, TraceSpan, TraceSpans};
|
||||
use super::{GREPTIME_TIMESTAMP, GREPTIME_VALUE};
|
||||
use crate::error::Result;
|
||||
use crate::row_writer::{self, MultiTableData, TableData};
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ use std::hash::{Hash, Hasher};
|
||||
use api::prom_store::remote::label_matcher::Type as MatcherType;
|
||||
use api::prom_store::remote::{Label, Query, Sample, TimeSeries, WriteRequest};
|
||||
use api::v1::RowInsertRequests;
|
||||
use common_query::prelude::{GREPTIME_TIMESTAMP, GREPTIME_VALUE};
|
||||
use common_recordbatch::{RecordBatch, RecordBatches};
|
||||
use common_time::timestamp::TimeUnit;
|
||||
use datafusion::prelude::{col, lit, regexp_match, Expr};
|
||||
@@ -35,8 +36,6 @@ use snap::raw::{Decoder, Encoder};
|
||||
use crate::error::{self, Result};
|
||||
use crate::row_writer::{self, MultiTableData};
|
||||
|
||||
pub const TIMESTAMP_COLUMN_NAME: &str = "greptime_timestamp";
|
||||
pub const FIELD_COLUMN_NAME: &str = "greptime_value";
|
||||
pub const METRIC_NAME_LABEL: &str = "__name__";
|
||||
|
||||
/// Metrics for push gateway protocol
|
||||
@@ -73,9 +72,8 @@ pub fn query_to_plan(dataframe: DataFrame, q: &Query) -> Result<LogicalPlan> {
|
||||
|
||||
let mut conditions = Vec::with_capacity(label_matches.len() + 1);
|
||||
|
||||
conditions
|
||||
.push(col(TIMESTAMP_COLUMN_NAME).gt_eq(lit_timestamp_millisecond(start_timestamp_ms)));
|
||||
conditions.push(col(TIMESTAMP_COLUMN_NAME).lt_eq(lit_timestamp_millisecond(end_timestamp_ms)));
|
||||
conditions.push(col(GREPTIME_TIMESTAMP).gt_eq(lit_timestamp_millisecond(start_timestamp_ms)));
|
||||
conditions.push(col(GREPTIME_TIMESTAMP).lt_eq(lit_timestamp_millisecond(end_timestamp_ms)));
|
||||
|
||||
for m in label_matches {
|
||||
let name = &m.name;
|
||||
@@ -204,9 +202,7 @@ fn collect_timeseries_ids(table_name: &str, recordbatch: &RecordBatch) -> Vec<Ti
|
||||
));
|
||||
|
||||
for (i, column_schema) in recordbatch.schema.column_schemas().iter().enumerate() {
|
||||
if column_schema.name == FIELD_COLUMN_NAME
|
||||
|| column_schema.name == TIMESTAMP_COLUMN_NAME
|
||||
{
|
||||
if column_schema.name == GREPTIME_VALUE || column_schema.name == GREPTIME_TIMESTAMP {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -239,7 +235,7 @@ pub fn recordbatches_to_timeseries(
|
||||
}
|
||||
|
||||
fn recordbatch_to_timeseries(table: &str, recordbatch: RecordBatch) -> Result<Vec<TimeSeries>> {
|
||||
let ts_column = recordbatch.column_by_name(TIMESTAMP_COLUMN_NAME).context(
|
||||
let ts_column = recordbatch.column_by_name(GREPTIME_TIMESTAMP).context(
|
||||
error::InvalidPromRemoteReadQueryResultSnafu {
|
||||
msg: "missing greptime_timestamp column in query result",
|
||||
},
|
||||
@@ -254,7 +250,7 @@ fn recordbatch_to_timeseries(table: &str, recordbatch: RecordBatch) -> Result<Ve
|
||||
}
|
||||
);
|
||||
|
||||
let field_column = recordbatch.column_by_name(FIELD_COLUMN_NAME).context(
|
||||
let field_column = recordbatch.column_by_name(GREPTIME_VALUE).context(
|
||||
error::InvalidPromRemoteReadQueryResultSnafu {
|
||||
msg: "missing greptime_value column in query result",
|
||||
},
|
||||
@@ -341,11 +337,11 @@ pub fn to_grpc_row_insert_requests(request: WriteRequest) -> Result<(RowInsertRe
|
||||
});
|
||||
row_writer::write_tags(table_data, kvs, &mut one_row)?;
|
||||
// value
|
||||
row_writer::write_f64(table_data, FIELD_COLUMN_NAME, *value, &mut one_row)?;
|
||||
row_writer::write_f64(table_data, GREPTIME_VALUE, *value, &mut one_row)?;
|
||||
// timestamp
|
||||
row_writer::write_ts_millis(
|
||||
table_data,
|
||||
TIMESTAMP_COLUMN_NAME,
|
||||
GREPTIME_TIMESTAMP,
|
||||
Some(*timestamp),
|
||||
&mut one_row,
|
||||
)?;
|
||||
@@ -494,15 +490,11 @@ mod tests {
|
||||
|
||||
let schema = Arc::new(Schema::new(vec![
|
||||
ColumnSchema::new(
|
||||
TIMESTAMP_COLUMN_NAME,
|
||||
GREPTIME_TIMESTAMP,
|
||||
ConcreteDataType::timestamp_millisecond_datatype(),
|
||||
true,
|
||||
),
|
||||
ColumnSchema::new(
|
||||
FIELD_COLUMN_NAME,
|
||||
ConcreteDataType::float64_datatype(),
|
||||
true,
|
||||
),
|
||||
ColumnSchema::new(GREPTIME_VALUE, ConcreteDataType::float64_datatype(), true),
|
||||
ColumnSchema::new("instance", ConcreteDataType::string_datatype(), true),
|
||||
ColumnSchema::new("job", ConcreteDataType::string_datatype(), true),
|
||||
]));
|
||||
@@ -701,15 +693,11 @@ mod tests {
|
||||
fn test_recordbatches_to_timeseries() {
|
||||
let schema = Arc::new(Schema::new(vec![
|
||||
ColumnSchema::new(
|
||||
TIMESTAMP_COLUMN_NAME,
|
||||
GREPTIME_TIMESTAMP,
|
||||
ConcreteDataType::timestamp_millisecond_datatype(),
|
||||
true,
|
||||
),
|
||||
ColumnSchema::new(
|
||||
FIELD_COLUMN_NAME,
|
||||
ConcreteDataType::float64_datatype(),
|
||||
true,
|
||||
),
|
||||
ColumnSchema::new(GREPTIME_VALUE, ConcreteDataType::float64_datatype(), true),
|
||||
ColumnSchema::new("instance", ConcreteDataType::string_datatype(), true),
|
||||
]));
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ create table http_requests (
|
||||
job string,
|
||||
instance string,
|
||||
g string, -- for `group`
|
||||
val double,
|
||||
greptime_value double,
|
||||
primary key (job, instance, g)
|
||||
);
|
||||
|
||||
@@ -32,7 +32,7 @@ Affected Rows: 0
|
||||
create table vector_matching_a(
|
||||
ts timestamp time index,
|
||||
l string primary key,
|
||||
val double,
|
||||
greptime_value double,
|
||||
);
|
||||
|
||||
Affected Rows: 0
|
||||
@@ -49,12 +49,12 @@ Affected Rows: 2
|
||||
-- SQLNESS SORT_RESULT 3 1
|
||||
tql eval (3000, 3000, '1s') http_requests{g="canary"} and http_requests{instance="0"};
|
||||
|
||||
+---------------------+-----+----------+--------+-------+
|
||||
| ts | job | instance | g | val |
|
||||
+---------------------+-----+----------+--------+-------+
|
||||
| 1970-01-01T00:50:00 | api | 0 | canary | 300.0 |
|
||||
| 1970-01-01T00:50:00 | app | 0 | canary | 700.0 |
|
||||
+---------------------+-----+----------+--------+-------+
|
||||
+---------------------+-----+----------+--------+----------------+
|
||||
| ts | job | instance | g | greptime_value |
|
||||
+---------------------+-----+----------+--------+----------------+
|
||||
| 1970-01-01T00:50:00 | api | 0 | canary | 300.0 |
|
||||
| 1970-01-01T00:50:00 | app | 0 | canary | 700.0 |
|
||||
+---------------------+-----+----------+--------+----------------+
|
||||
|
||||
-- eval instant at 50m (http_requests{group="canary"} + 1) and http_requests{instance="0"}
|
||||
-- {group="canary", instance="0", job="api-server"} 301
|
||||
@@ -62,12 +62,12 @@ tql eval (3000, 3000, '1s') http_requests{g="canary"} and http_requests{instance
|
||||
-- SQLNESS SORT_RESULT 3 1
|
||||
tql eval (3000, 3000, '1s') (http_requests{g="canary"} + 1) and http_requests{instance="0"};
|
||||
|
||||
+-----+----------+--------+---------------------+------------------+
|
||||
| job | instance | g | ts | val + Float64(1) |
|
||||
+-----+----------+--------+---------------------+------------------+
|
||||
| api | 0 | canary | 1970-01-01T00:50:00 | 301.0 |
|
||||
| app | 0 | canary | 1970-01-01T00:50:00 | 701.0 |
|
||||
+-----+----------+--------+---------------------+------------------+
|
||||
+-----+----------+--------+---------------------+-----------------------------+
|
||||
| job | instance | g | ts | greptime_value + Float64(1) |
|
||||
+-----+----------+--------+---------------------+-----------------------------+
|
||||
| api | 0 | canary | 1970-01-01T00:50:00 | 301.0 |
|
||||
| app | 0 | canary | 1970-01-01T00:50:00 | 701.0 |
|
||||
+-----+----------+--------+---------------------+-----------------------------+
|
||||
|
||||
-- eval instant at 50m (http_requests{group="canary"} + 1) and on(instance, job) http_requests{instance="0", group="production"}
|
||||
-- {group="canary", instance="0", job="api-server"} 301
|
||||
@@ -75,12 +75,12 @@ tql eval (3000, 3000, '1s') (http_requests{g="canary"} + 1) and http_requests{in
|
||||
-- SQLNESS SORT_RESULT 3 1
|
||||
tql eval (3000, 3000, '1s') (http_requests{g="canary"} + 1) and on(instance, job) http_requests{instance="0", g="production"};
|
||||
|
||||
+-----+----------+--------+---------------------+------------------+
|
||||
| job | instance | g | ts | val + Float64(1) |
|
||||
+-----+----------+--------+---------------------+------------------+
|
||||
| api | 0 | canary | 1970-01-01T00:50:00 | 301.0 |
|
||||
| app | 0 | canary | 1970-01-01T00:50:00 | 701.0 |
|
||||
+-----+----------+--------+---------------------+------------------+
|
||||
+-----+----------+--------+---------------------+-----------------------------+
|
||||
| job | instance | g | ts | greptime_value + Float64(1) |
|
||||
+-----+----------+--------+---------------------+-----------------------------+
|
||||
| api | 0 | canary | 1970-01-01T00:50:00 | 301.0 |
|
||||
| app | 0 | canary | 1970-01-01T00:50:00 | 701.0 |
|
||||
+-----+----------+--------+---------------------+-----------------------------+
|
||||
|
||||
-- eval instant at 50m (http_requests{group="canary"} + 1) and on(instance) http_requests{instance="0", group="production"}
|
||||
-- {group="canary", instance="0", job="api-server"} 301
|
||||
@@ -88,12 +88,12 @@ tql eval (3000, 3000, '1s') (http_requests{g="canary"} + 1) and on(instance, job
|
||||
-- SQLNESS SORT_RESULT 3 1
|
||||
tql eval (3000, 3000, '1s') (http_requests{g="canary"} + 1) and on(instance) http_requests{instance="0", g="production"};
|
||||
|
||||
+-----+----------+--------+---------------------+------------------+
|
||||
| job | instance | g | ts | val + Float64(1) |
|
||||
+-----+----------+--------+---------------------+------------------+
|
||||
| api | 0 | canary | 1970-01-01T00:50:00 | 301.0 |
|
||||
| app | 0 | canary | 1970-01-01T00:50:00 | 701.0 |
|
||||
+-----+----------+--------+---------------------+------------------+
|
||||
+-----+----------+--------+---------------------+-----------------------------+
|
||||
| job | instance | g | ts | greptime_value + Float64(1) |
|
||||
+-----+----------+--------+---------------------+-----------------------------+
|
||||
| api | 0 | canary | 1970-01-01T00:50:00 | 301.0 |
|
||||
| app | 0 | canary | 1970-01-01T00:50:00 | 701.0 |
|
||||
+-----+----------+--------+---------------------+-----------------------------+
|
||||
|
||||
-- eval instant at 50m (http_requests{group="canary"} + 1) and ignoring(group) http_requests{instance="0", group="production"}
|
||||
-- {group="canary", instance="0", job="api-server"} 301
|
||||
@@ -101,12 +101,12 @@ tql eval (3000, 3000, '1s') (http_requests{g="canary"} + 1) and on(instance) htt
|
||||
-- SQLNESS SORT_RESULT 3 1
|
||||
tql eval (3000, 3000, '1s') (http_requests{g="canary"} + 1) and ignoring(g) http_requests{instance="0", g="production"};
|
||||
|
||||
+-----+----------+--------+---------------------+------------------+
|
||||
| job | instance | g | ts | val + Float64(1) |
|
||||
+-----+----------+--------+---------------------+------------------+
|
||||
| api | 0 | canary | 1970-01-01T00:50:00 | 301.0 |
|
||||
| app | 0 | canary | 1970-01-01T00:50:00 | 701.0 |
|
||||
+-----+----------+--------+---------------------+------------------+
|
||||
+-----+----------+--------+---------------------+-----------------------------+
|
||||
| job | instance | g | ts | greptime_value + Float64(1) |
|
||||
+-----+----------+--------+---------------------+-----------------------------+
|
||||
| api | 0 | canary | 1970-01-01T00:50:00 | 301.0 |
|
||||
| app | 0 | canary | 1970-01-01T00:50:00 | 701.0 |
|
||||
+-----+----------+--------+---------------------+-----------------------------+
|
||||
|
||||
-- eval instant at 50m (http_requests{group="canary"} + 1) and ignoring(group, job) http_requests{instance="0", group="production"}
|
||||
-- {group="canary", instance="0", job="api-server"} 301
|
||||
@@ -114,12 +114,12 @@ tql eval (3000, 3000, '1s') (http_requests{g="canary"} + 1) and ignoring(g) http
|
||||
-- SQLNESS SORT_RESULT 3 1
|
||||
tql eval (3000, 3000, '1s') (http_requests{g="canary"} + 1) and ignoring(g, job) http_requests{instance="0", g="production"};
|
||||
|
||||
+-----+----------+--------+---------------------+------------------+
|
||||
| job | instance | g | ts | val + Float64(1) |
|
||||
+-----+----------+--------+---------------------+------------------+
|
||||
| api | 0 | canary | 1970-01-01T00:50:00 | 301.0 |
|
||||
| app | 0 | canary | 1970-01-01T00:50:00 | 701.0 |
|
||||
+-----+----------+--------+---------------------+------------------+
|
||||
+-----+----------+--------+---------------------+-----------------------------+
|
||||
| job | instance | g | ts | greptime_value + Float64(1) |
|
||||
+-----+----------+--------+---------------------+-----------------------------+
|
||||
| api | 0 | canary | 1970-01-01T00:50:00 | 301.0 |
|
||||
| app | 0 | canary | 1970-01-01T00:50:00 | 701.0 |
|
||||
+-----+----------+--------+---------------------+-----------------------------+
|
||||
|
||||
-- eval instant at 50m http_requests{group="canary"} or http_requests{group="production"}
|
||||
-- http_requests{group="canary", instance="0", job="api-server"} 300
|
||||
@@ -133,18 +133,18 @@ tql eval (3000, 3000, '1s') (http_requests{g="canary"} + 1) and ignoring(g, job)
|
||||
-- SQLNESS SORT_RESULT 3 1
|
||||
tql eval (3000, 3000, '1s') http_requests{g="canary"} or http_requests{g="production"};
|
||||
|
||||
+------------+----------+-----+---------------------+-------+
|
||||
| g | instance | job | ts | val |
|
||||
+------------+----------+-----+---------------------+-------+
|
||||
| canary | 0 | api | 1970-01-01T00:50:00 | 300.0 |
|
||||
| canary | 0 | app | 1970-01-01T00:50:00 | 700.0 |
|
||||
| canary | 1 | api | 1970-01-01T00:50:00 | 400.0 |
|
||||
| canary | 1 | app | 1970-01-01T00:50:00 | 800.0 |
|
||||
| production | 0 | api | 1970-01-01T00:50:00 | 100.0 |
|
||||
| production | 0 | app | 1970-01-01T00:50:00 | 500.0 |
|
||||
| production | 1 | api | 1970-01-01T00:50:00 | 200.0 |
|
||||
| production | 1 | app | 1970-01-01T00:50:00 | 600.0 |
|
||||
+------------+----------+-----+---------------------+-------+
|
||||
+---------------------+------------+----------------+----------+-----+
|
||||
| ts | g | greptime_value | instance | job |
|
||||
+---------------------+------------+----------------+----------+-----+
|
||||
| 1970-01-01T00:50:00 | canary | 300.0 | 0 | api |
|
||||
| 1970-01-01T00:50:00 | canary | 400.0 | 1 | api |
|
||||
| 1970-01-01T00:50:00 | canary | 700.0 | 0 | app |
|
||||
| 1970-01-01T00:50:00 | canary | 800.0 | 1 | app |
|
||||
| 1970-01-01T00:50:00 | production | 100.0 | 0 | api |
|
||||
| 1970-01-01T00:50:00 | production | 200.0 | 1 | api |
|
||||
| 1970-01-01T00:50:00 | production | 500.0 | 0 | app |
|
||||
| 1970-01-01T00:50:00 | production | 600.0 | 1 | app |
|
||||
+---------------------+------------+----------------+----------+-----+
|
||||
|
||||
-- # On overlap the rhs samples must be dropped.
|
||||
-- eval instant at 50m (http_requests{group="canary"} + 1) or http_requests{instance="1"}
|
||||
@@ -157,7 +157,7 @@ tql eval (3000, 3000, '1s') http_requests{g="canary"} or http_requests{g="produc
|
||||
-- SQLNESS SORT_RESULT 3 1
|
||||
tql eval (3000, 3000, '1s') (http_requests{g="canary"} + 1) or http_requests{instance="1"};
|
||||
|
||||
Error: 1004(InvalidArguments), Internal error during building DataFusion plan: No field named http_requests.val. Valid fields are http_requests.job, http_requests.instance, http_requests.g, http_requests.ts, "val + Float64(1)".
|
||||
Error: 1004(InvalidArguments), Internal error during building DataFusion plan: No field named http_requests.greptime_value. Valid fields are http_requests.job, http_requests.instance, http_requests.g, http_requests.ts, "greptime_value + Float64(1)".
|
||||
|
||||
-- # Matching only on instance excludes everything that has instance=0/1 but includes
|
||||
-- # entries without the instance label.
|
||||
@@ -172,7 +172,7 @@ Error: 1004(InvalidArguments), Internal error during building DataFusion plan: N
|
||||
-- NOT SUPPORTED: `or`
|
||||
tql eval (3000, 3000, '1s') (http_requests{g="canary"} + 1) or on(instance) (http_requests or cpu_count or vector_matching_a);
|
||||
|
||||
Error: 1004(InvalidArguments), Internal error during building DataFusion plan: No field named cpu_count.val. Valid fields are cpu_count.ts.
|
||||
Error: 1004(InvalidArguments), Internal error during building DataFusion plan: No field named cpu_count.greptime_value. Valid fields are cpu_count.ts.
|
||||
|
||||
-- eval instant at 50m (http_requests{group="canary"} + 1) or ignoring(l, group, job) (http_requests or cpu_count or vector_matching_a)
|
||||
-- {group="canary", instance="0", job="api-server"} 301
|
||||
@@ -185,7 +185,7 @@ Error: 1004(InvalidArguments), Internal error during building DataFusion plan: N
|
||||
-- NOT SUPPORTED: `or`
|
||||
tql eval (3000, 3000, '1s') (http_requests{g="canary"} + 1) or ignoring(l, g, job) (http_requests or cpu_count or vector_matching_a);
|
||||
|
||||
Error: 1004(InvalidArguments), Internal error during building DataFusion plan: No field named cpu_count.val. Valid fields are cpu_count.ts.
|
||||
Error: 1004(InvalidArguments), Internal error during building DataFusion plan: No field named cpu_count.greptime_value. Valid fields are cpu_count.ts.
|
||||
|
||||
-- eval instant at 50m http_requests{group="canary"} unless http_requests{instance="0"}
|
||||
-- http_requests{group="canary", instance="1", job="api-server"} 400
|
||||
@@ -193,12 +193,12 @@ Error: 1004(InvalidArguments), Internal error during building DataFusion plan: N
|
||||
-- SQLNESS SORT_RESULT 3 1
|
||||
tql eval (3000, 3000, '1s') http_requests{g="canary"} unless http_requests{instance="0"};
|
||||
|
||||
+---------------------+-----+----------+--------+-------+
|
||||
| ts | job | instance | g | val |
|
||||
+---------------------+-----+----------+--------+-------+
|
||||
| 1970-01-01T00:50:00 | api | 1 | canary | 400.0 |
|
||||
| 1970-01-01T00:50:00 | app | 1 | canary | 800.0 |
|
||||
+---------------------+-----+----------+--------+-------+
|
||||
+---------------------+-----+----------+--------+----------------+
|
||||
| ts | job | instance | g | greptime_value |
|
||||
+---------------------+-----+----------+--------+----------------+
|
||||
| 1970-01-01T00:50:00 | api | 1 | canary | 400.0 |
|
||||
| 1970-01-01T00:50:00 | app | 1 | canary | 800.0 |
|
||||
+---------------------+-----+----------+--------+----------------+
|
||||
|
||||
-- eval instant at 50m http_requests{group="canary"} unless on(job) http_requests{instance="0"}
|
||||
tql eval (3000, 3000, '1s') http_requests{g="canary"} unless on(job) http_requests{instance="0"};
|
||||
@@ -212,12 +212,12 @@ tql eval (3000, 3000, '1s') http_requests{g="canary"} unless on(job) http_reques
|
||||
-- SQLNESS SORT_RESULT 3 1
|
||||
tql eval (3000, 3000, '1s') http_requests{g="canary"} unless on(job, instance) http_requests{instance="0"};
|
||||
|
||||
+---------------------+-----+----------+--------+-------+
|
||||
| ts | job | instance | g | val |
|
||||
+---------------------+-----+----------+--------+-------+
|
||||
| 1970-01-01T00:50:00 | api | 1 | canary | 400.0 |
|
||||
| 1970-01-01T00:50:00 | app | 1 | canary | 800.0 |
|
||||
+---------------------+-----+----------+--------+-------+
|
||||
+---------------------+-----+----------+--------+----------------+
|
||||
| ts | job | instance | g | greptime_value |
|
||||
+---------------------+-----+----------+--------+----------------+
|
||||
| 1970-01-01T00:50:00 | api | 1 | canary | 400.0 |
|
||||
| 1970-01-01T00:50:00 | app | 1 | canary | 800.0 |
|
||||
+---------------------+-----+----------+--------+----------------+
|
||||
|
||||
-- eval instant at 50m http_requests{group="canary"} unless ignoring(group, instance) http_requests{instance="0"}
|
||||
tql eval (3000, 3000, '1s') http_requests{g="canary"} unless ignoring(g, instance) http_requests{instance="0"};
|
||||
@@ -231,12 +231,12 @@ tql eval (3000, 3000, '1s') http_requests{g="canary"} unless ignoring(g, instanc
|
||||
-- SQLNESS SORT_RESULT 3 1
|
||||
tql eval (3000, 3000, '1s') http_requests{g="canary"} unless ignoring(g) http_requests{instance="0"};
|
||||
|
||||
+---------------------+-----+----------+--------+-------+
|
||||
| ts | job | instance | g | val |
|
||||
+---------------------+-----+----------+--------+-------+
|
||||
| 1970-01-01T00:50:00 | api | 1 | canary | 400.0 |
|
||||
| 1970-01-01T00:50:00 | app | 1 | canary | 800.0 |
|
||||
+---------------------+-----+----------+--------+-------+
|
||||
+---------------------+-----+----------+--------+----------------+
|
||||
| ts | job | instance | g | greptime_value |
|
||||
+---------------------+-----+----------+--------+----------------+
|
||||
| 1970-01-01T00:50:00 | api | 1 | canary | 400.0 |
|
||||
| 1970-01-01T00:50:00 | app | 1 | canary | 800.0 |
|
||||
+---------------------+-----+----------+--------+----------------+
|
||||
|
||||
-- # https://github.com/prometheus/prometheus/issues/1489
|
||||
-- eval instant at 50m http_requests AND ON (dummy) vector(1)
|
||||
@@ -251,7 +251,7 @@ tql eval (3000, 3000, '1s') http_requests{g="canary"} unless ignoring(g) http_re
|
||||
-- NOT SUPPORTED: `vector()`
|
||||
tql eval (3000, 3000, '1s') http_requests AND ON (dummy) vector(1);
|
||||
|
||||
Error: 1004(InvalidArguments), Unsupported expr type: vector
|
||||
Error: 1004(InvalidArguments), Internal error during building DataFusion plan: No field named time. Valid fields are http_requests.ts, http_requests.job, http_requests.instance, http_requests.g, http_requests.greptime_value.
|
||||
|
||||
-- eval instant at 50m http_requests AND IGNORING (group, instance, job) vector(1)
|
||||
-- http_requests{group="canary", instance="0", job="api-server"} 300
|
||||
@@ -265,7 +265,7 @@ Error: 1004(InvalidArguments), Unsupported expr type: vector
|
||||
-- NOT SUPPORTED: `vector()`
|
||||
tql eval (3000, 3000, '1s') http_requests AND IGNORING (g, instance, job) vector(1);
|
||||
|
||||
Error: 1004(InvalidArguments), Unsupported expr type: vector
|
||||
Error: 1004(InvalidArguments), Internal error during building DataFusion plan: No field named time. Valid fields are http_requests.ts, http_requests.job, http_requests.instance, http_requests.g, http_requests.greptime_value.
|
||||
|
||||
drop table http_requests;
|
||||
|
||||
@@ -280,7 +280,7 @@ drop table vector_matching_a;
|
||||
Affected Rows: 0
|
||||
|
||||
-- the following cases are not from Prometheus.
|
||||
create table t1 (ts timestamp time index, job string primary key, val double);
|
||||
create table t1 (ts timestamp time index, job string primary key, greptime_value double);
|
||||
|
||||
Affected Rows: 0
|
||||
|
||||
@@ -288,7 +288,7 @@ insert into t1 values (0, "a", 1.0), (500000, "b", 2.0), (1000000, "a", 3.0), (1
|
||||
|
||||
Affected Rows: 4
|
||||
|
||||
create table t2 (ts timestamp time index, val double);
|
||||
create table t2 (ts timestamp time index, greptime_value double);
|
||||
|
||||
Affected Rows: 0
|
||||
|
||||
@@ -299,102 +299,102 @@ Affected Rows: 7
|
||||
-- SQLNESS SORT_RESULT 3 1
|
||||
tql eval (0, 2000, '400') t1 or t2;
|
||||
|
||||
+-----+---------------------+-----+
|
||||
| job | ts | val |
|
||||
+-----+---------------------+-----+
|
||||
| | 1970-01-01T00:00:00 | 0.0 |
|
||||
| | 1970-01-01T00:06:40 | 0.0 |
|
||||
| | 1970-01-01T00:13:20 | 0.0 |
|
||||
| | 1970-01-01T00:20:00 | 0.0 |
|
||||
| | 1970-01-01T00:26:40 | 0.0 |
|
||||
| | 1970-01-01T00:33:20 | 0.0 |
|
||||
| a | 1970-01-01T00:00:00 | 1.0 |
|
||||
| a | 1970-01-01T00:20:00 | 3.0 |
|
||||
| b | 1970-01-01T00:13:20 | 2.0 |
|
||||
| c | 1970-01-01T00:26:40 | 4.0 |
|
||||
+-----+---------------------+-----+
|
||||
+---------------------+----------------+-----+
|
||||
| ts | greptime_value | job |
|
||||
+---------------------+----------------+-----+
|
||||
| 1970-01-01T00:00:00 | 0.0 | |
|
||||
| 1970-01-01T00:00:00 | 1.0 | a |
|
||||
| 1970-01-01T00:06:40 | 0.0 | |
|
||||
| 1970-01-01T00:13:20 | 0.0 | |
|
||||
| 1970-01-01T00:13:20 | 2.0 | b |
|
||||
| 1970-01-01T00:20:00 | 0.0 | |
|
||||
| 1970-01-01T00:20:00 | 3.0 | a |
|
||||
| 1970-01-01T00:26:40 | 0.0 | |
|
||||
| 1970-01-01T00:26:40 | 4.0 | c |
|
||||
| 1970-01-01T00:33:20 | 0.0 | |
|
||||
+---------------------+----------------+-----+
|
||||
|
||||
-- SQLNESS SORT_RESULT 3 1
|
||||
tql eval (0, 2000, '400') t1 or on () t2;
|
||||
|
||||
+-----+---------------------+-----+
|
||||
| job | ts | val |
|
||||
+-----+---------------------+-----+
|
||||
| | 1970-01-01T00:06:40 | 0.0 |
|
||||
| | 1970-01-01T00:33:20 | 0.0 |
|
||||
| a | 1970-01-01T00:00:00 | 1.0 |
|
||||
| a | 1970-01-01T00:20:00 | 3.0 |
|
||||
| b | 1970-01-01T00:13:20 | 2.0 |
|
||||
| c | 1970-01-01T00:26:40 | 4.0 |
|
||||
+-----+---------------------+-----+
|
||||
+---------------------+----------------+-----+
|
||||
| ts | greptime_value | job |
|
||||
+---------------------+----------------+-----+
|
||||
| 1970-01-01T00:00:00 | 1.0 | a |
|
||||
| 1970-01-01T00:06:40 | 0.0 | |
|
||||
| 1970-01-01T00:13:20 | 2.0 | b |
|
||||
| 1970-01-01T00:20:00 | 3.0 | a |
|
||||
| 1970-01-01T00:26:40 | 4.0 | c |
|
||||
| 1970-01-01T00:33:20 | 0.0 | |
|
||||
+---------------------+----------------+-----+
|
||||
|
||||
-- SQLNESS SORT_RESULT 3 1
|
||||
tql eval (0, 2000, '400') t1 or on (job) t2;
|
||||
|
||||
+-----+---------------------+-----+
|
||||
| job | ts | val |
|
||||
+-----+---------------------+-----+
|
||||
| | 1970-01-01T00:00:00 | 0.0 |
|
||||
| | 1970-01-01T00:06:40 | 0.0 |
|
||||
| | 1970-01-01T00:13:20 | 0.0 |
|
||||
| | 1970-01-01T00:20:00 | 0.0 |
|
||||
| | 1970-01-01T00:26:40 | 0.0 |
|
||||
| | 1970-01-01T00:33:20 | 0.0 |
|
||||
| a | 1970-01-01T00:00:00 | 1.0 |
|
||||
| a | 1970-01-01T00:20:00 | 3.0 |
|
||||
| b | 1970-01-01T00:13:20 | 2.0 |
|
||||
| c | 1970-01-01T00:26:40 | 4.0 |
|
||||
+-----+---------------------+-----+
|
||||
+---------------------+----------------+-----+
|
||||
| ts | greptime_value | job |
|
||||
+---------------------+----------------+-----+
|
||||
| 1970-01-01T00:00:00 | 0.0 | |
|
||||
| 1970-01-01T00:00:00 | 1.0 | a |
|
||||
| 1970-01-01T00:06:40 | 0.0 | |
|
||||
| 1970-01-01T00:13:20 | 0.0 | |
|
||||
| 1970-01-01T00:13:20 | 2.0 | b |
|
||||
| 1970-01-01T00:20:00 | 0.0 | |
|
||||
| 1970-01-01T00:20:00 | 3.0 | a |
|
||||
| 1970-01-01T00:26:40 | 0.0 | |
|
||||
| 1970-01-01T00:26:40 | 4.0 | c |
|
||||
| 1970-01-01T00:33:20 | 0.0 | |
|
||||
+---------------------+----------------+-----+
|
||||
|
||||
-- SQLNESS SORT_RESULT 3 1
|
||||
tql eval (0, 2000, '400') t2 or t1;
|
||||
|
||||
+-----+---------------------+-----+
|
||||
| job | ts | val |
|
||||
+-----+---------------------+-----+
|
||||
| | 1970-01-01T00:00:00 | 0.0 |
|
||||
| | 1970-01-01T00:06:40 | 0.0 |
|
||||
| | 1970-01-01T00:13:20 | 0.0 |
|
||||
| | 1970-01-01T00:20:00 | 0.0 |
|
||||
| | 1970-01-01T00:26:40 | 0.0 |
|
||||
| | 1970-01-01T00:33:20 | 0.0 |
|
||||
| a | 1970-01-01T00:00:00 | 1.0 |
|
||||
| a | 1970-01-01T00:20:00 | 3.0 |
|
||||
| b | 1970-01-01T00:13:20 | 2.0 |
|
||||
| c | 1970-01-01T00:26:40 | 4.0 |
|
||||
+-----+---------------------+-----+
|
||||
+---------------------+----------------+-----+
|
||||
| ts | greptime_value | job |
|
||||
+---------------------+----------------+-----+
|
||||
| 1970-01-01T00:00:00 | 0.0 | |
|
||||
| 1970-01-01T00:00:00 | 1.0 | a |
|
||||
| 1970-01-01T00:06:40 | 0.0 | |
|
||||
| 1970-01-01T00:13:20 | 0.0 | |
|
||||
| 1970-01-01T00:13:20 | 2.0 | b |
|
||||
| 1970-01-01T00:20:00 | 0.0 | |
|
||||
| 1970-01-01T00:20:00 | 3.0 | a |
|
||||
| 1970-01-01T00:26:40 | 0.0 | |
|
||||
| 1970-01-01T00:26:40 | 4.0 | c |
|
||||
| 1970-01-01T00:33:20 | 0.0 | |
|
||||
+---------------------+----------------+-----+
|
||||
|
||||
-- SQLNESS SORT_RESULT 3 1
|
||||
tql eval (0, 2000, '400') t2 or on () t1;
|
||||
|
||||
+-----+---------------------+-----+
|
||||
| job | ts | val |
|
||||
+-----+---------------------+-----+
|
||||
| | 1970-01-01T00:00:00 | 0.0 |
|
||||
| | 1970-01-01T00:06:40 | 0.0 |
|
||||
| | 1970-01-01T00:13:20 | 0.0 |
|
||||
| | 1970-01-01T00:20:00 | 0.0 |
|
||||
| | 1970-01-01T00:26:40 | 0.0 |
|
||||
| | 1970-01-01T00:33:20 | 0.0 |
|
||||
+-----+---------------------+-----+
|
||||
+---------------------+----------------+-----+
|
||||
| ts | greptime_value | job |
|
||||
+---------------------+----------------+-----+
|
||||
| 1970-01-01T00:00:00 | 0.0 | |
|
||||
| 1970-01-01T00:06:40 | 0.0 | |
|
||||
| 1970-01-01T00:13:20 | 0.0 | |
|
||||
| 1970-01-01T00:20:00 | 0.0 | |
|
||||
| 1970-01-01T00:26:40 | 0.0 | |
|
||||
| 1970-01-01T00:33:20 | 0.0 | |
|
||||
+---------------------+----------------+-----+
|
||||
|
||||
-- SQLNESS SORT_RESULT 3 1
|
||||
tql eval (0, 2000, '400') t2 or on(job) t1;
|
||||
|
||||
+-----+---------------------+-----+
|
||||
| job | ts | val |
|
||||
+-----+---------------------+-----+
|
||||
| | 1970-01-01T00:00:00 | 0.0 |
|
||||
| | 1970-01-01T00:06:40 | 0.0 |
|
||||
| | 1970-01-01T00:13:20 | 0.0 |
|
||||
| | 1970-01-01T00:20:00 | 0.0 |
|
||||
| | 1970-01-01T00:26:40 | 0.0 |
|
||||
| | 1970-01-01T00:33:20 | 0.0 |
|
||||
| a | 1970-01-01T00:00:00 | 1.0 |
|
||||
| a | 1970-01-01T00:20:00 | 3.0 |
|
||||
| b | 1970-01-01T00:13:20 | 2.0 |
|
||||
| c | 1970-01-01T00:26:40 | 4.0 |
|
||||
+-----+---------------------+-----+
|
||||
+---------------------+----------------+-----+
|
||||
| ts | greptime_value | job |
|
||||
+---------------------+----------------+-----+
|
||||
| 1970-01-01T00:00:00 | 0.0 | |
|
||||
| 1970-01-01T00:00:00 | 1.0 | a |
|
||||
| 1970-01-01T00:06:40 | 0.0 | |
|
||||
| 1970-01-01T00:13:20 | 0.0 | |
|
||||
| 1970-01-01T00:13:20 | 2.0 | b |
|
||||
| 1970-01-01T00:20:00 | 0.0 | |
|
||||
| 1970-01-01T00:20:00 | 3.0 | a |
|
||||
| 1970-01-01T00:26:40 | 0.0 | |
|
||||
| 1970-01-01T00:26:40 | 4.0 | c |
|
||||
| 1970-01-01T00:33:20 | 0.0 | |
|
||||
+---------------------+----------------+-----+
|
||||
|
||||
drop table t1;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ create table http_requests (
|
||||
job string,
|
||||
instance string,
|
||||
g string, -- for `group`
|
||||
val double,
|
||||
greptime_value double,
|
||||
primary key (job, instance, g)
|
||||
);
|
||||
|
||||
@@ -27,7 +27,7 @@ create table cpu_count(ts timestamp time index);
|
||||
create table vector_matching_a(
|
||||
ts timestamp time index,
|
||||
l string primary key,
|
||||
val double,
|
||||
greptime_value double,
|
||||
);
|
||||
|
||||
insert into vector_matching_a values
|
||||
@@ -176,11 +176,11 @@ drop table vector_matching_a;
|
||||
|
||||
-- the following cases are not from Prometheus.
|
||||
|
||||
create table t1 (ts timestamp time index, job string primary key, val double);
|
||||
create table t1 (ts timestamp time index, job string primary key, greptime_value double);
|
||||
|
||||
insert into t1 values (0, "a", 1.0), (500000, "b", 2.0), (1000000, "a", 3.0), (1500000, "c", 4.0);
|
||||
|
||||
create table t2 (ts timestamp time index, val double);
|
||||
create table t2 (ts timestamp time index, greptime_value double);
|
||||
|
||||
insert into t2 values (0, 0), (300000, 0), (600000, 0), (900000, 0), (1200000, 0), (1500000, 0), (1800000, 0);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user