Skip to content

Commit

Permalink
fix: do not support v1/label/<label_name>/values
Browse files Browse the repository at this point in the history
This patch fix v1/label/<label_name>/values returns InvalidArguments
close issue GreptimeTeam#5217 by using the same logic as prometheus api.

Signed-off-by: yihong0618 <[email protected]>
  • Loading branch information
yihong0618 committed Jan 3, 2025
1 parent 4d6fe31 commit 504265f
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 18 deletions.
57 changes: 49 additions & 8 deletions src/servers/src/http/prometheus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -719,22 +719,63 @@ pub async fn label_values_query(
}

let queries = params.matches.0;
if queries.is_empty() {
return PrometheusJsonResponse::error(
StatusCode::InvalidArguments,
"match[] parameter is required",
);
}

let start = params.start.unwrap_or_else(yesterday_rfc3339);
let end = params.end.unwrap_or_else(current_time_rfc3339);
let lookback = params
.lookback
.unwrap_or_else(|| DEFAULT_LOOKBACK_STRING.to_string());

let mut label_values = HashSet::new();
// If no match[] is specified, collect label values from all tables.
if queries.is_empty() {
let mut label_values = HashSet::new();
let mut merge_map = HashMap::new();
let table_names = match handler
.catalog_manager()
.table_names(&catalog, &schema, Some(&query_ctx))
.await
{
Ok(tables) => tables,
Err(e) => return PrometheusJsonResponse::error(e.status_code(), e.output_msg()),
};

for table_name in table_names {
let prom_query = PromQuery {
query: table_name,
start: start.clone(),
end: end.clone(),
step: DEFAULT_LOOKBACK_STRING.to_string(),
lookback: lookback.clone(),
};
let result = handler.do_query(&prom_query, query_ctx.clone()).await;
if let Err(err) =
retrieve_label_values(result, &label_name, &mut label_values, &mut merge_map).await
{
// skip non-existent tables, columns, or time index errors
if err.status_code() != StatusCode::TableNotFound
&& err.status_code() != StatusCode::TableColumnNotFound
&& err.status_code() != StatusCode::InvalidArguments
{
return PrometheusJsonResponse::error(err.status_code(), err.output_msg());
}
}
}

let merge_map = merge_map
.into_iter()
.map(|(k, v)| (k, Value::from(v)))
.collect();
let mut label_values: Vec<_> = label_values.into_iter().collect();
label_values.sort_unstable();

let mut resp =
PrometheusJsonResponse::success(PrometheusResponse::LabelValues(label_values));
resp.resp_metrics = merge_map;
return resp;
}

let mut label_values = HashSet::new();
let mut merge_map = HashMap::new();

for query in queries {
let prom_query = PromQuery {
query,
Expand Down
18 changes: 8 additions & 10 deletions tests-integration/tests/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -573,20 +573,18 @@ pub async fn test_prom_http_api(store_type: StorageType) {
.is_some_and(|err| err.eq_ignore_ascii_case("Table not found: greptime.public.up")));

// label values
// should return error if there is no match[]
// fetch all values for label `instance`
let res = client
.get("/v1/prometheus/api/v1/label/instance/values")
.send()
.await;
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
let prom_resp = res.json::<PrometheusJsonResponse>().await;
assert_eq!(prom_resp.status, "error");
assert!(prom_resp
.error
.is_some_and(|err| err.eq_ignore_ascii_case("match[] parameter is required")));
assert!(prom_resp
.error_type
.is_some_and(|err| err.eq_ignore_ascii_case("InvalidArguments")));
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", "host2"])).unwrap()
);

// single match[]
let res = client
Expand Down

0 comments on commit 504265f

Please sign in to comment.