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

paulo pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git


The following commit(s) were added to refs/heads/trunk by this push:
     new f41b625e48 Expose Metric for Prepared Statement Cache Size (in bytes)
f41b625e48 is described below

commit f41b625e487b2f4d2fe319f6097b1b11e9f00f96
Author: Isaac Reath <[email protected]>
AuthorDate: Fri Feb 23 14:54:30 2024 -0500

    Expose Metric for Prepared Statement Cache Size (in bytes)
    
    Patch by Isaac Reath; Reviewed by Paulo Motta and guo Maxwell for
    CASSANDRA-20864
    
    Closes #4345
---
 CHANGES.txt                                        |  1 +
 .../pages/managing/operating/metrics.adoc          |  2 +
 .../org/apache/cassandra/cql3/QueryProcessor.java  | 11 +++++
 .../org/apache/cassandra/metrics/CQLMetrics.java   |  2 +
 .../apache/cassandra/metrics/CQLMetricsTest.java   | 51 ++++++++++++++++++----
 5 files changed, 59 insertions(+), 8 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index 08ae2c6162..f14cf1e6c1 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 5.1
+ * Expose Metric for Prepared Statement Cache Size (in bytes) (CASSANDRA-20864)
  * Add support for BEGIN TRANSACTION to allow mutations that touch multiple 
partitions (CASSANDRA-20857)
  * AutoRepair: Safeguard Full repair against disk protection(CASSANDRA-20045)
  * BEGIN TRANSACTION crashes if a mutation touches multiple rows 
(CASSANDRA-20844)
diff --git a/doc/modules/cassandra/pages/managing/operating/metrics.adoc 
b/doc/modules/cassandra/pages/managing/operating/metrics.adoc
index 6156682550..2dc6d4fd99 100644
--- a/doc/modules/cassandra/pages/managing/operating/metrics.adoc
+++ b/doc/modules/cassandra/pages/managing/operating/metrics.adoc
@@ -671,6 +671,8 @@ executed.
 
 |PreparedStatementsRatio |Gauge<Double> |Percentage of statements that
 are prepared vs unprepared.
+
+|PreparedStatementsCacheSize | Gauge<Long> | The size of the prepared 
statements cache in bytes.
 |===
 
 [[dropped-metrics]]
diff --git a/src/java/org/apache/cassandra/cql3/QueryProcessor.java 
b/src/java/org/apache/cassandra/cql3/QueryProcessor.java
index 7954a7bfc1..8f22bda5c8 100644
--- a/src/java/org/apache/cassandra/cql3/QueryProcessor.java
+++ b/src/java/org/apache/cassandra/cql3/QueryProcessor.java
@@ -42,6 +42,7 @@ import com.github.benmanes.caffeine.cache.Cache;
 import com.github.benmanes.caffeine.cache.Caffeine;
 import com.github.benmanes.caffeine.cache.RemovalCause;
 import org.antlr.runtime.RecognitionException;
+
 import org.apache.cassandra.concurrent.ImmediateExecutor;
 import org.apache.cassandra.concurrent.ScheduledExecutors;
 import org.apache.cassandra.config.DatabaseDescriptor;
@@ -178,6 +179,16 @@ public class QueryProcessor implements QueryHandler
         return preparedStatements.asMap().size();
     }
 
+    public static long preparedStatementsCacheMemoryUsedBytes()
+    {
+        long preparedStatementsCacheMemoryUsedBytes = 0;
+        for (Map.Entry<MD5Digest, Prepared> entry : 
preparedStatements.asMap().entrySet())
+        {
+            preparedStatementsCacheMemoryUsedBytes += 
getSizeOfPreparedStatementForCache(entry.getKey(), entry.getValue());
+        }
+        return preparedStatementsCacheMemoryUsedBytes;
+    }
+
     // Work around initialization dependency
     private enum InternalStateInstance
     {
diff --git a/src/java/org/apache/cassandra/metrics/CQLMetrics.java 
b/src/java/org/apache/cassandra/metrics/CQLMetrics.java
index edf13dfb4e..ad6c571b78 100644
--- a/src/java/org/apache/cassandra/metrics/CQLMetrics.java
+++ b/src/java/org/apache/cassandra/metrics/CQLMetrics.java
@@ -37,6 +37,7 @@ public class CQLMetrics
 
     public final Gauge<Integer> preparedStatementsCount;
     public final Gauge<Double> preparedStatementsRatio;
+    public final Gauge<Long> preparedStatementsCacheSize;
 
     public CQLMetrics()
     {
@@ -64,5 +65,6 @@ public class CQLMetrics
                 return regularStatementsExecuted.getCount() + 
preparedStatementsExecuted.getCount();
             }
         });
+        preparedStatementsCacheSize = 
Metrics.register(factory.createMetricName("PreparedStatementsCacheSize"), 
QueryProcessor::preparedStatementsCacheMemoryUsedBytes);
     }
 }
diff --git a/test/unit/org/apache/cassandra/metrics/CQLMetricsTest.java 
b/test/unit/org/apache/cassandra/metrics/CQLMetricsTest.java
index 4c447a7012..a1681f169e 100644
--- a/test/unit/org/apache/cassandra/metrics/CQLMetricsTest.java
+++ b/test/unit/org/apache/cassandra/metrics/CQLMetricsTest.java
@@ -31,9 +31,12 @@ import com.datastax.driver.core.Session;
 import com.datastax.driver.core.exceptions.InvalidQueryException;
 import org.apache.cassandra.ServerTestUtils;
 import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.cql3.QueryHandler;
 import org.apache.cassandra.cql3.QueryProcessor;
 import org.apache.cassandra.exceptions.ConfigurationException;
+import org.apache.cassandra.service.ClientState;
 import org.apache.cassandra.service.EmbeddedCassandraService;
+import org.apache.cassandra.utils.MD5Digest;
 
 import static org.apache.cassandra.cql3.CQLTester.assertRowsContains;
 import static org.apache.cassandra.cql3.CQLTester.row;
@@ -95,18 +98,50 @@ public class CQLMetricsTest
     }
 
     @Test
-    public void testPreparedStatementsCount()
+    public void testPreparedStatementsCountWithUse()
+    {
+        int n = QueryProcessor.metrics.preparedStatementsCount.getValue();
+        // Use local test session to avoid interference with other tests due 
to CASSANDRA-17248
+        try (Session localSession = cluster.connect())
+        {
+            long useCountBefore = 
QueryProcessor.metrics.useStatementsExecuted.getCount();
+            localSession.execute("use junit");
+            Assert.assertEquals(useCountBefore + 1, 
QueryProcessor.metrics.useStatementsExecuted.getCount());
+            localSession.prepare("SELECT * FROM junit.metricstest WHERE id = 
?");
+            assertEquals(n + 2, (int) 
QueryProcessor.metrics.preparedStatementsCount.getValue());
+
+            assertRowsContains(cluster, session.execute("SELECT * FROM 
system_metrics.cql_group"),
+                               
row("org.apache.cassandra.metrics.CQL.PreparedStatementsCount", 
METRIC_SCOPE_UNDEFINED, "gauge",
+                                   
String.valueOf(QueryProcessor.metrics.preparedStatementsCount.getValue())));
+        }
+    }
+
+    @Test
+    public void testPreparedStatementsCountWithoutUse()
     {
         int n = QueryProcessor.metrics.preparedStatementsCount.getValue();
         long useCountBefore = 
QueryProcessor.metrics.useStatementsExecuted.getCount();
-        session.execute("use junit");
-        Assert.assertEquals(useCountBefore + 1, 
QueryProcessor.metrics.useStatementsExecuted.getCount());
-        session.prepare("SELECT * FROM junit.metricstest WHERE id = ?");
-        assertEquals(n+2, (int) 
QueryProcessor.metrics.preparedStatementsCount.getValue());
+        session.prepare("SELECT * FROM junit.metricstest WHERE id = 101");
+        Assert.assertEquals(useCountBefore, 
QueryProcessor.metrics.useStatementsExecuted.getCount());
+        assertEquals(n+1, (int) 
QueryProcessor.metrics.preparedStatementsCount.getValue());
+    }
 
-        assertRowsContains(cluster, session.execute("SELECT * FROM 
system_metrics.cql_group"),
-                
row("org.apache.cassandra.metrics.CQL.PreparedStatementsCount", 
METRIC_SCOPE_UNDEFINED, "gauge",
-                        
String.valueOf(QueryProcessor.metrics.preparedStatementsCount.getValue())));
+    @Test
+    public void testPreparedStatementCacheMemoryUsed()
+    {
+        long n = QueryProcessor.metrics.preparedStatementsCacheSize.getValue();
+        String rawQueryString = "SELECT id, val FROM junit.metricstest WHERE 
id = 100";
+        PreparedStatement s = session.prepare(rawQueryString);
+
+        // Compute the expected size of a prepared statement.
+        QueryHandler.Prepared expected = 
QueryProcessor.parseAndPrepare(rawQueryString, ClientState.forInternalCalls(), 
false);
+        MD5Digest hashValue = MD5Digest.compute(rawQueryString);
+        long expectedHashSize = hashValue.size();
+        long expectedStatementSize = expected.pstmntSize;
+        long expectedSize = expectedHashSize + expectedStatementSize;
+
+        long actualSize = 
QueryProcessor.metrics.preparedStatementsCacheSize.getValue() - n;
+        assertEquals(expectedSize, actualSize);
     }
 
     @Test


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to