unbridled-41 opened a new issue, #5094:
URL: https://github.com/apache/rocketmq-dashboard/issues/5094

   ### Before Creating the Bug Report
   
   - [x] I searched the repository's issues and pull requests 
(`rmq.group.detail` in bodies, `health`, `health UNKNOWN`, `totalLag`, `unknown 
lag healthy`, `group health`) and found no issue for this verdict path. The 
related issues I did find cover other surfaces (see Additional Context).
   - [x] This is a defect in RocketMQ Studio (the `rmq.group.detail` MCP/AI 
tool contract), not a usage question.
   - [x] Reproduced on the development trunk `rocketmq-studio` at `a562601d`; 
the handler file is byte-identical on `master`, so the defect is on both.
   
   ### Studio Version
   
   ```
   branch: rocketmq-studio (development trunk)
   git commit id: a562601d0971001c1cd3b888a9f2664b6ef77811
   also present on: master (git diff origin/master origin/rocketmq-studio -- 
server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/handler/group/GroupDetailToolHandler.java
 is empty)
   deployed as: built from source
   ```
   
   ### Runtime Environment
   
   JDK 21 (`mvn -o test`). The defect is deterministic and needs no broker, 
cluster or MySQL:
   
   ```
   $ mvn -o test -Dtest=ConsumerGroupReadToolHandlersTest
   Tests run: 6, Failures: 0, Errors: 0, Skipped: 0        # with the fix
   ```
   
   ### Connected RocketMQ Cluster
   
   Not required for the reproduction. In production the state is produced by an 
Apache RocketMQ 5.x gRPC consumer, whose queue diffs are the broker's own `-1` 
(see Evidence).
   
   ### Describe the Bug
   
   `rmq.group.detail` grades a consumer group's health from three inputs — 
consume-stat availability, connection availability and the total lag — in 
`GroupDetailToolHandler.health` 
(`server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/handler/group/GroupDetailToolHandler.java:73-95`).
 The ladder enumerates the first two "signal unavailable" cases, then compares 
the lag directly:
   
   ```java
   } else if (group.getOnlineInstances() == 0) {
       status = "WARNING";
       reasons.add("The group has no online consumer.");
   } else if (group.getTotalLag() > 0) {
       status = "WARNING";
       reasons.add("The group has accumulated messages.");
   } else {
       status = "HEALTHY";
   }
   ```
   
   `-1` is the lag-unknown sentinel 
(`provider/apache/ConsumerLagResolver.java:33`, `UNKNOWN = -1`, documented 
there as "matches the broker's own -1 for gRPC"), so it is a *successful* 
comparison against `> 0` and a group whose lag cannot be determined is reported 
as **HEALTHY** — asserting "nothing has accumulated" from data the server 
itself marks undeterminable.
   
   ### Evidence
   
   1. The sentinel reaches the handler with consume stats reported as 
available: `RocketMQMetadataProvider` sets `consumeStatsAvailable = true` once 
`examineConsumeStats` returns and then writes `lagUnknown ? 
ConsumerLagResolver.UNKNOWN : totalLag` when any queue diff is `-1`. Both 
halves of that state are already pinned by existing tests:
      - 
`RocketMQAdminClientImplTest.getConsumerGroupReportsUnknownTotalLagWhenAnyQueueOffsetIsUnknownTest`
 
(`server/src/test/java/org/apache/rocketmq/studio/provider/apache/RocketMQAdminClientImplTest.java:329-345`)
 asserts `isConsumeStatsAvailable()` is `true` and `getTotalLag()` equals 
`ConsumerLagResolver.UNKNOWN`;
      - 
`RocketMQMetadataProviderTest.listConsumerGroupsShouldReportUnknownTotalLagWhenAnyQueueOffsetIsUnknownTest`
 (`…/RocketMQMetadataProviderTest.java:855-882`) asserts the same pair on the 
list path.
   2. The read-side contract already uses that vocabulary: 
`GroupDetailOutput.Progress.from` collapses a queue lag of `-1` into `totalLag 
= -1` (`…/ops/ai/tool/contract/group/GroupDetailOutput.java:156-158`), the 
record documents `-1` for `onlineInstances` as "the connection inventory is 
unavailable", and the tool catalog's schema lists `UNKNOWN` in the 
`health.status` enum 
(`server/src/main/resources/tool-catalog/tools/group.yaml`).
   
   Reproduction with the tool's own test fixture 
(`ConsumerGroupVO{consumeStatsAvailable=true, onlineInstances=1, totalLag=-1}`):
   
   ```
   $ mvn -o test -Dtest=ConsumerGroupReadToolHandlersTest      # fix reverted
   
ConsumerGroupReadToolHandlersTest.detailMarksHealthUnknownWhenTheConsumerLagIsUnavailableTest
   expected: "UNKNOWN"
    but was: "HEALTHY"
   ```
   
   Existing coverage only pins the two other unavailable signals 
(`onlineInstances = -1`, `consumeStatsAvailable = false`); there was no 
`totalLag == -1` case.
   
   ### What Did You Expect to See?
   
   An unresolved lag is reported the way the two other unavailable signals are: 
`status = "UNKNOWN"` with a reason, never a positive verdict derived from it. 
Groups with no online consumer keep their connection-derived `WARNING`, which 
does not depend on the lag.
   
   ### What Did You See Instead?
   
   `{"status":"HEALTHY","reasons":[]}` for a group whose consumption lag the 
provider could not resolve.
   
   ### Additional Context
   
   This is one instance of a class the project has already fixed elsewhere, on 
other surfaces — e.g. #4510 (Tencent zero backlog), #4516 (Apache queue-level 
metrics clamping unknown progress), #4361 (live stats failures rendered as zero 
lag), #4539 (reset-offset preview), #4293/#2500 (unknown lag rendered as a 
value). None of them covers this tool's health ladder.
   
   Consumers of the field: the AI Tool Playground, the hosted agent, and 
external MCP clients, since `health` is part of the frozen output contract.
   
   ### Corresponding pull request
   
   #5091 — `fix(ai): stop grading a group healthy from an unresolved consumer 
lag`
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to