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

markap14 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new 65658fa40a NIFI-15076 Fix potential ArithmeticException in Status 
Value Reducer (#10404)
65658fa40a is described below

commit 65658fa40a3d2ee913320f711ab92d24927d71a6
Author: David Handermann <[email protected]>
AuthorDate: Wed Oct 8 14:45:49 2025 -0500

    NIFI-15076 Fix potential ArithmeticException in Status Value Reducer 
(#10404)
    
    * NIFI-15076 Fixed potential ArithmeticException in Status Value Reducer
---
 .../status/history/ProcessorStatusDescriptor.java  |  5 +-
 .../history/ProcessorStatusDescriptorTest.java     | 75 ++++++++++++++++++++++
 2 files changed, 79 insertions(+), 1 deletion(-)

diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-framework-status-history-shared/src/main/java/org/apache/nifi/controller/status/history/ProcessorStatusDescriptor.java
 
b/nifi-framework-bundle/nifi-framework/nifi-framework-status-history-shared/src/main/java/org/apache/nifi/controller/status/history/ProcessorStatusDescriptor.java
index e701b2be2f..6462ef7d38 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-framework-status-history-shared/src/main/java/org/apache/nifi/controller/status/history/ProcessorStatusDescriptor.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-framework-status-history-shared/src/main/java/org/apache/nifi/controller/status/history/ProcessorStatusDescriptor.java
@@ -323,7 +323,10 @@ public enum ProcessorStatusDescriptor {
                 }
 
                 final long procMillis = 
TimeUnit.MILLISECONDS.convert(procNanos, TimeUnit.NANOSECONDS);
-                return metricMillis * 100 / procMillis;
+                // Convert processing milliseconds to 1 if nanoseconds is 0 to 
avoid ArithmeticException
+                final long convertedProcessingMilliseconds = procMillis == 0 ? 
1 : procMillis;
+
+                return metricMillis * 100 / convertedProcessingMilliseconds;
             }
         };
     }
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-framework-status-history-shared/src/test/java/org/apache/nifi/controller/status/history/ProcessorStatusDescriptorTest.java
 
b/nifi-framework-bundle/nifi-framework/nifi-framework-status-history-shared/src/test/java/org/apache/nifi/controller/status/history/ProcessorStatusDescriptorTest.java
new file mode 100644
index 0000000000..0033b075ea
--- /dev/null
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-framework-status-history-shared/src/test/java/org/apache/nifi/controller/status/history/ProcessorStatusDescriptorTest.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.controller.status.history;
+
+import org.apache.nifi.controller.status.ProcessorStatus;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class ProcessorStatusDescriptorTest {
+
+    private static final long ZERO = 0;
+
+    private static final long FIVE_HUNDRED_NANOSECONDS = 500;
+
+    private static final long METRIC_MILLISECONDS = 10;
+
+    private static final long MINIMUM_METRIC_PERCENTAGE_EXPECTED = 1000;
+
+    private static final ProcessorStatusDescriptor PERCENTAGE_DESCRIPTOR = 
ProcessorStatusDescriptor.CPU_PERCENTAGE;
+
+    private static final ProcessorStatusDescriptor METRIC_DESCRIPTOR = 
ProcessorStatusDescriptor.CPU_MILLIS;
+
+    @Test
+    void testPercentageValueReducerTaskNanosZero() {
+        final MetricDescriptor<ProcessorStatus> descriptor = 
PERCENTAGE_DESCRIPTOR.getDescriptor();
+        final ValueReducer<StatusSnapshot, Long> valueReducer = 
descriptor.getValueReducer();
+
+        final StatusSnapshot statusSnapshot = getStatusSnapshot(ZERO);
+        final List<StatusSnapshot> snapshots = List.of(statusSnapshot);
+
+        final Long reduced = valueReducer.reduce(snapshots);
+
+        assertEquals(ZERO, reduced);
+    }
+
+    @Test
+    void testPercentageValueReducerTaskNanosFiveHundred() {
+        final MetricDescriptor<ProcessorStatus> descriptor = 
PERCENTAGE_DESCRIPTOR.getDescriptor();
+        final ValueReducer<StatusSnapshot, Long> valueReducer = 
descriptor.getValueReducer();
+
+        final StatusSnapshot statusSnapshot = 
getStatusSnapshot(FIVE_HUNDRED_NANOSECONDS);
+        final List<StatusSnapshot> snapshots = List.of(statusSnapshot);
+
+        final Long reduced = valueReducer.reduce(snapshots);
+
+        assertEquals(MINIMUM_METRIC_PERCENTAGE_EXPECTED, reduced);
+    }
+
+    private StatusSnapshot getStatusSnapshot(final long taskNanoseconds) {
+        final StatusSnapshot statusSnapshot = mock(StatusSnapshot.class);
+        
when(statusSnapshot.getStatusMetric(eq(METRIC_DESCRIPTOR.getDescriptor()))).thenReturn(METRIC_MILLISECONDS);
+        
when(statusSnapshot.getStatusMetric(eq(ProcessorStatusDescriptor.TASK_NANOS.getDescriptor()))).thenReturn(taskNanoseconds);
+        return statusSnapshot;
+    }
+}

Reply via email to