You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ratis.apache.org by sh...@apache.org on 2020/04/15 08:55:24 UTC

[incubator-ratis] branch master updated: RATIS-832. Add Metrics for retry cache count as well as size in bytes. Contributed by runzhiwang.

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

shashikant pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-ratis.git


The following commit(s) were added to refs/heads/master by this push:
     new 1eb0ece  RATIS-832. Add Metrics for retry cache count as well as size in bytes. Contributed by runzhiwang.
1eb0ece is described below

commit 1eb0ece983104afd9375a9d9a24ff3474df485d2
Author: Shashikant Banerjee <sh...@apache.org>
AuthorDate: Wed Apr 15 14:24:25 2020 +0530

    RATIS-832. Add Metrics for retry cache count as well as size in bytes. Contributed by runzhiwang.
---
 .../apache/ratis/server/impl/RaftServerImpl.java   |   1 -
 .../ratis/server/impl/RaftServerMetrics.java       |  20 ++--
 .../org/apache/ratis/server/impl/RetryCache.java   |   8 +-
 .../ratis/server/impl/TestRetryCacheMetrics.java   | 119 +++++++++++++++++++++
 4 files changed, 140 insertions(+), 8 deletions(-)

diff --git a/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java b/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java
index 2574609..8019303 100644
--- a/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java
+++ b/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java
@@ -586,7 +586,6 @@ public class RaftServerImpl implements RaftServerProtocol, RaftServerAsynchronou
         if (previousResult.isRetry()) {
           // if the previous attempt is still pending or it succeeded, return its
           // future
-          raftServerMetrics.onRetryRequestCacheHit();
           replyFuture = previousResult.getEntry().getReplyFuture();
         } else {
           final RetryCache.CacheEntry cacheEntry = previousResult.getEntry();
diff --git a/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerMetrics.java b/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerMetrics.java
index 0135304..898b8a4 100644
--- a/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerMetrics.java
+++ b/ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerMetrics.java
@@ -54,13 +54,16 @@ public final class RaftServerMetrics extends RatisMetrics {
   public static final String RAFT_CLIENT_STALE_READ_REQUEST = "clientStaleReadRequest";
   public static final String RAFT_CLIENT_WRITE_REQUEST = "clientWriteRequest";
   public static final String RAFT_CLIENT_WATCH_REQUEST = "clientWatch%sRequest";
-  public static final String RETRY_REQUEST_CACHE_HIT_COUNTER = "numRetryCacheHits";
   public static final String REQUEST_QUEUE_LIMIT_HIT_COUNTER = "numRequestQueueLimitHits";
   public static final String RESOURCE_LIMIT_HIT_COUNTER = "leaderNumResourceLimitHits";
   public static final String REQUEST_BYTE_SIZE_LIMIT_HIT_COUNTER = "numRequestsByteSizeLimitHits";
   public static final String REQUEST_QUEUE_SIZE = "numPendingRequestInQueue";
   public static final String REQUEST_BYTE_SIZE = "numPendingRequestByteSize";
-
+  public static final String RETRY_CACHE_ENTRY_COUNT_METRIC = "retryCacheEntryCount";
+  public static final String RETRY_CACHE_HIT_COUNT_METRIC = "retryCacheHitCount";
+  public static final String RETRY_CACHE_HIT_RATE_METRIC = "retryCacheHitRate";
+  public static final String RETRY_CACHE_MISS_COUNT_METRIC = "retryCacheMissCount";
+  public static final String RETRY_CACHE_MISS_RATE_METRIC = "retryCacheMissRate";
 
   private Map<String, Long> followerLastHeartbeatElapsedTimeMap = new HashMap<>();
   private CommitInfoCache commitInfoCache;
@@ -78,6 +81,7 @@ public final class RaftServerMetrics extends RatisMetrics {
     registry = getMetricRegistryForRaftServer(server.getMemberId().toString());
     commitInfoCache = server.getCommitInfoCache();
     addPeerCommitIndexGauge(server.getId());
+    addRetryCacheMetric(server);
   }
 
   private RatisMetricRegistry getMetricRegistryForRaftServer(String serverId) {
@@ -86,6 +90,14 @@ public final class RaftServerMetrics extends RatisMetrics {
         RATIS_SERVER_METRICS_DESC));
   }
 
+  private void addRetryCacheMetric(RaftServerImpl raftServer) {
+    registry.gauge(RETRY_CACHE_ENTRY_COUNT_METRIC, () -> () -> raftServer.getRetryCache().size());
+    registry.gauge(RETRY_CACHE_HIT_COUNT_METRIC, () -> () -> raftServer.getRetryCache().stats().hitCount());
+    registry.gauge(RETRY_CACHE_HIT_RATE_METRIC, () -> () -> raftServer.getRetryCache().stats().hitRate());
+    registry.gauge(RETRY_CACHE_MISS_COUNT_METRIC, () -> () -> raftServer.getRetryCache().stats().missCount());
+    registry.gauge(RETRY_CACHE_MISS_RATE_METRIC, () -> () -> raftServer.getRetryCache().stats().missRate());
+  }
+
   /**
    * Register a follower with this Leader Metrics registry instance.
    * @param peer {@Link RaftPeer} representing the follower
@@ -182,10 +194,6 @@ public final class RaftServerMetrics extends RatisMetrics {
     return null;
   }
 
-  public void onRetryRequestCacheHit() {
-    registry.counter(RETRY_REQUEST_CACHE_HIT_COUNTER).inc();
-  }
-
   public void onRequestQueueLimitHit() {
     registry.counter(REQUEST_QUEUE_LIMIT_HIT_COUNTER).inc();
   }
diff --git a/ratis-server/src/main/java/org/apache/ratis/server/impl/RetryCache.java b/ratis-server/src/main/java/org/apache/ratis/server/impl/RetryCache.java
index 47ed3fa..11bb11e 100644
--- a/ratis-server/src/main/java/org/apache/ratis/server/impl/RetryCache.java
+++ b/ratis-server/src/main/java/org/apache/ratis/server/impl/RetryCache.java
@@ -26,6 +26,7 @@ import org.apache.ratis.protocol.RaftClientReply;
 import org.apache.ratis.thirdparty.com.google.common.annotations.VisibleForTesting;
 import org.apache.ratis.thirdparty.com.google.common.cache.Cache;
 import org.apache.ratis.thirdparty.com.google.common.cache.CacheBuilder;
+import org.apache.ratis.thirdparty.com.google.common.cache.CacheStats;
 import org.apache.ratis.util.JavaUtils;
 import org.apache.ratis.util.TimeDuration;
 import org.slf4j.Logger;
@@ -154,6 +155,7 @@ public class RetryCache implements Closeable {
    */
   RetryCache(TimeDuration expirationTime) {
     cache = CacheBuilder.newBuilder()
+        .recordStats()
         .expireAfterWrite(expirationTime.getDuration(), expirationTime.getUnit())
         .build();
   }
@@ -209,10 +211,14 @@ public class RetryCache implements Closeable {
   }
 
   @VisibleForTesting
-  long size() {
+  public long size() {
     return cache.size();
   }
 
+  public CacheStats stats() {
+    return cache.stats();
+  }
+
   @VisibleForTesting
   CacheEntry get(ClientId clientId, long callId) {
     return cache.getIfPresent(new CacheKey(clientId, callId));
diff --git a/ratis-server/src/test/java/org/apache/ratis/server/impl/TestRetryCacheMetrics.java b/ratis-server/src/test/java/org/apache/ratis/server/impl/TestRetryCacheMetrics.java
new file mode 100644
index 0000000..cdde7b6
--- /dev/null
+++ b/ratis-server/src/test/java/org/apache/ratis/server/impl/TestRetryCacheMetrics.java
@@ -0,0 +1,119 @@
+/*
+ * 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.ratis.server.impl;
+
+import static org.apache.ratis.server.impl.RaftServerMetrics.*;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.ratis.metrics.RatisMetricRegistry;
+import org.apache.ratis.protocol.ClientId;
+import org.apache.ratis.protocol.RaftGroupId;
+import org.apache.ratis.protocol.RaftGroupMemberId;
+import org.apache.ratis.protocol.RaftPeerId;
+import org.apache.ratis.util.TimeDuration;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Test for metrics of retry cache.
+ */
+public class TestRetryCacheMetrics {
+    private static RatisMetricRegistry ratisMetricRegistry;
+    private static RetryCache retryCache;
+
+    @BeforeClass
+    public static void setUp() {
+      RaftServerImpl raftServer = mock(RaftServerImpl.class);
+
+      RaftGroupId raftGroupId = RaftGroupId.randomId();
+      RaftPeerId raftPeerId = RaftPeerId.valueOf("TestId");
+      RaftGroupMemberId raftGroupMemberId = RaftGroupMemberId
+          .valueOf(raftPeerId, raftGroupId);
+      when(raftServer.getMemberId()).thenReturn(raftGroupMemberId);
+
+      retryCache = new RetryCache(TimeDuration.valueOf(60, TimeUnit.SECONDS));
+      when(raftServer.getRetryCache()).thenReturn(retryCache);
+
+      RaftServerMetrics raftServerMetrics = RaftServerMetrics
+          .getRaftServerMetrics(raftServer);
+      ratisMetricRegistry = raftServerMetrics.getRegistry();
+    }
+
+    @Test
+    public void testRetryCacheEntryCount() {
+      checkEntryCount(0);
+
+      ClientId clientId = ClientId.randomId();
+      RetryCache.CacheKey key = new RetryCache.CacheKey(clientId, 1);
+      RetryCache.CacheEntry entry = new RetryCache.CacheEntry(key);
+
+      retryCache.refreshEntry(entry);
+      checkEntryCount(1);
+
+      retryCache.close();
+      checkEntryCount(0);
+    }
+
+    @Test
+    public void testRetryCacheHitMissCount() {
+      checkHit(0, 1.0);
+      checkMiss(0, 0.0);
+
+      ClientId clientId = ClientId.randomId();
+      retryCache.getOrCreateEntry(clientId, 2);
+
+      checkHit(0, 0.0);
+      checkMiss(1, 1.0);
+
+      retryCache.getOrCreateEntry(clientId, 2);
+
+      checkHit(1, 0.5);
+      checkMiss(1, 0.5);
+    }
+
+    private static void checkHit(long count, double rate) {
+      Long hitCount = (Long) ratisMetricRegistry.getGauges((s, metric) ->
+          s.contains(RETRY_CACHE_HIT_COUNT_METRIC)).values().iterator().next().getValue();
+      assertEquals(hitCount.longValue(), count);
+
+      Double hitRate = (Double) ratisMetricRegistry.getGauges((s, metric) ->
+          s.contains(RETRY_CACHE_HIT_RATE_METRIC)).values().iterator().next().getValue();
+      assertEquals(hitRate.doubleValue(), rate, 0.0);
+    }
+
+    private static void checkMiss(long count, double rate) {
+      Long missCount = (Long) ratisMetricRegistry.getGauges((s, metric) ->
+          s.contains(RETRY_CACHE_MISS_COUNT_METRIC)).values().iterator().next().getValue();
+      assertEquals(missCount.longValue(), count);
+
+      Double missRate = (Double) ratisMetricRegistry.getGauges((s, metric) ->
+          s.contains(RETRY_CACHE_MISS_RATE_METRIC)).values().iterator().next().getValue();
+      assertEquals(missRate.doubleValue(), rate, 0.0);
+    }
+
+    private static void checkEntryCount(long count) {
+      Long entryCount = (Long) ratisMetricRegistry.getGauges((s, metric) ->
+          s.contains(RETRY_CACHE_ENTRY_COUNT_METRIC)).values().iterator().next().getValue();
+      assertEquals(entryCount.longValue(), count);
+    }
+}