This is an automated email from the ASF dual-hosted git repository.
ycai 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 945a4fc Add a virtual table for exposing prepared statements metrics
945a4fc is described below
commit 945a4fc23ac1f60b8380be3b60aef89caf3daba2
Author: Shailaja Koppu <[email protected]>
AuthorDate: Tue Feb 1 09:53:49 2022 -0800
Add a virtual table for exposing prepared statements metrics
patch by Shailaja Koppu; reviewed by Ekaterina Dimitrova, Francisco
Guerrero, Yifan Cai for CASSANDRA-17224
---
CHANGES.txt | 1 +
doc/modules/cassandra/pages/new/virtualtables.adoc | 18 +++
.../cassandra/db/virtual/CQLMetricsTable.java | 81 +++++++++++++
.../cassandra/db/virtual/SystemViewsKeyspace.java | 1 +
.../cassandra/db/virtual/CQLMetricsTableTest.java | 126 +++++++++++++++++++++
5 files changed, 227 insertions(+)
diff --git a/CHANGES.txt b/CHANGES.txt
index 03a97fa..fe3fb22 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
4.1
+ * Add a virtual table for exposing prepared statements metrics
(CASSANDRA-17224)
* Remove python 2.x support from cqlsh (CASSANDRA-17242)
* Prewarm role and credential caches to avoid timeouts at startup
(CASSANDRA-16958)
* Make capacity/validity/updateinterval/activeupdate for Auth Caches
configurable via nodetool (CASSANDRA-17063)
diff --git a/doc/modules/cassandra/pages/new/virtualtables.adoc
b/doc/modules/cassandra/pages/new/virtualtables.adoc
index b18ba31..914bc27 100644
--- a/doc/modules/cassandra/pages/new/virtualtables.adoc
+++ b/doc/modules/cassandra/pages/new/virtualtables.adoc
@@ -74,6 +74,8 @@ recent_hit_rate_per_second, recent_request_rate_per_second,
request_count, and s
|coordinator_write_latency |Records counts, keyspace_name, table_name, max,
median, and per_second for coordinator writes.
+|cql_metrcs |Metrics specific to CQL prepared statement caching.
+
|disk_usage |Records disk usage including disk_space, keyspace_name, and
table_name, sorted by system keyspaces.
|internode_inbound |Lists information about the inbound internode messaging.
@@ -99,6 +101,7 @@ recent_hit_rate_per_second, recent_request_rate_per_second,
request_count, and s
|thread_pools |Lists metrics for each thread pool.
|tombstones_per_read |Records counts, keyspace_name, tablek_name, max, and
median for tombstones.
+
|===
We shall discuss some of the virtual tables in more detail next.
@@ -170,6 +173,21 @@ counters | 26214400 | 0 | 0 |
NaN |
(4 rows)
....
+=== CQL metrics Virtual Table
+The `cql_metrics` virtual table lists metrics specific to CQL prepared
statement caching. A query on `cql_metrics` virtual table lists below metrics.
+
+....
+cqlsh> select * from system_views.cql_metrics ;
+
+ name | value
+------------------------------+-------
+ prepared_statements_count | 0
+ prepared_statements_evicted | 0
+ prepared_statements_executed | 0
+ prepared_statements_ratio | 0
+ regular_statements_executed | 17
+....
+
=== Settings Virtual Table
The `settings` table is rather useful and lists all the current
diff --git a/src/java/org/apache/cassandra/db/virtual/CQLMetricsTable.java
b/src/java/org/apache/cassandra/db/virtual/CQLMetricsTable.java
new file mode 100644
index 0000000..acd8947
--- /dev/null
+++ b/src/java/org/apache/cassandra/db/virtual/CQLMetricsTable.java
@@ -0,0 +1,81 @@
+/*
+ * 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.cassandra.db.virtual;
+
+import com.google.common.annotations.VisibleForTesting;
+
+import org.apache.cassandra.db.marshal.DoubleType;
+import org.apache.cassandra.db.marshal.UTF8Type;
+import org.apache.cassandra.dht.LocalPartitioner;
+import org.apache.cassandra.metrics.CQLMetrics;
+import org.apache.cassandra.schema.TableMetadata;
+import org.apache.cassandra.cql3.QueryProcessor;
+
+
+final class CQLMetricsTable extends AbstractVirtualTable
+{
+ public static final String TABLE_NAME = "cql_metrics";
+ public static final String PREPARED_STATEMENTS_COUNT =
"prepared_statements_count";
+ public static final String PREPARED_STATEMENTS_EVICTED =
"prepared_statements_evicted";
+ public static final String PREPARED_STATEMENTS_EXECUTED =
"prepared_statements_executed";
+ public static final String PREPARED_STATEMENTS_RATIO =
"prepared_statements_ratio";
+ public static final String REGULAR_STATEMENTS_EXECUTED =
"regular_statements_executed";
+ public static final String NAME_COL = "name";
+ public static final String VALUE_COL = "value";
+
+ private final CQLMetrics cqlMetrics;
+
+ CQLMetricsTable(String keyspace)
+ {
+ this(keyspace, QueryProcessor.metrics);
+ }
+
+ // For dependency injection
+ @VisibleForTesting
+ CQLMetricsTable(String keyspace, CQLMetrics cqlMetrics)
+ {
+ super(TableMetadata.builder(keyspace, TABLE_NAME)
+ .comment("Metrics specific to CQL prepared
statement caching")
+ .kind(TableMetadata.Kind.VIRTUAL)
+ .partitioner(new
LocalPartitioner(UTF8Type.instance))
+ .addPartitionKeyColumn(NAME_COL, UTF8Type.instance)
+ .addRegularColumn(VALUE_COL, DoubleType.instance)
+ .build());
+ this.cqlMetrics = cqlMetrics;
+ }
+
+ @Override
+ public DataSet data()
+ {
+ SimpleDataSet result = new SimpleDataSet(metadata());
+ addRow(result, PREPARED_STATEMENTS_COUNT,
cqlMetrics.preparedStatementsCount.getValue());
+ addRow(result, PREPARED_STATEMENTS_EVICTED,
cqlMetrics.preparedStatementsEvicted.getCount());
+ addRow(result, PREPARED_STATEMENTS_EXECUTED,
cqlMetrics.preparedStatementsExecuted.getCount());
+ addRow(result, PREPARED_STATEMENTS_RATIO,
cqlMetrics.preparedStatementsRatio.getValue());
+ addRow(result, REGULAR_STATEMENTS_EXECUTED,
cqlMetrics.regularStatementsExecuted.getCount());
+
+ return result;
+ }
+
+ private void addRow(SimpleDataSet dataSet, String name, double value)
+ {
+ dataSet.row(name)
+ .column(VALUE_COL, value);
+ }
+}
diff --git a/src/java/org/apache/cassandra/db/virtual/SystemViewsKeyspace.java
b/src/java/org/apache/cassandra/db/virtual/SystemViewsKeyspace.java
index 6dfd8a9..6d5582e 100644
--- a/src/java/org/apache/cassandra/db/virtual/SystemViewsKeyspace.java
+++ b/src/java/org/apache/cassandra/db/virtual/SystemViewsKeyspace.java
@@ -43,6 +43,7 @@ public final class SystemViewsKeyspace extends VirtualKeyspace
.add(new NetworkPermissionsCacheKeysTable(VIRTUAL_VIEWS))
.add(new PermissionsCacheKeysTable(VIRTUAL_VIEWS))
.add(new RolesCacheKeysTable(VIRTUAL_VIEWS))
+ .add(new CQLMetricsTable(VIRTUAL_VIEWS))
.build());
}
}
diff --git a/test/unit/org/apache/cassandra/db/virtual/CQLMetricsTableTest.java
b/test/unit/org/apache/cassandra/db/virtual/CQLMetricsTableTest.java
new file mode 100644
index 0000000..658b841
--- /dev/null
+++ b/test/unit/org/apache/cassandra/db/virtual/CQLMetricsTableTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.cassandra.db.virtual;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import com.google.common.collect.ImmutableList;
+
+import com.datastax.driver.core.PreparedStatement;
+import com.datastax.driver.core.ResultSet;
+import com.datastax.driver.core.Session;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.junit.BeforeClass;
+
+import org.apache.cassandra.cql3.CQLTester;
+import org.apache.cassandra.cql3.QueryProcessor;
+import org.apache.cassandra.metrics.CQLMetrics;
+
+public class CQLMetricsTableTest extends CQLTester
+{
+ private static final String KS_NAME = "vts";
+
+ @BeforeClass
+ public static void setUpClass()
+ {
+ CQLTester.setUpClass();
+ }
+
+ private void queryAndValidateMetrics(CQLMetrics expectedMetrics) throws
Throwable
+ {
+ String getMetricsQuery = "SELECT * FROM " + KS_NAME + "." +
CQLMetricsTable.TABLE_NAME;
+ ResultSet vtsRows = executeNet(getMetricsQuery);
+
+ assertEquals(2, vtsRows.getColumnDefinitions().size());
+
+ AtomicInteger rowCount = new AtomicInteger(0);
+ vtsRows.forEach(r -> {
+ final double metricValue = r.getDouble(CQLMetricsTable.VALUE_COL);
+ switch (r.getString(CQLMetricsTable.NAME_COL))
+ {
+ case CQLMetricsTable.PREPARED_STATEMENTS_COUNT:
+
assertEquals(expectedMetrics.preparedStatementsCount.getValue(), metricValue,
0);
+ break;
+ case CQLMetricsTable.PREPARED_STATEMENTS_EVICTED:
+
assertEquals(expectedMetrics.preparedStatementsEvicted.getCount(), metricValue,
0);
+ break;
+ case CQLMetricsTable.PREPARED_STATEMENTS_EXECUTED:
+
assertEquals(expectedMetrics.preparedStatementsExecuted.getCount(),
metricValue, 0);
+ break;
+ case CQLMetricsTable.PREPARED_STATEMENTS_RATIO:
+
assertEquals(expectedMetrics.preparedStatementsRatio.getValue(), metricValue,
0.01);
+ break;
+ case CQLMetricsTable.REGULAR_STATEMENTS_EXECUTED:
+
assertEquals(expectedMetrics.regularStatementsExecuted.getCount(), metricValue,
0);
+ break;
+ }
+ rowCount.getAndIncrement();
+ });
+
+ assertEquals(5, rowCount.get());
+ }
+
+ @Test
+ public void testUsingPrepareStmts() throws Throwable
+ {
+ CQLMetricsTable table = new CQLMetricsTable(KS_NAME);
+ VirtualKeyspaceRegistry.instance.register(new VirtualKeyspace(KS_NAME,
ImmutableList.of(table)));
+
+ String ks = createKeyspace("CREATE KEYSPACE %s WITH replication={
'class' : 'SimpleStrategy', 'replication_factor' : 1 }");
+ String tbl = createTable(ks, "CREATE TABLE %s (id int PRIMARY KEY, cid
int, val text)");
+ Session session = sessionNet();
+
+ String insertCQL = "INSERT INTO " + ks + "." + tbl + " (id, cid, val)
VALUES (?, ?, ?)";
+ PreparedStatement preparedInsert = session.prepare(insertCQL);
+
+ String selectCQL = "Select * from " + ks + "." + tbl + " where id = ?";
+ PreparedStatement preparedSelect = session.prepare(selectCQL);
+
+ for (int i = 0; i < 10; i++)
+ {
+ session.execute(preparedInsert.bind(i, i, "value" + i));
+ session.execute(preparedSelect.bind(i));
+ }
+
+ queryAndValidateMetrics(QueryProcessor.metrics);
+ }
+
+ @Test
+ public void testUsingInjectedValues() throws Throwable
+ {
+ CQLMetrics cqlMetrics = new CQLMetrics();
+ CQLMetricsTable table = new CQLMetricsTable(KS_NAME, cqlMetrics);
+ VirtualKeyspaceRegistry.instance.register(new VirtualKeyspace(KS_NAME,
ImmutableList.of(table)));
+
+ // With initial injected values
+ cqlMetrics.preparedStatementsExecuted.inc(50);
+ cqlMetrics.regularStatementsExecuted.inc(100);
+ cqlMetrics.preparedStatementsEvicted.inc(25);
+ queryAndValidateMetrics(cqlMetrics);
+
+ // Test again with updated values
+ cqlMetrics.preparedStatementsExecuted.inc(150);
+ cqlMetrics.regularStatementsExecuted.inc(200);
+ cqlMetrics.preparedStatementsEvicted.inc(50);
+ queryAndValidateMetrics(cqlMetrics);
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]