fix: return empty when promql gets non-exist label name (#7899)

* fix: return empty when promql gets non-exist label name

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* fix: fmt

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* chore: minor refactor

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* fix: typo

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

---------

Signed-off-by: shuiyisong <xixing.sys@gmail.com>
This commit is contained in:
shuiyisong
2026-04-02 11:20:45 +08:00
committed by GitHub
parent 3f3407fa24
commit d9736407f2
3 changed files with 30 additions and 4 deletions

View File

@@ -395,7 +395,7 @@ impl SlowQueryTimer {
impl Drop for SlowQueryTimer {
fn drop(&mut self) {
// Calculate the elaspsed duration since the timer is created.
// Calculate the elapsed duration since the timer is created.
let elapsed = self.start.elapsed();
if elapsed > self.threshold {
// Only capture a portion of slow queries based on sample_ratio.

View File

@@ -31,7 +31,7 @@ use snafu::{OptionExt, ResultExt};
use crate::error::{
CatalogSnafu, CollectRecordbatchSnafu, ExecLogicalPlanSnafu,
PrometheusLabelValuesQueryPlanSnafu, PrometheusMetricNamesQueryPlanSnafu, ReadTableSnafu,
Result, TableNotFoundSnafu,
Result, TableNotFoundSnafu, TableSnafu,
};
use crate::instance::Instance;
@@ -120,20 +120,32 @@ impl Instance {
})
.unwrap_or_else(|| ctx.current_schema());
let full_table_name = format_full_table_name(ctx.current_catalog(), &table_schema, &metric);
let table = self
.catalog_manager
.table(ctx.current_catalog(), &table_schema, &metric, Some(ctx))
.await
.context(CatalogSnafu)?
.with_context(|| TableNotFoundSnafu {
table_name: format_full_table_name(ctx.current_catalog(), &table_schema, &metric),
table_name: full_table_name.clone(),
})?;
// Check label column existence before building the query plan so a missing label can be
// reported as `TableColumnNotFound` and handled like Prometheus expects.
if table.schema().column_schema_by_name(&label_name).is_none() {
return table::error::ColumnNotExistsSnafu {
column_name: label_name,
table_name: full_table_name,
}
.fail()
.context(TableSnafu);
}
let dataframe = self
.query_engine
.read_table(table.clone())
.with_context(|_| ReadTableSnafu {
table_name: format_full_table_name(ctx.current_catalog(), &table_schema, &metric),
table_name: full_table_name,
})?;
let scan_plan = dataframe.into_unoptimized_plan();

View File

@@ -1176,6 +1176,20 @@ pub async fn test_prom_http_api(store_type: StorageType) {
.await;
assert_eq!(res.status(), StatusCode::OK);
// query non-exist label in metric table
let res = client
.get("/v1/prometheus/api/v1/label/not_exist_label/values?match[]=demo&start=0&end=600")
.send()
.await;
assert_eq!(res.status(), StatusCode::OK);
let prom_resp = res.json::<PrometheusJsonResponse>().await;
assert_eq!(prom_resp.status, "success");
assert!(prom_resp.error.is_none() && prom_resp.error_type.is_none());
assert_eq!(
prom_resp.data,
serde_json::from_value::<PrometheusResponse>(json!([])).unwrap()
);
// query `__name__` without match[]
// create a physical table and a logical table
let res = client