HDDS-1750. Add block allocation metrics for pipelines in SCM. Contributed by Lokesh Jain. (#1047)

This commit is contained in:
Lokesh Jain 2019-07-09 08:42:55 +05:30 committed by Mukul Kumar Singh
parent 738c09349e
commit b5d30e4914
5 changed files with 101 additions and 3 deletions

View File

@ -243,6 +243,7 @@ public class BlockManagerImpl implements BlockManager, BlockmanagerMXBean {
.setPipeline(pipeline); .setPipeline(pipeline);
LOG.trace("New block allocated : {} Container ID: {}", localID, LOG.trace("New block allocated : {} Container ID: {}", localID,
containerID); containerID);
pipelineManager.incNumBlocksAllocatedMetric(pipeline.getId());
return abb.build(); return abb.build();
} catch (PipelineNotFoundException ex) { } catch (PipelineNotFoundException ex) {
LOG.error("Pipeline Machine count is zero.", ex); LOG.error("Pipeline Machine count is zero.", ex);

View File

@ -75,4 +75,6 @@ public interface PipelineManager extends Closeable, PipelineManagerMXBean {
void startPipelineCreator(); void startPipelineCreator();
void triggerPipelineCreation(); void triggerPipelineCreation();
void incNumBlocksAllocatedMetric(PipelineID id);
} }

View File

@ -152,6 +152,7 @@ public class SCMPipelineManager implements PipelineManager {
stateManager.addPipeline(pipeline); stateManager.addPipeline(pipeline);
nodeManager.addPipeline(pipeline); nodeManager.addPipeline(pipeline);
metrics.incNumPipelineCreated(); metrics.incNumPipelineCreated();
metrics.createPerPipelineMetrics(pipeline);
return pipeline; return pipeline;
} catch (InsufficientDatanodesException idEx) { } catch (InsufficientDatanodesException idEx) {
throw idEx; throw idEx;
@ -285,7 +286,8 @@ public class SCMPipelineManager implements PipelineManager {
public void openPipeline(PipelineID pipelineId) throws IOException { public void openPipeline(PipelineID pipelineId) throws IOException {
lock.writeLock().lock(); lock.writeLock().lock();
try { try {
stateManager.openPipeline(pipelineId); Pipeline pipeline = stateManager.openPipeline(pipelineId);
metrics.createPerPipelineMetrics(pipeline);
} finally { } finally {
lock.writeLock().unlock(); lock.writeLock().unlock();
} }
@ -362,6 +364,7 @@ public class SCMPipelineManager implements PipelineManager {
for (ContainerID containerID : containerIDs) { for (ContainerID containerID : containerIDs) {
eventPublisher.fireEvent(SCMEvents.CLOSE_CONTAINER, containerID); eventPublisher.fireEvent(SCMEvents.CLOSE_CONTAINER, containerID);
} }
metrics.removePipelineMetrics(pipelineId);
} finally { } finally {
lock.writeLock().unlock(); lock.writeLock().unlock();
} }
@ -402,6 +405,11 @@ public class SCMPipelineManager implements PipelineManager {
} }
} }
@Override
public void incNumBlocksAllocatedMetric(PipelineID id) {
metrics.incNumBlocksAllocated(id);
}
@Override @Override
public void close() throws IOException { public void close() throws IOException {
if (scheduler != null) { if (scheduler != null) {

View File

@ -19,31 +19,46 @@
package org.apache.hadoop.hdds.scm.pipeline; package org.apache.hadoop.hdds.scm.pipeline;
import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.metrics2.MetricsCollector;
import org.apache.hadoop.metrics2.MetricsRecordBuilder;
import org.apache.hadoop.metrics2.MetricsSource;
import org.apache.hadoop.metrics2.MetricsSystem; import org.apache.hadoop.metrics2.MetricsSystem;
import org.apache.hadoop.metrics2.annotation.Metric; import org.apache.hadoop.metrics2.annotation.Metric;
import org.apache.hadoop.metrics2.annotation.Metrics; import org.apache.hadoop.metrics2.annotation.Metrics;
import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem;
import org.apache.hadoop.metrics2.lib.Interns;
import org.apache.hadoop.metrics2.lib.MetricsRegistry;
import org.apache.hadoop.metrics2.lib.MutableCounterLong; import org.apache.hadoop.metrics2.lib.MutableCounterLong;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* This class maintains Pipeline related metrics. * This class maintains Pipeline related metrics.
*/ */
@InterfaceAudience.Private @InterfaceAudience.Private
@Metrics(about = "SCM PipelineManager Metrics", context = "ozone") @Metrics(about = "SCM PipelineManager Metrics", context = "ozone")
public final class SCMPipelineMetrics { public final class SCMPipelineMetrics implements MetricsSource {
private static final String SOURCE_NAME = private static final String SOURCE_NAME =
SCMPipelineMetrics.class.getSimpleName(); SCMPipelineMetrics.class.getSimpleName();
private MetricsRegistry registry;
private @Metric MutableCounterLong numPipelineCreated; private @Metric MutableCounterLong numPipelineCreated;
private @Metric MutableCounterLong numPipelineCreationFailed; private @Metric MutableCounterLong numPipelineCreationFailed;
private @Metric MutableCounterLong numPipelineDestroyed; private @Metric MutableCounterLong numPipelineDestroyed;
private @Metric MutableCounterLong numPipelineDestroyFailed; private @Metric MutableCounterLong numPipelineDestroyFailed;
private @Metric MutableCounterLong numPipelineReportProcessed; private @Metric MutableCounterLong numPipelineReportProcessed;
private @Metric MutableCounterLong numPipelineReportProcessingFailed; private @Metric MutableCounterLong numPipelineReportProcessingFailed;
private Map<PipelineID, MutableCounterLong> numBlocksAllocated;
/** Private constructor. */ /** Private constructor. */
private SCMPipelineMetrics() { } private SCMPipelineMetrics() {
this.registry = new MetricsRegistry(SOURCE_NAME);
numBlocksAllocated = new ConcurrentHashMap<>();
}
/** /**
* Create and returns SCMPipelineMetrics instance. * Create and returns SCMPipelineMetrics instance.
@ -64,6 +79,43 @@ public final class SCMPipelineMetrics {
ms.unregisterSource(SOURCE_NAME); ms.unregisterSource(SOURCE_NAME);
} }
@Override
@SuppressWarnings("SuspiciousMethodCalls")
public void getMetrics(MetricsCollector collector, boolean all) {
MetricsRecordBuilder recordBuilder = collector.addRecord(SOURCE_NAME);
numPipelineCreated.snapshot(recordBuilder, true);
numPipelineCreationFailed.snapshot(recordBuilder, true);
numPipelineDestroyed.snapshot(recordBuilder, true);
numPipelineDestroyFailed.snapshot(recordBuilder, true);
numPipelineReportProcessed.snapshot(recordBuilder, true);
numPipelineReportProcessingFailed.snapshot(recordBuilder, true);
numBlocksAllocated
.forEach((pid, metric) -> metric.snapshot(recordBuilder, true));
}
void createPerPipelineMetrics(Pipeline pipeline) {
numBlocksAllocated.put(pipeline.getId(), new MutableCounterLong(Interns
.info(getBlockAllocationMetricName(pipeline),
"Number of blocks allocated in pipeline " + pipeline.getId()), 0L));
}
public static String getBlockAllocationMetricName(Pipeline pipeline) {
return "NumBlocksAllocated-" + pipeline.getType() + "-" + pipeline
.getFactor() + "-" + pipeline.getId().getId();
}
void removePipelineMetrics(PipelineID pipelineID) {
numBlocksAllocated.remove(pipelineID);
}
/**
* Increments number of blocks allocated for the pipeline.
*/
void incNumBlocksAllocated(PipelineID pipelineID) {
Optional.of(numBlocksAllocated.get(pipelineID)).ifPresent(
MutableCounterLong::incr);
}
/** /**
* Increments number of successful pipeline creation count. * Increments number of successful pipeline creation count.
*/ */

View File

@ -19,6 +19,9 @@
package org.apache.hadoop.ozone.scm.pipeline; package org.apache.hadoop.ozone.scm.pipeline;
import org.apache.hadoop.hdds.conf.OzoneConfiguration; import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import org.apache.hadoop.hdds.scm.container.common.helpers.AllocatedBlock;
import org.apache.hadoop.hdds.scm.container.common.helpers.ExcludeList;
import org.apache.hadoop.hdds.scm.pipeline.Pipeline; import org.apache.hadoop.hdds.scm.pipeline.Pipeline;
import org.apache.hadoop.hdds.scm.pipeline.PipelineManager; import org.apache.hadoop.hdds.scm.pipeline.PipelineManager;
import org.apache.hadoop.hdds.scm.pipeline.SCMPipelineMetrics; import org.apache.hadoop.hdds.scm.pipeline.SCMPipelineMetrics;
@ -90,6 +93,38 @@ public class TestSCMPipelineMetrics {
assertCounter("NumPipelineDestroyed", 1L, metrics); assertCounter("NumPipelineDestroyed", 1L, metrics);
} }
@Test
public void testNumBlocksAllocated() throws IOException {
AllocatedBlock block =
cluster.getStorageContainerManager().getScmBlockManager()
.allocateBlock(5, HddsProtos.ReplicationType.RATIS,
HddsProtos.ReplicationFactor.ONE, "Test", new ExcludeList());
MetricsRecordBuilder metrics =
getMetrics(SCMPipelineMetrics.class.getSimpleName());
Pipeline pipeline = block.getPipeline();
long numBlocksAllocated = getLongCounter(
SCMPipelineMetrics.getBlockAllocationMetricName(pipeline), metrics);
Assert.assertEquals(numBlocksAllocated, 1);
// destroy the pipeline
try {
cluster.getStorageContainerManager().getClientProtocolServer()
.closePipeline(pipeline.getId().getProtobuf());
} catch (IOException e) {
e.printStackTrace();
Assert.fail();
}
metrics = getMetrics(SCMPipelineMetrics.class.getSimpleName());
try {
getLongCounter(SCMPipelineMetrics.getBlockAllocationMetricName(pipeline),
metrics);
Assert.fail("Metric should not be present for closed pipeline.");
} catch (AssertionError e) {
Assert.assertTrue(e.getMessage().contains(
"Expected exactly one metric for name " + SCMPipelineMetrics
.getBlockAllocationMetricName(block.getPipeline())));
}
}
@After @After
public void teardown() { public void teardown() {