Skip to content

Commit

Permalink
In-situ tombstone metrics (#524)
Browse files Browse the repository at this point in the history
Co-authored-by: svc-autorelease <[email protected]>
  • Loading branch information
wi11dey and svc-autorelease authored Oct 16, 2024
1 parent 7ca0451 commit c3ab8d6
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 29 deletions.
12 changes: 9 additions & 3 deletions src/java/com/palantir/cassandra/utils/CountingCellIterator.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import org.apache.cassandra.db.Cell;
import org.apache.cassandra.db.ExpiringCell;
import org.apache.cassandra.metrics.ColumnFamilyMetrics;
import org.apache.cassandra.utils.MergeIterator;

/**
Expand All @@ -38,6 +39,7 @@
public class CountingCellIterator implements Iterator<Cell> {
private final Iterator<Cell> delegate;

private final ColumnFamilyMetrics metrics;
/*
* Given the way SliceQueryFilter is passed these values, per ColumnFamilyStore.getColumnFamily(QueryFilter filter),
* it is generally expected that gcBefore will be equivalent to { (now / 1000) - gc_grace_seconds }
Expand All @@ -50,12 +52,13 @@ public class CountingCellIterator implements Iterator<Cell> {
private int liveCells = 0;
private int tombstones = 0;

public static CountingCellIterator wrapIterator(Iterator<Cell> delegate, long timestamp, long gcBefore) {
return new CountingCellIterator(delegate, timestamp, gcBefore);
public static CountingCellIterator wrapIterator(Iterator<Cell> delegate, ColumnFamilyMetrics metrics, long timestamp, long gcBefore) {
return new CountingCellIterator(delegate, metrics, timestamp, gcBefore);
}

private CountingCellIterator(Iterator<Cell> delegate, long timestamp, long gcBefore) {
private CountingCellIterator(Iterator<Cell> delegate, ColumnFamilyMetrics metrics, long timestamp, long gcBefore) {
this.delegate = delegate;
this.metrics = metrics;
this.gcBeforeSeconds = gcBefore;
this.nowMillis = timestamp;
}
Expand Down Expand Up @@ -103,6 +106,9 @@ private void count(Cell cell) {
} else if (ExpiringCell.class.isAssignableFrom(cell.getClass())) {
droppableTtls++;
} else if (cell.getLocalDeletionTime() < gcBeforeSeconds) {
if (metrics != null) {
metrics.droppableTombstones.mark();
}
droppableTombstones++;
} else {
tombstones++;
Expand Down
26 changes: 9 additions & 17 deletions src/java/org/apache/cassandra/db/ColumnFamilyStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -2060,6 +2060,10 @@ public ColumnFamily getColumnFamily(QueryFilter filter)

ColumnFamily result = null;

if (filter.filter instanceof SliceQueryFilter) {
((SliceQueryFilter) filter.filter).setMetrics(metric);
}

long start = System.nanoTime();

int readDelay = DatabaseDescriptor.getReadDelay();
Expand Down Expand Up @@ -2127,7 +2131,6 @@ public ColumnFamily getColumnFamily(QueryFilter filter)
}

private void recordMetrics(SliceQueryFilter filter) {
metric.droppableTombstones.mark(filter.lastReadDroppableTombstones());
// Log the number of tombstones scanned on single key queries
metric.tombstoneScannedHistogram.update(filter.lastTombstones());
metric.liveScannedHistogram.update(filter.lastLive());
Expand All @@ -2136,21 +2139,6 @@ private void recordMetrics(SliceQueryFilter filter) {
metric.liveReadHistogram.update(filter.lastReadLive());
metric.tombstonesReadHistogram.update(filter.lastReadTombstones());

Optional<DeletionInfo> maybeDeletionInfo = filter.lastReadDeletionInfo();

if (maybeDeletionInfo.isPresent()) {
DeletionInfo deletionInfo = maybeDeletionInfo.get();
logger.trace("Ranged tombstones read {} and droppable {} for {}.{}",
deletionInfo.getRangeTombstoneCounter().getNonDroppableCount(),
deletionInfo.getRangeTombstoneCounter().getDroppableCount(), keyspace, getColumnFamilyName());

metric.rangeTombstonesReadHistogram.update(deletionInfo.getRangeTombstoneCounter().getNonDroppableCount());
metric.droppableRangeTombstonesReadHistogram.update(deletionInfo.getRangeTombstoneCounter().getDroppableCount());
metric.rangeTombstonesHistogram.update(deletionInfo.rangeCount());

metric.droppableTombstones.mark(deletionInfo.getRangeTombstoneCounter().getDroppableCount());
}

if (filter.hitTombstoneWarnThreshold()) metric.tombstoneWarnings.inc();
}

Expand Down Expand Up @@ -2586,6 +2574,11 @@ public List<Row> filter(AbstractScanIterator rowIterator, ExtendedFilter filter)

if (rowIterator.needsFiltering())
{
IDiskAtomFilter queryFilter = filter.columnFilter(rawRow.key.getKey());
if (queryFilter instanceof SliceQueryFilter) {
((SliceQueryFilter) queryFilter).setMetrics(metric);
}

IDiskAtomFilter extraFilter = filter.getExtraFilter(rawRow.key, data);
if (extraFilter != null)
{
Expand All @@ -2603,7 +2596,6 @@ public List<Row> filter(AbstractScanIterator rowIterator, ExtendedFilter filter)
// cut the resultset back to what was requested, if necessary
data = filter.prune(rawRow.key, data);

IDiskAtomFilter queryFilter = filter.columnFilter(rawRow.key.getKey());
if (queryFilter instanceof SliceQueryFilter) {
recordMetrics((SliceQueryFilter) queryFilter);
}
Expand Down
31 changes: 22 additions & 9 deletions src/java/org/apache/cassandra/db/filter/SliceQueryFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.composites.*;
import org.apache.cassandra.io.util.FileUtils;
import org.apache.cassandra.metrics.ColumnFamilyMetrics;
import org.apache.cassandra.utils.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -65,15 +66,15 @@ public class SliceQueryFilter implements IDiskAtomFilter
private boolean hitTombstoneFailureThreshold = false;
private boolean hitTombstoneWarnThreshold = false;

private DeletionInfo deletionInfo;

// Not serialized, just a ack for range slices to find the number of live column counted, even when we group
private ColumnCounter columnCounter;

private CountingCellIterator reducedCells;

private RangeTombstoneCounter rangeTombstoneCounter = new RangeTombstoneCounter();

private volatile ColumnFamilyMetrics metrics;

public SliceQueryFilter(Composite start, Composite finish, boolean reversed, int count)
{
this(new ColumnSlice(start, finish), reversed, count);
Expand Down Expand Up @@ -114,6 +115,10 @@ public SliceQueryFilter(ColumnSlice[] slices, boolean reversed, int count, int c
: null;
}

public void setMetrics(ColumnFamilyMetrics metrics) {
this.metrics = metrics;
}

public SliceQueryFilter cloneShallow()
{
return new SliceQueryFilter(slices, reversed, count, compositesToGroup);
Expand Down Expand Up @@ -276,10 +281,22 @@ public Comparator<Cell> getColumnComparator(CellNameType comparator)

public void collectReducedColumns(ColumnFamily container, Iterator<Cell> reducedColumns, DecoratedKey key, int gcBefore, long now)
{
reducedCells = CountingCellIterator.wrapIterator(reducedColumns, now, gcBefore);
reducedCells = CountingCellIterator.wrapIterator(reducedColumns, metrics, now, gcBefore);
columnCounter = columnCounter(container.getComparator(), now);
deletionInfo = container.deletionInfo();
DeletionInfo.InOrderTester tester = container.deletionInfo().inOrderTester(reversed);
DeletionInfo deletionInfo = container.deletionInfo();
logger.trace("Ranged tombstones read {} and droppable {} for {}",
deletionInfo.getRangeTombstoneCounter().getNonDroppableCount(),
deletionInfo.getRangeTombstoneCounter().getDroppableCount(), container.metadata().ksAndCFName);

if (metrics != null)
{
metrics.rangeTombstonesReadHistogram.update(deletionInfo.getRangeTombstoneCounter().getNonDroppableCount());
metrics.droppableRangeTombstonesReadHistogram.update(deletionInfo.getRangeTombstoneCounter().getDroppableCount());
metrics.rangeTombstonesHistogram.update(deletionInfo.rangeCount());

metrics.droppableTombstones.mark(deletionInfo.getRangeTombstoneCounter().getDroppableCount());
}
DeletionInfo.InOrderTester tester = deletionInfo.inOrderTester(reversed);

boolean hasBreachedCollectionThreshold = false;
long dataSizeCollected = 0;
Expand Down Expand Up @@ -500,10 +517,6 @@ public int lastReadTombstones()
return reducedCells == null ? 0 : reducedCells.tombstones();
}

public Optional<DeletionInfo> lastReadDeletionInfo() {
return Optional.ofNullable(deletionInfo);
}

@Override
public String toString()
{
Expand Down

0 comments on commit c3ab8d6

Please sign in to comment.