This is an automated email from the ASF dual-hosted git repository.
lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git
The following commit(s) were added to refs/heads/rocketmq-studio by this push:
new 22bf3a300 fix(ai): stop grading a group healthy from an unresolved
consumer lag (#5091)
22bf3a300 is described below
commit 22bf3a3009cb408f01f866cb77c11fc68d1b5e34
Author: 烤化の初雪 <[email protected]>
AuthorDate: Thu Oct 1 17:28:38 2026 +0800
fix(ai): stop grading a group healthy from an unresolved consumer lag
(#5091)
rmq.group.detail's health ladder enumerated two "signal unavailable" inputs
(consume statistics missing, connection inventory missing) and then tested
only
`totalLag > 0`. The lag-unknown sentinel is -1 (ConsumerLagResolver.UNKNOWN,
what the provider writes when any queue diff is the broker's own -1 for gRPC
consumers), so a group with online consumers and an unresolved lag fell
through
to the final `else` and was reported as HEALTHY, i.e. "nothing accumulated"
was
asserted from data the server itself marks undeterminable.
Test the sentinel before the lag-derived branches and answer UNKNOWN with a
reason, the way the two other unavailable signals already do. The
connection-derived verdicts stay as they were: a group with no online
consumer
is still WARNING, because that verdict does not depend on the lag.
Co-authored-by: unbridled-41 <[email protected]>
---
.../tool/handler/group/GroupDetailToolHandler.java | 5 ++++
.../group/ConsumerGroupReadToolHandlersTest.java | 34 ++++++++++++++++++++++
2 files changed, 39 insertions(+)
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/handler/group/GroupDetailToolHandler.java
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/handler/group/GroupDetailToolHandler.java
index 4a5ac0542..26a062a3a 100644
---
a/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/handler/group/GroupDetailToolHandler.java
+++
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/handler/group/GroupDetailToolHandler.java
@@ -85,6 +85,11 @@ public class GroupDetailToolHandler implements
ToolHandler<GroupDetailInput, Gro
} else if (group.getOnlineInstances() == 0) {
status = "WARNING";
reasons.add("The group has no online consumer.");
+ } else if (group.getTotalLag() < 0) {
+ // The -1 sentinel means the lag could not be resolved (a queue
whose diff is unknown),
+ // so no verdict may be derived from it, not even the "nothing
accumulated" one.
+ status = "UNKNOWN";
+ reasons.add("Consumer lag information is unavailable.");
} else if (group.getTotalLag() > 0) {
status = "WARNING";
reasons.add("The group has accumulated messages.");
diff --git
a/server/src/test/java/org/apache/rocketmq/studio/ops/ai/tool/handler/group/ConsumerGroupReadToolHandlersTest.java
b/server/src/test/java/org/apache/rocketmq/studio/ops/ai/tool/handler/group/ConsumerGroupReadToolHandlersTest.java
index 000b1be5a..82f2e06ea 100644
---
a/server/src/test/java/org/apache/rocketmq/studio/ops/ai/tool/handler/group/ConsumerGroupReadToolHandlersTest.java
+++
b/server/src/test/java/org/apache/rocketmq/studio/ops/ai/tool/handler/group/ConsumerGroupReadToolHandlersTest.java
@@ -27,6 +27,7 @@ import
org.apache.rocketmq.studio.instance.topic.MetadataService;
import org.apache.rocketmq.studio.ops.ai.tool.contract.group.GroupDetailInput;
import org.apache.rocketmq.studio.ops.ai.tool.contract.group.GroupDetailOutput;
import org.apache.rocketmq.studio.ops.ai.tool.core.ToolExecutionContext;
+import org.apache.rocketmq.studio.provider.apache.ConsumerLagResolver;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -172,6 +173,39 @@ class ConsumerGroupReadToolHandlersTest {
assertThat(output.onlineInstances()).isEqualTo(-1);
}
+ @Test
+ void detailMarksHealthUnknownWhenTheConsumerLagIsUnavailableTest() {
+ group.setOnlineInstances(1);
+ group.setTotalLag(ConsumerLagResolver.UNKNOWN);
+ when(metadataService.consumerGroupRuntimeView("instance-a",
"group-a")).thenReturn(group);
+ when(metadataService.consumerGroupConfigurations("instance-a",
"group-a")).thenReturn(List.of(group));
+ when(metadataService.getGroupSubscriptions("instance-a",
"group-a")).thenReturn(List.of());
+ when(metadataService.getGroupProgress("instance-a",
"group-a")).thenReturn(List.of());
+
+ GroupDetailOutput output = new GroupDetailToolHandler(metadataService)
+ .execute(new GroupDetailInput("instance-a", "group-a", null),
context());
+
+ assertThat(output.health().status()).isEqualTo("UNKNOWN");
+ assertThat(output.health().reasons()).contains("Consumer lag
information is unavailable.");
+ assertThat(output.totalLag()).isEqualTo(ConsumerLagResolver.UNKNOWN);
+ }
+
+ @Test
+ void detailKeepsTheConnectionWarningWhenTheConsumerLagIsUnavailableTest() {
+ group.setOnlineInstances(0);
+ group.setTotalLag(ConsumerLagResolver.UNKNOWN);
+ when(metadataService.consumerGroupRuntimeView("instance-a",
"group-a")).thenReturn(group);
+ when(metadataService.consumerGroupConfigurations("instance-a",
"group-a")).thenReturn(List.of(group));
+ when(metadataService.getGroupSubscriptions("instance-a",
"group-a")).thenReturn(List.of());
+ when(metadataService.getGroupProgress("instance-a",
"group-a")).thenReturn(List.of());
+
+ GroupDetailOutput output = new GroupDetailToolHandler(metadataService)
+ .execute(new GroupDetailInput("instance-a", "group-a", null),
context());
+
+ assertThat(output.health().status()).isEqualTo("WARNING");
+ assertThat(output.health().reasons()).contains("The group has no
online consumer.");
+ }
+
@Test
void detailWithoutOnlineConsumersKeepsProgressAndClientsEmpty() {
ConsumerGroupVO offline = new ConsumerGroupVO();