Skip to content

Commit 68ac374

Browse files
authored
feat: add limit to label value api (GreptimeTeam#6795)
* feat: add limit to label value api Signed-off-by: Ning Sun <sunning@greptime.com> * feat: limit for special labels Signed-off-by: Ning Sun <sunning@greptime.com> --------- Signed-off-by: Ning Sun <sunning@greptime.com>
1 parent 4c2955b commit 68ac374

2 files changed

Lines changed: 71 additions & 1 deletion

File tree

src/servers/src/http/prometheus.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,7 @@ pub struct LabelValueQuery {
978978
#[serde(flatten)]
979979
matches: Matches,
980980
db: Option<String>,
981+
limit: Option<usize>,
981982
}
982983

983984
#[axum_macros::debug_handler]
@@ -1025,6 +1026,7 @@ pub async fn label_values_query(
10251026
}
10261027
}
10271028
table_names.sort_unstable();
1029+
truncate_results(&mut table_names, params.limit);
10281030
return PrometheusJsonResponse::success(PrometheusResponse::LabelValues(table_names));
10291031
} else if label_name == FIELD_NAME_LABEL {
10301032
let field_columns = handle_schema_err!(
@@ -1033,12 +1035,14 @@ pub async fn label_values_query(
10331035
.unwrap_or_default();
10341036
let mut field_columns = field_columns.into_iter().collect::<Vec<_>>();
10351037
field_columns.sort_unstable();
1038+
truncate_results(&mut field_columns, params.limit);
10361039
return PrometheusJsonResponse::success(PrometheusResponse::LabelValues(field_columns));
10371040
} else if label_name == SCHEMA_LABEL || label_name == DATABASE_LABEL {
10381041
let catalog_manager = handler.catalog_manager();
10391042

10401043
match retrieve_schema_names(&query_ctx, catalog_manager, params.matches.0).await {
1041-
Ok(schema_names) => {
1044+
Ok(mut schema_names) => {
1045+
truncate_results(&mut schema_names, params.limit);
10421046
return PrometheusJsonResponse::success(PrometheusResponse::LabelValues(
10431047
schema_names,
10441048
));
@@ -1100,9 +1104,19 @@ pub async fn label_values_query(
11001104

11011105
let mut label_values: Vec<_> = label_values.into_iter().collect();
11021106
label_values.sort_unstable();
1107+
truncate_results(&mut label_values, params.limit);
1108+
11031109
PrometheusJsonResponse::success(PrometheusResponse::LabelValues(label_values))
11041110
}
11051111

1112+
fn truncate_results(label_values: &mut Vec<String>, limit: Option<usize>) {
1113+
if let Some(limit) = limit {
1114+
if limit > 0 && label_values.len() >= limit {
1115+
label_values.truncate(limit);
1116+
}
1117+
}
1118+
}
1119+
11061120
/// Take metric name from the [VectorSelector].
11071121
/// It takes the name in the selector or removes the name matcher.
11081122
fn take_metric_name(selector: &mut VectorSelector) -> Option<String> {

tests-integration/tests/http.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,62 @@ pub async fn test_prom_http_api(store_type: StorageType) {
978978
serde_json::from_value::<PrometheusResponse>(json!(["val"])).unwrap()
979979
);
980980

981+
// limit
982+
let res = client
983+
.get("/v1/prometheus/api/v1/label/host/values?match[]=demo&start=0&end=600&limit=1")
984+
.send()
985+
.await;
986+
assert_eq!(res.status(), StatusCode::OK);
987+
let body = serde_json::from_str::<PrometheusJsonResponse>(&res.text().await).unwrap();
988+
assert_eq!(body.status, "success");
989+
assert_eq!(
990+
body.data,
991+
serde_json::from_value::<PrometheusResponse>(json!(["host1"])).unwrap()
992+
);
993+
994+
// limit 0
995+
let res = client
996+
.get("/v1/prometheus/api/v1/label/host/values?match[]=demo&start=0&end=600&limit=0")
997+
.send()
998+
.await;
999+
assert_eq!(res.status(), StatusCode::OK);
1000+
let body = serde_json::from_str::<PrometheusJsonResponse>(&res.text().await).unwrap();
1001+
assert_eq!(body.status, "success");
1002+
assert_eq!(
1003+
body.data,
1004+
serde_json::from_value::<PrometheusResponse>(json!(["host1", "host2"])).unwrap()
1005+
);
1006+
1007+
// limit 10
1008+
let res = client
1009+
.get("/v1/prometheus/api/v1/label/host/values?match[]=demo&start=0&end=600&limit=10")
1010+
.send()
1011+
.await;
1012+
assert_eq!(res.status(), StatusCode::OK);
1013+
let body = serde_json::from_str::<PrometheusJsonResponse>(&res.text().await).unwrap();
1014+
assert_eq!(body.status, "success");
1015+
assert_eq!(
1016+
body.data,
1017+
serde_json::from_value::<PrometheusResponse>(json!(["host1", "host2"])).unwrap()
1018+
);
1019+
1020+
// special labels limit
1021+
let res = client
1022+
.get("/v1/prometheus/api/v1/label/__schema__/values?start=0&end=600&limit=2")
1023+
.send()
1024+
.await;
1025+
assert_eq!(res.status(), StatusCode::OK);
1026+
let body = serde_json::from_str::<PrometheusJsonResponse>(&res.text().await).unwrap();
1027+
assert_eq!(body.status, "success");
1028+
assert_eq!(
1029+
body.data,
1030+
serde_json::from_value::<PrometheusResponse>(json!([
1031+
"greptime_private",
1032+
"information_schema",
1033+
]))
1034+
.unwrap()
1035+
);
1036+
9811037
// query an empty database should return nothing
9821038
let res = client
9831039
.get("/v1/prometheus/api/v1/label/host/values?match[]=demo&start=0&end=600")

0 commit comments

Comments
 (0)