mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-01-14 09:12:57 +00:00
fix: support __name__ matcher in label values (#5773)
This commit is contained in:
@@ -32,6 +32,7 @@ use datatypes::scalars::ScalarVector;
|
||||
use datatypes::vectors::Float64Vector;
|
||||
use futures::future::join_all;
|
||||
use futures::StreamExt;
|
||||
use itertools::Itertools;
|
||||
use promql_parser::label::{MatchOp, Matcher, Matchers, METRIC_NAME};
|
||||
use promql_parser::parser::value::ValueType;
|
||||
use promql_parser::parser::{
|
||||
@@ -1003,18 +1004,19 @@ pub async fn label_values_query(
|
||||
|
||||
for query in queries {
|
||||
let promql_expr = try_call_return_response!(promql_parser::parser::parse(&query));
|
||||
let PromqlExpr::VectorSelector(VectorSelector { name, matchers, .. }) = promql_expr else {
|
||||
let PromqlExpr::VectorSelector(mut vector_selector) = promql_expr else {
|
||||
return PrometheusJsonResponse::error(
|
||||
StatusCode::InvalidArguments,
|
||||
"expected vector selector",
|
||||
);
|
||||
};
|
||||
let Some(name) = name else {
|
||||
let Some(name) = take_metric_name(&mut vector_selector) else {
|
||||
return PrometheusJsonResponse::error(
|
||||
StatusCode::InvalidArguments,
|
||||
"expected metric name",
|
||||
);
|
||||
};
|
||||
let VectorSelector { matchers, .. } = vector_selector;
|
||||
// Only use and filter matchers.
|
||||
let matchers = matchers.matchers;
|
||||
let result = handler
|
||||
@@ -1048,6 +1050,25 @@ pub async fn label_values_query(
|
||||
PrometheusJsonResponse::success(PrometheusResponse::LabelValues(label_values))
|
||||
}
|
||||
|
||||
/// Take metric name from the [VectorSelector].
|
||||
/// It takes the name in the selector or removes the name matcher.
|
||||
fn take_metric_name(selector: &mut VectorSelector) -> Option<String> {
|
||||
if let Some(name) = selector.name.take() {
|
||||
return Some(name);
|
||||
}
|
||||
|
||||
let (pos, matcher) = selector
|
||||
.matchers
|
||||
.matchers
|
||||
.iter()
|
||||
.find_position(|matcher| matcher.name == "__name__" && matcher.op == MatchOp::Equal)?;
|
||||
let name = matcher.value.clone();
|
||||
// We need to remove the name matcher to avoid using it as a filter in query.
|
||||
selector.matchers.matchers.remove(pos);
|
||||
|
||||
Some(name)
|
||||
}
|
||||
|
||||
async fn retrieve_field_names(
|
||||
query_ctx: &QueryContext,
|
||||
manager: CatalogManagerRef,
|
||||
|
||||
@@ -682,6 +682,19 @@ pub async fn test_prom_http_api(store_type: StorageType) {
|
||||
serde_json::from_value::<PrometheusResponse>(json!(["host1"])).unwrap()
|
||||
);
|
||||
|
||||
// single match[] with __name__
|
||||
let res = client
|
||||
.get("/v1/prometheus/api/v1/label/host/values?match[]={__name__%3D%22demo%22}&start=0&end=300")
|
||||
.send()
|
||||
.await;
|
||||
assert_eq!(res.status(), StatusCode::OK);
|
||||
let body = serde_json::from_str::<PrometheusJsonResponse>(&res.text().await).unwrap();
|
||||
assert_eq!(body.status, "success");
|
||||
assert_eq!(
|
||||
body.data,
|
||||
serde_json::from_value::<PrometheusResponse>(json!(["host1"])).unwrap()
|
||||
);
|
||||
|
||||
// single match[]
|
||||
let res = client
|
||||
.get("/v1/prometheus/api/v1/label/idc/values?match[]=demo_metrics_with_nanos&start=0&end=600")
|
||||
|
||||
Reference in New Issue
Block a user