Skip to content

Commit 9b474f9

Browse files
authored
NIFI-14770: Allowing the user to reset all counters in a single action. (apache#10115)
* NIFI-14770: Allowing the user to reset all counters in a single action. * NIFI-14770: Fixing checkstyle issues. * NIFI-14770: Addressing review feedback. This closes apache#10115
1 parent a2ff519 commit 9b474f9

23 files changed

Lines changed: 1501 additions & 321 deletions

File tree

nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/repository/StandardCounterRepository.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,16 @@ public Counter resetCounter(final String identifier) {
106106
}
107107
return null;
108108
}
109+
110+
@Override
111+
public List<Counter> resetAllCounters() {
112+
final List<Counter> resetCounters = new ArrayList<>();
113+
for (final ConcurrentMap<String, Counter> counters : processorCounters.values()) {
114+
for (final Counter counter : counters.values()) {
115+
counter.reset();
116+
resetCounters.add(StandardCounter.unmodifiableCounter(counter));
117+
}
118+
}
119+
return resetCounters;
120+
}
109121
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.nifi.controller.repository;
18+
19+
import org.apache.nifi.controller.Counter;
20+
import org.junit.jupiter.api.BeforeEach;
21+
import org.junit.jupiter.api.Test;
22+
23+
import java.util.List;
24+
25+
import static org.junit.jupiter.api.Assertions.assertEquals;
26+
import static org.junit.jupiter.api.Assertions.assertNotNull;
27+
import static org.junit.jupiter.api.Assertions.assertTrue;
28+
29+
public class StandardCounterRepositoryTest {
30+
31+
private StandardCounterRepository repository;
32+
33+
@BeforeEach
34+
public void setUp() {
35+
repository = new StandardCounterRepository();
36+
}
37+
38+
@Test
39+
public void testResetAllCountersWithEmptyRepository() {
40+
final List<Counter> resetCounters = repository.resetAllCounters();
41+
assertNotNull(resetCounters);
42+
assertTrue(resetCounters.isEmpty());
43+
}
44+
45+
@Test
46+
public void testResetAllCountersWithSingleCounter() {
47+
// Create a counter and adjust its value
48+
repository.adjustCounter("context1", "counter1", 10);
49+
50+
// Verify the counter has the expected value
51+
final Counter counter = repository.getCounter("context1", "counter1");
52+
assertEquals(10, counter.getValue());
53+
54+
// Reset all counters
55+
final List<Counter> resetCounters = repository.resetAllCounters();
56+
57+
// Verify the result
58+
assertNotNull(resetCounters);
59+
assertEquals(1, resetCounters.size());
60+
assertEquals(0, resetCounters.get(0).getValue());
61+
assertEquals("counter1", resetCounters.get(0).getName());
62+
assertEquals("context1", resetCounters.get(0).getContext());
63+
64+
// Verify the original counter is also reset
65+
assertEquals(0, repository.getCounter("context1", "counter1").getValue());
66+
}
67+
68+
@Test
69+
public void testResetAllCountersWithMultipleCountersAndContexts() {
70+
// Create counters in different contexts with different values
71+
repository.adjustCounter("context1", "counter1", 15);
72+
repository.adjustCounter("context1", "counter2", 25);
73+
repository.adjustCounter("context2", "counter1", 35);
74+
repository.adjustCounter("context2", "counter3", 45);
75+
76+
// Verify initial values
77+
assertEquals(15, repository.getCounter("context1", "counter1").getValue());
78+
assertEquals(25, repository.getCounter("context1", "counter2").getValue());
79+
assertEquals(35, repository.getCounter("context2", "counter1").getValue());
80+
assertEquals(45, repository.getCounter("context2", "counter3").getValue());
81+
82+
// Reset all counters
83+
final List<Counter> resetCounters = repository.resetAllCounters();
84+
85+
// Verify the result
86+
assertNotNull(resetCounters);
87+
assertEquals(4, resetCounters.size());
88+
89+
// All reset counters should have value 0
90+
for (final Counter counter : resetCounters) {
91+
assertEquals(0, counter.getValue());
92+
}
93+
94+
// Verify all original counters are reset
95+
assertEquals(0, repository.getCounter("context1", "counter1").getValue());
96+
assertEquals(0, repository.getCounter("context1", "counter2").getValue());
97+
assertEquals(0, repository.getCounter("context2", "counter1").getValue());
98+
assertEquals(0, repository.getCounter("context2", "counter3").getValue());
99+
}
100+
101+
@Test
102+
public void testResetAllCountersIsAtomic() {
103+
// Create multiple counters
104+
repository.adjustCounter("context1", "counter1", 100);
105+
repository.adjustCounter("context1", "counter2", 200);
106+
repository.adjustCounter("context2", "counter1", 300);
107+
108+
// Reset all counters should return all counters with value 0
109+
final List<Counter> resetCounters = repository.resetAllCounters();
110+
111+
assertEquals(3, resetCounters.size());
112+
113+
// Verify all returned counters are reset
114+
long totalValue = resetCounters.stream().mapToLong(Counter::getValue).sum();
115+
assertEquals(0, totalValue);
116+
}
117+
118+
@Test
119+
public void testResetAllCountersAfterIndividualReset() {
120+
// Create counters
121+
repository.adjustCounter("context1", "counter1", 50);
122+
repository.adjustCounter("context1", "counter2", 75);
123+
124+
// Reset one counter individually
125+
final Counter counter1 = repository.getCounter("context1", "counter1");
126+
repository.resetCounter(counter1.getIdentifier());
127+
128+
// Verify individual reset worked
129+
assertEquals(0, repository.getCounter("context1", "counter1").getValue());
130+
assertEquals(75, repository.getCounter("context1", "counter2").getValue());
131+
132+
// Reset all counters
133+
final List<Counter> resetCounters = repository.resetAllCounters();
134+
135+
// Should still return all counters (including already reset ones)
136+
assertEquals(2, resetCounters.size());
137+
for (final Counter counter : resetCounters) {
138+
assertEquals(0, counter.getValue());
139+
}
140+
}
141+
142+
@Test
143+
public void testResetAllCountersReturnsUnmodifiableCounters() {
144+
// Create a counter
145+
repository.adjustCounter("context1", "counter1", 42);
146+
147+
// Reset all counters
148+
final List<Counter> resetCounters = repository.resetAllCounters();
149+
150+
assertNotNull(resetCounters);
151+
assertEquals(1, resetCounters.size());
152+
153+
final Counter returnedCounter = resetCounters.get(0);
154+
assertEquals(0, returnedCounter.getValue());
155+
156+
// The returned counter should be unmodifiable (this is implementation specific)
157+
// We can verify the type or behavior if needed, but the main contract is that it reflects the reset state
158+
assertEquals("counter1", returnedCounter.getName());
159+
assertEquals("context1", returnedCounter.getContext());
160+
}
161+
}

nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/repository/CounterRepository.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,6 @@ public interface CounterRepository {
3131
List<Counter> getCounters(String counterContext);
3232

3333
Counter resetCounter(String identifier);
34+
35+
List<Counter> resetAllCounters();
3436
}

nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2418,6 +2418,11 @@ public Counter resetCounter(final String identifier) {
24182418
return resetValue;
24192419
}
24202420

2421+
public List<Counter> resetAllCounters() {
2422+
final CounterRepository counterRepo = counterRepositoryRef.get();
2423+
return counterRepo.resetAllCounters();
2424+
}
2425+
24212426
public class GroupStatusCounts {
24222427
private int queuedCount = 0;
24232428
private long queuedContentSize = 0;

nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,13 @@ public interface NiFiServiceFacade {
446446
*/
447447
CounterDTO updateCounter(String counterId);
448448

449+
/**
450+
* Updates all counters by setting their values to 0.
451+
*
452+
* @return The counters
453+
*/
454+
CountersDTO updateAllCounters();
455+
449456
/**
450457
* Returns the counters.
451458
*

0 commit comments

Comments
 (0)