From 48e7280fba96c950b2595b14d4b66ad9966081ba Mon Sep 17 00:00:00 2001 From: liuhy Date: Fri, 24 Jul 2026 09:18:35 -0700 Subject: [PATCH] Validate Prometheus source queries --- .../metrics/PrometheusMetricsSource.java | 12 ++++ .../metrics/PrometheusMetricsSourceTest.java | 64 +++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/server/src/main/java/com/rocketmq/studio/cluster/metrics/PrometheusMetricsSource.java b/server/src/main/java/com/rocketmq/studio/cluster/metrics/PrometheusMetricsSource.java index 701bab1a..de208331 100644 --- a/server/src/main/java/com/rocketmq/studio/cluster/metrics/PrometheusMetricsSource.java +++ b/server/src/main/java/com/rocketmq/studio/cluster/metrics/PrometheusMetricsSource.java @@ -108,10 +108,22 @@ private void validateQuery(MetricQueryDTO query) { if (query == null) { throw new PrometheusException(HttpStatus.BAD_REQUEST.value(), "Metric query is required"); } + if (!StringUtils.hasText(query.getMetric())) { + throw new PrometheusException(HttpStatus.BAD_REQUEST.value(), "Metric query is required"); + } + if (query.getStart() <= 0) { + throw new PrometheusException(HttpStatus.BAD_REQUEST.value(), "Metric query start must be positive"); + } + if (query.getEnd() <= 0) { + throw new PrometheusException(HttpStatus.BAD_REQUEST.value(), "Metric query end must be positive"); + } if (query.getEnd() < query.getStart()) { throw new PrometheusException(HttpStatus.BAD_REQUEST.value(), "Metric query end must not be earlier than start"); } + if (!StringUtils.hasText(query.getStep())) { + throw new PrometheusException(HttpStatus.BAD_REQUEST.value(), "Metric query step is required"); + } } private URI queryRangeUri() { diff --git a/server/src/test/java/com/rocketmq/studio/cluster/metrics/PrometheusMetricsSourceTest.java b/server/src/test/java/com/rocketmq/studio/cluster/metrics/PrometheusMetricsSourceTest.java index 3d2fbb26..905d6887 100644 --- a/server/src/test/java/com/rocketmq/studio/cluster/metrics/PrometheusMetricsSourceTest.java +++ b/server/src/test/java/com/rocketmq/studio/cluster/metrics/PrometheusMetricsSourceTest.java @@ -244,6 +244,70 @@ void queryShouldRejectEndEarlierThanStart() { .hasMessage("Metric query end must not be earlier than start"); } + @Test + void queryShouldRejectBlankMetric() { + MetricQueryDTO invalidQuery = MetricQueryDTO.builder() + .metric(" ") + .start(1L) + .end(2L) + .step("30s") + .build(); + + assertThatThrownBy(() -> source(Duration.ofSeconds(2)).query(invalidQuery)) + .isInstanceOf(PrometheusException.class) + .satisfies(exception -> assertThat(((PrometheusException) exception).getStatusCode()) + .isEqualTo(HttpStatus.BAD_REQUEST.value())) + .hasMessage("Metric query is required"); + } + + @Test + void queryShouldRejectNonPositiveStart() { + MetricQueryDTO invalidQuery = MetricQueryDTO.builder() + .metric("up") + .start(0L) + .end(2L) + .step("30s") + .build(); + + assertThatThrownBy(() -> source(Duration.ofSeconds(2)).query(invalidQuery)) + .isInstanceOf(PrometheusException.class) + .satisfies(exception -> assertThat(((PrometheusException) exception).getStatusCode()) + .isEqualTo(HttpStatus.BAD_REQUEST.value())) + .hasMessage("Metric query start must be positive"); + } + + @Test + void queryShouldRejectNonPositiveEnd() { + MetricQueryDTO invalidQuery = MetricQueryDTO.builder() + .metric("up") + .start(1L) + .end(0L) + .step("30s") + .build(); + + assertThatThrownBy(() -> source(Duration.ofSeconds(2)).query(invalidQuery)) + .isInstanceOf(PrometheusException.class) + .satisfies(exception -> assertThat(((PrometheusException) exception).getStatusCode()) + .isEqualTo(HttpStatus.BAD_REQUEST.value())) + .hasMessage("Metric query end must be positive"); + } + + @Test + void queryShouldRejectBlankStep() { + MetricQueryDTO invalidQuery = MetricQueryDTO.builder() + .metric("up") + .start(1L) + .end(2L) + .step(" ") + .build(); + + assertThatThrownBy(() -> source(Duration.ofSeconds(2)).query(invalidQuery)) + .isInstanceOf(PrometheusException.class) + .satisfies(exception -> assertThat(((PrometheusException) exception).getStatusCode()) + .isEqualTo(HttpStatus.BAD_REQUEST.value())) + .hasMessage("Metric query step is required"); + } + @Test void queryShouldFailLoudWhenPrometheusIsNotConfigured() { PrometheusProperties properties = new PrometheusProperties();