unbridled-41 opened a new pull request, #4748:
URL: https://github.com/apache/rocketmq-dashboard/pull/4748

   Fixes #4747.
   
   ## Problem
   
   One enabled alert rule stored without a metric makes the alert 
reconciliation pass throw, so every active alert of that instance and domain 
stays active forever — no `RESOLVED` state, no `RESOLVED` event, no recovery 
notification.
   
   - `ops/alert/NativeAlertProcessor.java:113-116` filtered the domain's rules 
with 
`scope.metricKeys().contains(StringUtils.trimWhitespace(rule.getMetric()))`.
   - `MetricCollectionScope` holds its keys as `Set.copyOf(...)` 
(`cluster/metrics/MetricCollectionScope.java:31`); every `Set.of`/`Set.copyOf` 
implementation rejects a null lookup (`Set12.contains` dereferences the 
argument, `SetN.contains` calls `Objects.requireNonNull`), and 
`StringUtils.trimWhitespace(null)` is null.
   - A metric-less rule is storable: `AlertRuleRequestDTO.metric` 
(`ops/alert/AlertRuleRequestDTO.java:34`) has no `@NotBlank`, the column is 
nullable (`db/schema.sql:274`), and the JSON import path tolerates it 
explicitly (`AlertRuleTransferService.java:33-46`, 
`NativeAlertMetricCatalogService.java:70-73`, reachable from 
`AlertRuleController.java:85-86`).
   - The failure is swallowed: `CollectorScheduler.java:282-284` / `:298-300` 
catch `RuntimeException` and log a warning, so the reconcile pass for the whole 
scope is skipped.
   
   ## Root cause
   
   A null-unsafe membership test over an immutable set, in a filter that runs 
before any metric-less rule is discarded — so the rule is not skipped, it 
aborts the pass.
   
   ## Fix
   
   `NativeAlertProcessor` normalises the rule's metric to `""` when it is 
absent, so the membership test answers `false` and the rule is filtered out 
while the rest of the scope is still reconciled (`normalizedMetric`, 13 lines 
including the comment). A rule without a metric can never match a collected 
sample, so it has no active state that the pass could resolve; the semantics of 
every other rule in the scope are unchanged.
   
   ## Tests
   
   Red before the fix:
   
   ```
   [ERROR] 
NativeAlertProcessorTest.reconcilesRemainingRulesWhenAnotherRuleHasNoMetricTest 
-- Time elapsed: 0.016 s <<< FAILURE!
     "java.lang.NullPointerException: Cannot invoke "Object.equals(Object)" 
because "o" is null
   [ERROR] Tests run: 24, Failures: 1, Errors: 0, Skipped: 0
   ```
   
   Commands and results after the fix, run from `server/`:
   
   - `mvn -B -ntp -o test -Dtest=NativeAlertProcessorTest` → **24 passed**, 
`BUILD SUCCESS`.
   - `mvn -B -ntp -o test 
-Dtest='org.apache.rocketmq.studio.ops.alert.**,CollectorSchedulerTest'` → 
**318 tests, 0 failures, 5 errors**; all 5 errors are the sandbox's missing 
MySQL (`CannotGetJdbcConnectionException: Communications link failure`, from 
`NativeAlertEvaluationTransactionTest`, 
`NotificationOutboxMapperIntegrationTest`, 
`RmqAlertStateMapperIntegrationTest`), the same baseline failure this 
environment produces on the clean trunk.
   
   ## Duplicate check
   
   Searched open PRs (205) and issues (214) for `reconcile`, `null metric`, 
`without a metric`, `resolve`, `alert state`, plus the commit index: the 
adjacent open items are #4571 (the AI rule-list tool tolerating a metric-less 
rule) and #4711 (rejecting a metric-less rule *test run*) — same input class, 
two other surfaces, neither touching 
`NativeAlertProcessor.reconcileMissingActiveStates`. No open item covers this 
crash site. #4647/#4648 touch a different unguarded parse in the same scheduler.
   
   ## Base branch
   
   Targets the development trunk `rocketmq-studio`. GitHub interprets closing 
keywords only for pull requests that target the repository default branch, and 
that is still `master`, so merging will not close #4747 automatically — it 
needs to be closed by hand.
   
   ## Risk
   
   Low and narrow: the filter now skips a rule that previously made the pass 
abort before doing anything. No behaviour is removed for rules that carry a 
metric, and the change cannot turn a resolvable alert into an unresolvable one.
   


-- 
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