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 70e64e2b5 fix(alert): render a ratio notification value as an exact 
percent (#4292)
70e64e2b5 is described below

commit 70e64e2b5a57544bb67e3ba0f3bf45a67e9f4dc8
Author: btlqql <[email protected]>
AuthorDate: Tue Sep 15 21:07:09 2026 +0800

    fix(alert): render a ratio notification value as an exact percent (#4292)
    
    Scaling the stored fraction with plain double arithmetic turns 0.29 into
    
    28.999999999999996 in the delivered alert body. Scale through BigDecimal
    
    instead so the percent keeps its shortest exact decimal form.
    
    (cherry picked from commit 922ae48d4a971d473793e8d85dd422b647ac78d0)
---
 .../studio/ops/alert/AlertNotificationTemplate.java         | 13 ++++++++++---
 .../studio/ops/alert/AlertNotificationTemplateTest.java     | 13 +++++++++++++
 2 files changed, 23 insertions(+), 3 deletions(-)

diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/ops/alert/AlertNotificationTemplate.java
 
b/server/src/main/java/org/apache/rocketmq/studio/ops/alert/AlertNotificationTemplate.java
index 2930d659f..1c75373cb 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/ops/alert/AlertNotificationTemplate.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/ops/alert/AlertNotificationTemplate.java
@@ -6,6 +6,7 @@
  */
 package org.apache.rocketmq.studio.ops.alert;
 
+import java.math.BigDecimal;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Set;
@@ -59,14 +60,20 @@ final class AlertNotificationTemplate {
     }
 
     private static String formattedValue(SystemAlertVO alert, AlertRuleVO 
rule) {
-        if (alert.getCurrentValue() == null) {
+        Double currentValue = alert.getCurrentValue();
+        if (currentValue == null) {
             return "";
         }
         if (rule != null && "%".equals(rule.getThresholdUnit())
                 && RATIO_METRICS.contains(rule.getMetric() == null ? "" : 
rule.getMetric().trim())) {
-            return String.valueOf(alert.getCurrentValue() * 100);
+            // Ratio metrics are stored as fractions of the whole, so the 
percent rendering scales
+            // them by 100. Scaling through BigDecimal keeps the exact decimal 
form: plain double
+            // arithmetic renders the stored 0.29 as "28.999999999999996".
+            return Double.isFinite(currentValue)
+                    ? 
BigDecimal.valueOf(currentValue).movePointRight(2).stripTrailingZeros().toPlainString()
+                    : String.valueOf(currentValue);
         }
-        return String.valueOf(alert.getCurrentValue());
+        return String.valueOf(currentValue);
     }
 
     private static String formatLabels(Map<String, String> labels) {
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/ops/alert/AlertNotificationTemplateTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/ops/alert/AlertNotificationTemplateTest.java
index ed1a15110..032fe9aad 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/ops/alert/AlertNotificationTemplateTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/ops/alert/AlertNotificationTemplateTest.java
@@ -45,6 +45,19 @@ class AlertNotificationTemplateTest {
         assertThat(rendered).isEqualTo("86.5%");
     }
 
+    @Test
+    void rendersWholePercentForRatioValueWithoutFloatingPointNoiseTest() {
+        AlertRuleVO rule = AlertRuleVO.builder().name("Disk 
threshold").metric("broker.disk.usage_ratio")
+                .threshold(29).thresholdUnit("%").build();
+        SystemAlertVO alert = 
SystemAlertVO.builder().level(AlertLevel.warning).title("Disk threshold")
+                
.description("FIRING").transition("FIRING").instanceId("local").currentValue(0.29)
+                .time(LocalDateTime.of(2026, 8, 23, 12, 
0)).labels(Map.of()).build();
+
+        String rendered = 
AlertNotificationTemplate.render("${value}${thresholdUnit}", alert, rule);
+
+        assertThat(rendered).isEqualTo("29%");
+    }
+
     @Test
     void usesTheExistingNotificationFormatWhenNoTemplateWasConfiguredTest() {
         SystemAlertVO alert = 
SystemAlertVO.builder().level(AlertLevel.info).title("Test")

Reply via email to