Skip to content

Commit 03450cd

Browse files
pwalczaksmiklosovic
authored andcommitted
Add TotalRowsRead and TotalRowsMutated counters to TableMetrics for accurate per-table row throughput tracking
patch by Piotrek Walczak; reviewed by Dmitry Konstantinov, Stefan Miklosovic for CASSANDRA-21321
1 parent e21461e commit 03450cd

5 files changed

Lines changed: 65 additions & 0 deletions

File tree

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
6.0-alpha2
2+
* Add TotalRowsRead and TotalRowsMutated counters to TableMetrics for accurate per-table row throughput tracking (CASSANDRA-21321)
23
* Move exception handling of SPI startup checks when iterating over them (CASSANDRA-21409)
34
* Avoid type lookup in SerializationHeader#getType if schema and SSTable are aligned (CASSANDRA-21402)
45
* Replace LongAdder in metric-like logic with ThreadLocalCounter (CASSANDRA-21400)

src/java/org/apache/cassandra/db/ColumnFamilyStore.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,6 +1530,7 @@ public void apply(PartitionUpdate update, CassandraWriteContext context, boolean
15301530
metric.topWritePartitionSize.addSample(key.getKey(), update.dataSize());
15311531
StorageHook.instance.reportWrite(metadata.id, update);
15321532
metric.writeLatency.addNano(nanoTime() - start);
1533+
metric.totalRowsMutated.inc(update.affectedRowCount());
15331534
// CASSANDRA-11117 - certain resolution paths on memtable put can result in very
15341535
// large time deltas, either through a variety of sentinel timestamps (used for empty values, ensuring
15351536
// a minimal write, etc). This limits the time delta to the max value the histogram

src/java/org/apache/cassandra/db/ReadCommand.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,7 @@ public void onClose()
718718

719719
metric.tombstoneScannedHistogram.update(tombstones);
720720
metric.liveScannedHistogram.update(liveRows);
721+
metric.totalRowsRead.inc(liveRows);
721722

722723
boolean warnTombstones = tombstones > warningThreshold && respectTombstoneThresholds;
723724
if (warnTombstones)

src/java/org/apache/cassandra/metrics/TableMetrics.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ public class TableMetrics
166166
public final TableHistogram purgeableTombstoneScannedHistogram;
167167
/** Live rows scanned in queries on this CF */
168168
public final TableHistogram liveScannedHistogram;
169+
/** Total number of live rows read from this CF (cumulative counter, suitable for rate/windowed calculations) */
170+
public final Counter totalRowsRead;
171+
/** Total number of rows mutated in writes to this CF (cumulative counter, suitable for rate/windowed calculations) */
172+
public final Counter totalRowsMutated;
169173
/** Column update time delta on this CF */
170174
public final TableHistogram colUpdateTimeDeltaHistogram;
171175
/** time taken acquiring the partition lock for materialized view updates for this table */
@@ -812,6 +816,8 @@ public Long getValue()
812816
tombstoneScannedHistogram = createTableHistogram("TombstoneScannedHistogram", cfs.keyspace.metric.tombstoneScannedHistogram, false);
813817
purgeableTombstoneScannedHistogram = createTableHistogram("PurgeableTombstoneScannedHistogram", cfs.keyspace.metric.purgeableTombstoneScannedHistogram, true);
814818
liveScannedHistogram = createTableHistogram("LiveScannedHistogram", cfs.keyspace.metric.liveScannedHistogram, false);
819+
totalRowsRead = createTableCounter("TotalRowsRead");
820+
totalRowsMutated = createTableCounter("TotalRowsMutated");
815821
colUpdateTimeDeltaHistogram = createTableHistogram("ColUpdateTimeDeltaHistogram", cfs.keyspace.metric.colUpdateTimeDeltaHistogram, false);
816822
coordinatorReadLatency = createTableTimer("CoordinatorReadLatency");
817823
coordinatorScanLatency = createTableTimer("CoordinatorScanLatency");

test/unit/org/apache/cassandra/metrics/TableMetricsTest.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.stream.Collectors;
2525
import java.util.stream.Stream;
2626

27+
import com.codahale.metrics.Counter;
2728
import com.datastax.driver.core.BatchStatement;
2829
import com.datastax.driver.core.Cluster;
2930
import com.datastax.driver.core.PreparedStatement;
@@ -213,6 +214,61 @@ public void testPreparedStatementsExecuted()
213214
assertGreaterThan(cfs.metric.coordinatorWriteLatency.getMeanRate(), 0);
214215
}
215216

217+
@Test
218+
public void testRowsMutatedCounter()
219+
{
220+
ColumnFamilyStore cfs = recreateTable();
221+
assertEquals(0, cfs.metric.totalRowsMutated.getCount());
222+
223+
// Each INSERT touches exactly one row
224+
session.execute(String.format("INSERT INTO %s.%s (id, val1, val2) VALUES (1, 'a', 'b')", KEYSPACE, TABLE));
225+
assertEquals(1, cfs.metric.totalRowsMutated.getCount());
226+
227+
session.execute(String.format("INSERT INTO %s.%s (id, val1, val2) VALUES (2, 'c', 'd')", KEYSPACE, TABLE));
228+
assertEquals(2, cfs.metric.totalRowsMutated.getCount());
229+
230+
// Batch of 3 rows — counter should jump by 3
231+
executeBatch(false, 3, 1);
232+
assertEquals(5, cfs.metric.totalRowsMutated.getCount());
233+
234+
assertMetricRows("TotalRowsMutated", cfs.metric.totalRowsMutated);
235+
}
236+
237+
@Test
238+
public void testRowsReadCounter()
239+
{
240+
ColumnFamilyStore cfs = recreateTable();
241+
assertEquals(0, cfs.metric.totalRowsRead.getCount());
242+
243+
// Seed some rows
244+
for (int i = 0; i < 5; i++)
245+
session.execute(String.format("INSERT INTO %s.%s (id, val1, val2) VALUES (%d, 'v%d', 'x')", KEYSPACE, TABLE, i, i));
246+
247+
// Full-table scan should touch all 5 rows
248+
session.execute(String.format("SELECT * FROM %s.%s", KEYSPACE, TABLE));
249+
assertEquals(5, cfs.metric.totalRowsRead.getCount());
250+
251+
// Single-partition read touches 1 row
252+
session.execute(String.format("SELECT * FROM %s.%s WHERE id = 0", KEYSPACE, TABLE));
253+
assertEquals(6, cfs.metric.totalRowsRead.getCount());
254+
255+
assertMetricRows("TotalRowsRead", cfs.metric.totalRowsRead);
256+
}
257+
258+
private void assertMetricRows(String metricName, Counter counter)
259+
{
260+
assertRowsContains(cluster, session.execute("SELECT * FROM system_metrics.table_group"),
261+
row("org.apache.cassandra.metrics.Table." + metricName + ".junit.tablemetricstest",
262+
"junit.tablemetricstest",
263+
"counter",
264+
String.valueOf(counter.getCount())));
265+
assertRowsContains(cluster, session.execute("SELECT * FROM system_metrics.column_family_group"),
266+
row("org.apache.cassandra.metrics.ColumnFamily." + metricName + ".junit.tablemetricstest",
267+
"junit.tablemetricstest",
268+
"counter",
269+
String.valueOf(counter.getCount())));
270+
}
271+
216272
@Test
217273
public void testLoggedPartitionsPerBatch()
218274
{

0 commit comments

Comments
 (0)