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());
+ }
}