This is an automated email from the ASF dual-hosted git repository.

sivabalan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hudi.git


The following commit(s) were added to refs/heads/master by this push:
     new e063493337e5 feat(metrics): emit metric for rollback failures (#18148)
e063493337e5 is described below

commit e063493337e50968e32cfffb78fa7bae728003d7
Author: Nada <[email protected]>
AuthorDate: Fri Feb 27 18:14:35 2026 -0500

    feat(metrics): emit metric for rollback failures (#18148)
---
 .../hudi/client/BaseHoodieTableServiceClient.java  |  1 +
 .../org/apache/hudi/metrics/HoodieMetrics.java     | 15 +++++++++
 .../org/apache/hudi/metrics/TestHoodieMetrics.java | 36 ++++++++++++++++++++++
 3 files changed, 52 insertions(+)

diff --git 
a/hudi-client/hudi-client-common/src/main/java/org/apache/hudi/client/BaseHoodieTableServiceClient.java
 
b/hudi-client/hudi-client-common/src/main/java/org/apache/hudi/client/BaseHoodieTableServiceClient.java
index cb1777ad2adf..4e08e9fa6824 100644
--- 
a/hudi-client/hudi-client-common/src/main/java/org/apache/hudi/client/BaseHoodieTableServiceClient.java
+++ 
b/hudi-client/hudi-client-common/src/main/java/org/apache/hudi/client/BaseHoodieTableServiceClient.java
@@ -1207,6 +1207,7 @@ public abstract class BaseHoodieTableServiceClient<I, T, 
O> extends BaseHoodieCl
         throw new HoodieRollbackException("Failed to rollback " + 
config.getBasePath() + " commits " + commitInstantTime);
       }
     } catch (Exception e) {
+      metrics.emitRollbackFailure(e.getClass().getSimpleName());
       throw new HoodieRollbackException("Failed to rollback " + 
config.getBasePath() + " commits " + commitInstantTime, e);
     }
   }
diff --git 
a/hudi-client/hudi-client-common/src/main/java/org/apache/hudi/metrics/HoodieMetrics.java
 
b/hudi-client/hudi-client-common/src/main/java/org/apache/hudi/metrics/HoodieMetrics.java
index c94087b1b149..3fa85d5c7878 100644
--- 
a/hudi-client/hudi-client-common/src/main/java/org/apache/hudi/metrics/HoodieMetrics.java
+++ 
b/hudi-client/hudi-client-common/src/main/java/org/apache/hudi/metrics/HoodieMetrics.java
@@ -118,6 +118,7 @@ public class HoodieMetrics {
   private String conflictResolutionFailureCounterName = null;
   private String compactionRequestedCounterName = null;
   private String compactionCompletedCounterName = null;
+  private String rollbackFailureCounterName = null;
   private final HoodieWriteConfig config;
   private final String tableName;
   private Timer rollbackTimer = null;
@@ -136,6 +137,7 @@ public class HoodieMetrics {
   private Counter conflictResolutionFailureCounter = null;
   private Counter compactionRequestedCounter = null;
   private Counter compactionCompletedCounter = null;
+  private Counter rollbackFailureCounter = null;
 
   public HoodieMetrics(HoodieWriteConfig config, HoodieStorage storage) {
     this.config = config;
@@ -158,6 +160,7 @@ public class HoodieMetrics {
       this.conflictResolutionFailureCounterName = 
getMetricsName(CONFLICT_RESOLUTION_STR, FAILURE_COUNTER);
       this.compactionRequestedCounterName = 
getMetricsName(HoodieTimeline.COMPACTION_ACTION, 
HoodieTimeline.REQUESTED_COMPACTION_SUFFIX + COUNTER_METRIC_EXTENSION);
       this.compactionCompletedCounterName = 
getMetricsName(HoodieTimeline.COMPACTION_ACTION, 
HoodieTimeline.COMPLETED_COMPACTION_SUFFIX + COUNTER_METRIC_EXTENSION);
+      this.rollbackFailureCounterName = getMetricsName("rollback", 
FAILURE_COUNTER);
     }
   }
 
@@ -362,6 +365,18 @@ public class HoodieMetrics {
     }
   }
 
+  public void emitRollbackFailure(String exceptionType) {
+    if (config.isMetricsOn()) {
+      rollbackFailureCounter = getCounter(rollbackFailureCounter, 
rollbackFailureCounterName);
+      rollbackFailureCounter.inc();
+      if (exceptionType != null) {
+        String exceptionCounterName = getMetricsName("rollback", exceptionType 
+ COUNTER_METRIC_EXTENSION);
+        Counter exceptionCounter = 
metrics.getRegistry().counter(exceptionCounterName);
+        exceptionCounter.inc();
+      }
+    }
+  }
+  
   public void updateArchivalMetrics(Map<String, Long> archivalMetrics) {
     if (config.isMetricsOn()) {
       log.info(String.format("Sending archival metrics %s", archivalMetrics));
diff --git 
a/hudi-client/hudi-client-common/src/test/java/org/apache/hudi/metrics/TestHoodieMetrics.java
 
b/hudi-client/hudi-client-common/src/test/java/org/apache/hudi/metrics/TestHoodieMetrics.java
index 304ed1f12dd9..f28f80672e1b 100755
--- 
a/hudi-client/hudi-client-common/src/test/java/org/apache/hudi/metrics/TestHoodieMetrics.java
+++ 
b/hudi-client/hudi-client-common/src/test/java/org/apache/hudi/metrics/TestHoodieMetrics.java
@@ -44,6 +44,8 @@ import java.util.UUID;
 import java.util.stream.Stream;
 
 import static 
org.apache.hudi.common.testutils.HoodieTestUtils.INSTANT_GENERATOR;
+import static org.apache.hudi.metrics.HoodieMetrics.COUNTER_METRIC_EXTENSION;
+import static org.apache.hudi.metrics.HoodieMetrics.FAILURE_COUNTER;
 import static 
org.apache.hudi.metrics.HoodieMetrics.SOURCE_READ_AND_INDEX_ACTION;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -318,4 +320,38 @@ public class TestHoodieMetrics {
       this.setInstants(Arrays.asList(instants));
     }
   }
+
+  @Test
+  public void testRollbackFailureMetric() {
+    // Test that rollback failure metric is emitted correctly
+    String exceptionType = "FileNotFoundException";
+    hoodieMetrics.emitRollbackFailure(exceptionType);
+
+    // Verify the failure counter is incremented
+    String metricName = hoodieMetrics.getMetricsName("rollback", 
FAILURE_COUNTER);
+    assertEquals(1, 
metrics.getRegistry().getCounters().get(metricName).getCount());
+
+    // Verify a specific counter is incremented for this exception type
+    String exceptionMetricName = hoodieMetrics.getMetricsName("rollback", 
exceptionType + COUNTER_METRIC_EXTENSION);
+    assertEquals(1, 
metrics.getRegistry().getCounters().get(exceptionMetricName).getCount());
+
+    // Emit another failure and verify counter increments
+    hoodieMetrics.emitRollbackFailure(exceptionType);
+    assertEquals(2, 
metrics.getRegistry().getCounters().get(metricName).getCount());
+    assertEquals(2, 
metrics.getRegistry().getCounters().get(exceptionMetricName).getCount());
+
+    // Test with a different exception type
+    String differentExceptionType = "IOException";
+    hoodieMetrics.emitRollbackFailure(differentExceptionType);
+
+    // Verify the overall failure counter is incremented
+    assertEquals(3, 
metrics.getRegistry().getCounters().get(metricName).getCount());
+
+    // Verify a separate counter is incremented for this new exception type
+    String differentExceptionMetricName = 
hoodieMetrics.getMetricsName("rollback", differentExceptionType + 
COUNTER_METRIC_EXTENSION);
+    assertEquals(1, 
metrics.getRegistry().getCounters().get(differentExceptionMetricName).getCount());
+
+    // Verify the original exception type counter is unchanged
+    assertEquals(2, 
metrics.getRegistry().getCounters().get(exceptionMetricName).getCount());
+  }
 }

Reply via email to