/**
* Copyright 2016 LinkedIn Corp. All rights reserved.
*
* Licensed 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.
*/
package com.github.ambry.store;
import com.codahale.metrics.Counter;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.Histogram;
import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Metrics for a specific store.
*/
public class StoreMetrics {
public final Timer getResponse;
public final Timer putResponse;
public final Timer deleteResponse;
public final Timer findEntriesSinceResponse;
public final Timer findMissingKeysResponse;
public final Timer isKeyDeletedResponse;
public final Timer storeStartTime;
public final Histogram storeShutdownTimeInMs;
public final Histogram indexShutdownTimeInMs;
public final Histogram hardDeleteShutdownTimeInMs;
public final Counter storeStartFailure;
public final Counter overflowWriteError;
public final Counter overflowReadError;
public final Timer recoveryTime;
public final Timer findTime;
public final Timer indexFlushTime;
public final Timer cleanupTokenFlushTime;
public final Timer hardDeleteTime;
public final Counter putEntryDeletedInfoMismatchCount;
public final Counter nonzeroMessageRecovery;
public final Counter blobFoundInActiveSegmentCount;
public final Counter bloomAccessedCount;
public final Counter bloomPositiveCount;
public final Counter bloomFalsePositiveCount;
public final Counter keySizeMismatchCount;
public final Counter hardDeleteDoneCount;
public final Counter hardDeleteFailedCount;
public final Counter hardDeleteIncompleteRecoveryCount;
public final Counter hardDeleteExceptionsCount;
public final Histogram segmentSizeForExists;
public final Histogram segmentsAccessedPerBlobCount;
public final Counter identicalPutAttemptCount;
// Compaction related metrics
public final Counter compactionFixStateCount;
public final Meter compactionCopyRateInBytes;
private final MetricRegistry registry;
private final String name;
public StoreMetrics(String storeId, MetricRegistry registry) {
this.registry = registry;
name = storeId + ".";
getResponse = registry.timer(MetricRegistry.name(BlobStore.class, name + "StoreGetResponse"));
putResponse = registry.timer(MetricRegistry.name(BlobStore.class, name + "StorePutResponse"));
deleteResponse = registry.timer(MetricRegistry.name(BlobStore.class, name + "StoreDeleteResponse"));
findEntriesSinceResponse =
registry.timer(MetricRegistry.name(BlobStore.class, name + "StoreFindEntriesSinceResponse"));
findMissingKeysResponse =
registry.timer(MetricRegistry.name(BlobStore.class, name + "StoreFindMissingKeyResponse"));
isKeyDeletedResponse = registry.timer(MetricRegistry.name(BlobStore.class, name + "IsKeyDeletedResponse"));
storeStartTime = registry.timer(MetricRegistry.name(BlobStore.class, name + "StoreStartTime"));
storeShutdownTimeInMs = registry.histogram(MetricRegistry.name(BlobStore.class, name + "StoreShutdownTimeInMs"));
indexShutdownTimeInMs =
registry.histogram(MetricRegistry.name(PersistentIndex.class, name + "IndexShutdownTimeInMs"));
hardDeleteShutdownTimeInMs =
registry.histogram(MetricRegistry.name(HardDeleter.class, name + "HardDeleteShutdownTimeInMs"));
storeStartFailure = registry.counter(MetricRegistry.name(BlobStore.class, name + "StoreStartFailure"));
overflowWriteError = registry.counter(MetricRegistry.name(Log.class, name + "OverflowWriteError"));
overflowReadError = registry.counter(MetricRegistry.name(Log.class, name + "OverflowReadError"));
recoveryTime = registry.timer(MetricRegistry.name(PersistentIndex.class, name + "IndexRecoveryTime"));
findTime = registry.timer(MetricRegistry.name(PersistentIndex.class, name + "IndexFindTime"));
indexFlushTime = registry.timer(MetricRegistry.name(PersistentIndex.class, name + "IndexFlushTime"));
cleanupTokenFlushTime = registry.timer(MetricRegistry.name(PersistentIndex.class, name + "CleanupTokenFlushTime"));
hardDeleteTime = registry.timer(MetricRegistry.name(PersistentIndex.class, name + "HardDeleteTime"));
putEntryDeletedInfoMismatchCount =
registry.counter(MetricRegistry.name(PersistentIndex.class, name + "PutEntryDeletedInfoMismatchCount"));
nonzeroMessageRecovery =
registry.counter(MetricRegistry.name(PersistentIndex.class, name + "NonZeroMessageRecovery"));
blobFoundInActiveSegmentCount =
registry.counter(MetricRegistry.name(IndexSegment.class, name + "BlobFoundInActiveSegmentCount"));
bloomAccessedCount = registry.counter(MetricRegistry.name(IndexSegment.class, name + "BloomAccessedCount"));
bloomPositiveCount = registry.counter(MetricRegistry.name(IndexSegment.class, name + "BloomPositiveCount"));
bloomFalsePositiveCount =
registry.counter(MetricRegistry.name(IndexSegment.class, name + "BloomFalsePositiveCount"));
keySizeMismatchCount = registry.counter(MetricRegistry.name(IndexSegment.class, name + "KeySizeMismatchCount"));
hardDeleteDoneCount = registry.counter(MetricRegistry.name(PersistentIndex.class, name + "HardDeleteDoneCount"));
hardDeleteFailedCount =
registry.counter(MetricRegistry.name(PersistentIndex.class, name + "HardDeleteFailedCount"));
hardDeleteIncompleteRecoveryCount =
registry.counter(MetricRegistry.name(PersistentIndex.class, name + "HardDeleteIncompleteRecoveryCount"));
hardDeleteExceptionsCount =
registry.counter(MetricRegistry.name(PersistentIndex.class, name + "HardDeleteExceptionsCount"));
segmentSizeForExists = registry.histogram(MetricRegistry.name(IndexSegment.class, name + "SegmentSizeForExists"));
segmentsAccessedPerBlobCount =
registry.histogram(MetricRegistry.name(IndexSegment.class, name + "SegmentsAccessedPerBlobCount"));
identicalPutAttemptCount =
registry.counter(MetricRegistry.name(PersistentIndex.class, name + "IdenticalPutAttemptCount"));
compactionFixStateCount = registry.counter(MetricRegistry.name(BlobStoreCompactor.class, name + "FixStateCount"));
compactionCopyRateInBytes = registry.meter(MetricRegistry.name(BlobStoreCompactor.class, "CopyRateInBytes"));
}
MetricRegistry getRegistry() {
return registry;
}
void initializeIndexGauges(final PersistentIndex index, final long capacityInBytes) {
Gauge<Long> currentCapacityUsed = new Gauge<Long>() {
@Override
public Long getValue() {
return index.getLogUsedCapacity();
}
};
registry.register(MetricRegistry.name(Log.class, name + "CurrentCapacityUsed"), currentCapacityUsed);
Gauge<Double> percentageUsedCapacity = new Gauge<Double>() {
@Override
public Double getValue() {
return ((double) index.getLogUsedCapacity() / capacityInBytes) * 100;
}
};
registry.register(MetricRegistry.name(Log.class, name + "PercentageUsedCapacity"), percentageUsedCapacity);
Gauge<Long> currentSegmentCount = new Gauge<Long>() {
@Override
public Long getValue() {
return index.getLogSegmentCount();
}
};
registry.register(MetricRegistry.name(Log.class, name + "CurrentSegmentCount"), currentSegmentCount);
}
void initializeHardDeleteMetric(final HardDeleter hardDeleter, final PersistentIndex index) {
Gauge<Long> currentHardDeleteProgress = new Gauge<Long>() {
@Override
public Long getValue() {
return hardDeleter.getProgress();
}
};
registry.register(MetricRegistry.name(PersistentIndex.class, name + "CurrentHardDeleteProgress"),
currentHardDeleteProgress);
Gauge<Double> percentageHardDeleteCompleted = new Gauge<Double>() {
@Override
public Double getValue() {
return ((double) hardDeleter.getProgress() / index.getLogUsedCapacity()) * 100;
}
};
registry.register(MetricRegistry.name(Log.class, name + "PercentageHardDeleteCompleted"),
percentageHardDeleteCompleted);
Gauge<Long> hardDeleteThreadRunning = new Gauge<Long>() {
@Override
public Long getValue() {
return hardDeleter.isRunning() ? 1L : 0L;
}
};
registry.register(MetricRegistry.name(PersistentIndex.class, name + "HardDeleteThreadRunning"),
hardDeleteThreadRunning);
Gauge<Long> hardDeleteCaughtUp = new Gauge<Long>() {
@Override
public Long getValue() {
return hardDeleter.isCaughtUp() ? 1L : 0L;
}
};
registry.register(MetricRegistry.name(PersistentIndex.class, name + "HardDeleteCaughtUp"), hardDeleteCaughtUp);
}
void initializeCompactorGauges(final AtomicBoolean compactionInProgress) {
Gauge<Long> compactionInProgressGauge = new Gauge<Long>() {
@Override
public Long getValue() {
return compactionInProgress.get() ? 1L : 0L;
}
};
registry.register(MetricRegistry.name(BlobStoreCompactor.class, name + "CompactionInProgress"),
compactionInProgressGauge);
}
}