This is an automated email from the ASF dual-hosted git repository.
albumenj pushed a commit to branch 3.1
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/3.1 by this push:
new 64c928a8c5 metrics series 1 : add TimeWindowCounter (#10493)
64c928a8c5 is described below
commit 64c928a8c50028aba59ddf9d9e77067dcd4d6c14
Author: Hui Yao <[email protected]>
AuthorDate: Wed Aug 24 10:10:31 2022 +0800
metrics series 1 : add TimeWindowCounter (#10493)
---
.../dubbo/metrics/aggregate/TimeWindowCounter.java | 90 ++++++++++++++++++++++
.../metrics/aggregate/TimeWindowCounterTest.java | 37 +++++++++
2 files changed, 127 insertions(+)
diff --git
a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/TimeWindowCounter.java
b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/TimeWindowCounter.java
new file mode 100644
index 0000000000..3dc3666602
--- /dev/null
+++
b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/TimeWindowCounter.java
@@ -0,0 +1,90 @@
+/*
+ * 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.dubbo.metrics.aggregate;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Wrapper around Counter like Long and Integer.
+ * <p>
+ * Maintains a ring buffer of Counter to provide count over a sliding windows
of time.
+ */
+public class TimeWindowCounter {
+ private final Long[] ringBuffer;
+ private final Long[] bucketStartTimeMillis;
+ private int currentBucket;
+ private long lastRotateTimestampMillis;
+ private final long durationBetweenRotatesMillis;
+
+ public TimeWindowCounter(int bucketNum, int timeWindowSeconds) {
+ this.ringBuffer = new Long[bucketNum];
+ this.bucketStartTimeMillis = new Long[bucketNum];
+ for (int i = 0; i < bucketNum; i++) {
+ this.ringBuffer[i] = 0L;
+ this.bucketStartTimeMillis[i] = System.currentTimeMillis();
+ }
+
+ this.currentBucket = 0;
+ this.lastRotateTimestampMillis = System.currentTimeMillis();
+ this.durationBetweenRotatesMillis =
TimeUnit.SECONDS.toMillis(timeWindowSeconds) / bucketNum;
+ }
+
+ public synchronized double get() {
+ return rotate();
+ }
+
+ public long bucketLivedSeconds() {
+ return TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() -
bucketStartTimeMillis[currentBucket]);
+ }
+
+ public synchronized void increment() {
+ this.increment(1L);
+ }
+
+ public synchronized void increment(Long step) {
+ rotate();
+ for (int i = 0; i < ringBuffer.length; i++) {
+ ringBuffer[i] = ringBuffer[i] + step;
+ }
+ }
+
+ public synchronized void decrement() {
+ this.decrement(1L);
+ }
+
+ public synchronized void decrement(Long step) {
+ rotate();
+ for (int i = 0; i < ringBuffer.length; i++) {
+ ringBuffer[i] = ringBuffer[i] - step;
+ }
+ }
+
+ private Long rotate() {
+ long timeSinceLastRotateMillis = System.currentTimeMillis() -
lastRotateTimestampMillis;
+ while (timeSinceLastRotateMillis > durationBetweenRotatesMillis) {
+ ringBuffer[currentBucket] = 0L;
+ bucketStartTimeMillis[currentBucket] = lastRotateTimestampMillis +
durationBetweenRotatesMillis;
+ if (++currentBucket >= ringBuffer.length) {
+ currentBucket = 0;
+ }
+ timeSinceLastRotateMillis -= durationBetweenRotatesMillis;
+ lastRotateTimestampMillis += durationBetweenRotatesMillis;
+ }
+ return ringBuffer[currentBucket];
+ }
+}
diff --git
a/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/aggregate/TimeWindowCounterTest.java
b/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/aggregate/TimeWindowCounterTest.java
new file mode 100644
index 0000000000..0b49925126
--- /dev/null
+++
b/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/aggregate/TimeWindowCounterTest.java
@@ -0,0 +1,37 @@
+/*
+ * 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.dubbo.metrics.aggregate;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TimeWindowCounterTest {
+
+ @Test
+ public void test() throws Exception {
+ TimeWindowCounter counter = new TimeWindowCounter(12, 1);
+ counter.increment();
+ Assertions.assertEquals(counter.get(), 1);
+ counter.decrement();
+ Assertions.assertEquals(counter.get(), 0);
+ counter.increment();
+ Thread.sleep(1000);
+ Assertions.assertEquals(counter.get(), 0);
+ Assertions.assertTrue(counter.bucketLivedSeconds() < 1);
+ }
+}