Skip to content

Commit d54536b

Browse files
CNDB-15920: Add cassandra.sai.metrics.table_state.enabled flag to be able to enable/disable TableStateMetrics
1 parent e4d83f5 commit d54536b

File tree

4 files changed

+82
-12
lines changed

4 files changed

+82
-12
lines changed

src/java/org/apache/cassandra/config/CassandraRelevantProperties.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,12 @@ public enum CassandraRelevantProperties
635635
*/
636636
SAI_INDEX_METRICS_ENABLED("cassandra.sai.metrics.index.enabled", "true"),
637637

638+
/**
639+
* Whether to enable SAI table state metrics such as disk usage, queryable index count, and index build progress.
640+
* These metrics include gauges for table-level SAI state information.
641+
*/
642+
SAI_TABLE_STATE_METRICS_ENABLED("cassandra.sai.metrics.table_state.enabled", "true"),
643+
638644
/**
639645
* If true, while creating or altering schema, NetworkTopologyStrategy won't check if the DC exists.
640646
* This is to remain compatible with older workflows that first change the replication before adding the nodes.

src/java/org/apache/cassandra/index/sai/StorageAttachedIndexGroup.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@
7474
import org.apache.cassandra.utils.Throwables;
7575
import org.apache.lucene.index.CorruptIndexException;
7676

77+
import static org.apache.cassandra.config.CassandraRelevantProperties.SAI_TABLE_STATE_METRICS_ENABLED;
78+
7779
/**
7880
* Orchestrates building of storage-attached indices, and manages lifecycle of resources shared between them.
7981
*/
@@ -85,7 +87,8 @@ public class StorageAttachedIndexGroup implements Index.Group, INotificationCons
8587
public static final Index.Group.Key GROUP_KEY = new Index.Group.Key(StorageAttachedIndexGroup.class);
8688

8789
private final TableQueryMetrics queryMetrics;
88-
private final TableStateMetrics stateMetrics;
90+
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
91+
private final Optional<TableStateMetrics> stateMetrics;
8992
private final IndexGroupMetrics groupMetrics;
9093

9194
private final Set<StorageAttachedIndex> indices = ConcurrentHashMap.newKeySet();
@@ -100,7 +103,9 @@ public class StorageAttachedIndexGroup implements Index.Group, INotificationCons
100103
{
101104
this.baseCfs = baseCfs;
102105
this.queryMetrics = new TableQueryMetrics(baseCfs.metadata());
103-
this.stateMetrics = new TableStateMetrics(baseCfs.metadata(), this);
106+
this.stateMetrics = SAI_TABLE_STATE_METRICS_ENABLED.getBoolean()
107+
? Optional.of(new TableStateMetrics(baseCfs.metadata(), this))
108+
: Optional.empty();
104109
this.groupMetrics = new IndexGroupMetrics(baseCfs.metadata(), this);
105110
this.contextManager = new SSTableContextManager(baseCfs.getTracker());
106111
this.version = Version.current(baseCfs.keyspace.getName());
@@ -164,7 +169,7 @@ public void invalidate()
164169
// in case of removing last index from group, sstable contexts should already been removed by StorageAttachedIndexGroup#removeIndex
165170
queryMetrics.release();
166171
groupMetrics.release();
167-
stateMetrics.release();
172+
stateMetrics.ifPresent(TableStateMetrics::release);
168173
baseCfs.getTracker().unsubscribe(this);
169174
}
170175

@@ -176,7 +181,7 @@ public void unload()
176181
contextManager.clear();
177182
queryMetrics.release();
178183
groupMetrics.release();
179-
stateMetrics.release();
184+
stateMetrics.ifPresent(TableStateMetrics::release);
180185
}
181186

182187
@Override
@@ -473,6 +478,12 @@ public TableQueryMetrics queryMetrics()
473478
return queryMetrics;
474479
}
475480

481+
// Needed by CNDB
482+
public Optional<TableStateMetrics> stateMetrics()
483+
{
484+
return stateMetrics;
485+
}
486+
476487
public ColumnFamilyStore table()
477488
{
478489
return baseCfs;

src/java/org/apache/cassandra/index/sai/metrics/TableStateMetrics.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ public class TableStateMetrics extends AbstractMetrics
2828
{
2929
public static final String TABLE_STATE_METRIC_TYPE = "TableStateMetrics";
3030

31-
private final Gauge diskUsageBytes;
31+
// Visible for CNDB
32+
public final Gauge diskUsageBytes;
3233
private final Gauge diskUsagePercentageOfBaseTable;
3334
private final Gauge totalIndexCount;
3435
private final Gauge totalIndexBuildsInProgress;

test/unit/org/apache/cassandra/index/sai/metrics/StateMetricsTest.java

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import com.datastax.driver.core.ResultSet;
2727

28+
import static org.apache.cassandra.config.CassandraRelevantProperties.SAI_TABLE_STATE_METRICS_ENABLED;
2829
import static org.apache.cassandra.index.sai.metrics.TableStateMetrics.TABLE_STATE_METRIC_TYPE;
2930
import static org.assertj.core.api.Assertions.assertThatThrownBy;
3031
import static org.junit.Assert.assertEquals;
@@ -49,9 +50,9 @@ public void testMetricRelease()
4950
createTable(String.format(CREATE_TABLE_TEMPLATE, keyspace, table));
5051
createIndex(String.format(CREATE_INDEX_TEMPLATE, index, keyspace, table, "v1"));
5152

52-
execute("INSERT INTO " + keyspace + "." + table + " (id1, v1, v2) VALUES ('0', 0, '0')");
53+
execute("INSERT INTO " + keyspace + '.' + table + " (id1, v1, v2) VALUES ('0', 0, '0')");
5354

54-
ResultSet rows = executeNet("SELECT id1 FROM " + keyspace + "." + table + " WHERE v1 = 0");
55+
ResultSet rows = executeNet("SELECT id1 FROM " + keyspace + '.' + table + " WHERE v1 = 0");
5556
assertEquals(1, rows.all().size());
5657
assertEquals(1L, getTableStateMetrics(keyspace, table, "TotalIndexCount"));
5758

@@ -75,14 +76,14 @@ public void testMetricCreation()
7576
createIndex(String.format(CREATE_INDEX_TEMPLATE, index+"_v1", keyspace, table, "v1"));
7677
createIndex(String.format(CREATE_INDEX_TEMPLATE, index+"_v2", keyspace, table, "v2"));
7778

78-
execute("INSERT INTO " + keyspace + "." + table + " (id1, v1, v2) VALUES ('0', 0, '0')");
79-
execute("INSERT INTO " + keyspace + "." + table + " (id1, v1, v2) VALUES ('1', 1, '1')");
80-
execute("INSERT INTO " + keyspace + "." + table + " (id1, v1, v2) VALUES ('2', 2, '2')");
81-
execute("INSERT INTO " + keyspace + "." + table + " (id1, v1, v2) VALUES ('3', 3, '3')");
79+
execute("INSERT INTO " + keyspace + '.' + table + " (id1, v1, v2) VALUES ('0', 0, '0')");
80+
execute("INSERT INTO " + keyspace + '.' + table + " (id1, v1, v2) VALUES ('1', 1, '1')");
81+
execute("INSERT INTO " + keyspace + '.' + table + " (id1, v1, v2) VALUES ('2', 2, '2')");
82+
execute("INSERT INTO " + keyspace + '.' + table + " (id1, v1, v2) VALUES ('3', 3, '3')");
8283

8384
flush(keyspace, table);
8485

85-
ResultSet rows = executeNet("SELECT id1, v1, v2 FROM " + keyspace + "." + table + " WHERE v1 >= 0");
86+
ResultSet rows = executeNet("SELECT id1, v1, v2 FROM " + keyspace + '.' + table + " WHERE v1 >= 0");
8687

8788
int actualRows = rows.all().size();
8889
assertEquals(4, actualRows);
@@ -98,4 +99,55 @@ private int getTableStateMetrics(String keyspace, String table, String metricsNa
9899
{
99100
return (int) getMetricValue(objectNameNoIndex(metricsName, keyspace, table, TABLE_STATE_METRIC_TYPE));
100101
}
102+
103+
@Test
104+
public void testTableStateMetricsEnabledAndDisabled()
105+
{
106+
testTableStateMetrics(true);
107+
testTableStateMetrics(false);
108+
}
109+
110+
private void testTableStateMetrics(boolean metricsEnabled)
111+
{
112+
SAI_TABLE_STATE_METRICS_ENABLED.setBoolean(metricsEnabled);
113+
114+
try
115+
{
116+
String table = "test_table_state_metrics_" + (metricsEnabled ? "enabled" : "disabled");
117+
String index = "test_index_" + (metricsEnabled ? "enabled" : "disabled");
118+
119+
String keyspace = createKeyspace(CREATE_KEYSPACE_TEMPLATE);
120+
createTable(String.format(CREATE_TABLE_TEMPLATE, keyspace, table));
121+
createIndex(String.format(CREATE_INDEX_TEMPLATE, index, keyspace, table, "v1"));
122+
123+
// Test all TableStateMetrics Gauge metrics
124+
assertTableStateMetricExistsIfEnabled(metricsEnabled, "TotalIndexCount", keyspace, table);
125+
assertTableStateMetricExistsIfEnabled(metricsEnabled, "TotalQueryableIndexCount", keyspace, table);
126+
assertTableStateMetricExistsIfEnabled(metricsEnabled, "TotalIndexBuildsInProgress", keyspace, table);
127+
assertTableStateMetricExistsIfEnabled(metricsEnabled, "DiskUsedBytes", keyspace, table);
128+
assertTableStateMetricExistsIfEnabled(metricsEnabled, "DiskPercentageOfBaseTable", keyspace, table);
129+
130+
// Test indexing operations to ensure null stateMetrics is handled gracefully
131+
execute("INSERT INTO " + keyspace + '.' + table + " (id1, v1, v2) VALUES ('0', 0, '0')");
132+
execute("INSERT INTO " + keyspace + '.' + table + " (id1, v1, v2) VALUES ('1', 1, '1')");
133+
execute("INSERT INTO " + keyspace + '.' + table + " (id1, v1, v2) VALUES ('2', 2, '2')");
134+
135+
// Verify metrics still behave correctly after operations
136+
assertTableStateMetricExistsIfEnabled(metricsEnabled, "TotalIndexCount", keyspace, table);
137+
assertTableStateMetricExistsIfEnabled(metricsEnabled, "DiskUsedBytes", keyspace, table);
138+
}
139+
finally
140+
{
141+
// Reset property to default
142+
SAI_TABLE_STATE_METRICS_ENABLED.setBoolean(true);
143+
}
144+
}
145+
146+
void assertTableStateMetricExistsIfEnabled(boolean shouldExist, String metricName, String keyspace, String table)
147+
{
148+
if (shouldExist)
149+
assertMetricExists(objectNameNoIndex(metricName, keyspace, table, TABLE_STATE_METRIC_TYPE));
150+
else
151+
assertMetricDoesNotExist(objectNameNoIndex(metricName, keyspace, table, TABLE_STATE_METRIC_TYPE));
152+
}
101153
}

0 commit comments

Comments
 (0)