From c85185a68f04b96a460c8dc92a475c6baec1dbac Mon Sep 17 00:00:00 2001 From: Zhihong Yu Date: Tue, 19 Jun 2012 18:04:45 +0000 Subject: [PATCH] HBASE-6211 Put latencies in jmx (Elliot Clark) Submitted by: Elliot Clark Reviewed by: Stack, Ted git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1351789 13f79535-47bb-0310-9956-ffa450edef68 --- .../hbase/metrics/MetricsMBeanBase.java | 74 +++++++++++++++++++ .../metrics/histogram/MetricsHistogram.java | 31 +++++--- .../hbase/metrics/TestMetricsMBeanBase.java | 54 ++++++++++++++ 3 files changed, 148 insertions(+), 11 deletions(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/metrics/MetricsMBeanBase.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/metrics/MetricsMBeanBase.java index d23f37897af..ce5e3230c98 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/metrics/MetricsMBeanBase.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/metrics/MetricsMBeanBase.java @@ -30,9 +30,11 @@ import javax.management.MBeanException; import javax.management.MBeanInfo; import javax.management.ReflectionException; +import com.yammer.metrics.stats.Snapshot; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.classification.InterfaceAudience; +import org.apache.hadoop.hbase.metrics.histogram.MetricsHistogram; import org.apache.hadoop.metrics.util.MetricsBase; import org.apache.hadoop.metrics.util.MetricsDynamicMBeanBase; import org.apache.hadoop.metrics.util.MetricsRegistry; @@ -106,6 +108,52 @@ public class MetricsMBeanBase extends MetricsDynamicMBeanBase { "java.lang.String", metric.getDescription(), true, false, false) ); extendedAttributes.put(metric.getName(), metric); LOG.info("MetricsString added: " + metric.getName()); + } else if (metric instanceof MetricsHistogram) { + + String metricName = metric.getName() + MetricsHistogram.NUM_OPS_METRIC_NAME; + attributes.add(new MBeanAttributeInfo(metricName, + "java.lang.Long", metric.getDescription(), true, false, false)); + extendedAttributes.put(metricName, metric); + + metricName = metric.getName() + MetricsHistogram.MIN_METRIC_NAME; + attributes.add(new MBeanAttributeInfo(metricName, + "java.lang.Long", metric.getDescription(), true, false, false)); + extendedAttributes.put(metricName, metric); + + metricName = metric.getName() + MetricsHistogram.MAX_METRIC_NAME; + attributes.add(new MBeanAttributeInfo(metricName, + "java.lang.Long", metric.getDescription(), true, false, false)); + extendedAttributes.put(metricName, metric); + + metricName = metric.getName() + MetricsHistogram.MEAN_METRIC_NAME; + attributes.add(new MBeanAttributeInfo(metricName, + "java.lang.Float", metric.getDescription(), true, false, false)); + extendedAttributes.put(metricName, metric); + + metricName = metric.getName() + MetricsHistogram.STD_DEV_METRIC_NAME; + attributes.add(new MBeanAttributeInfo(metricName, + "java.lang.Float", metric.getDescription(), true, false, false)); + extendedAttributes.put(metricName, metric); + + metricName = metric.getName() + MetricsHistogram.MEDIAN_METRIC_NAME; + attributes.add(new MBeanAttributeInfo(metricName, + "java.lang.Float", metric.getDescription(), true, false, false)); + extendedAttributes.put(metricName, metric); + + metricName = metric.getName() + MetricsHistogram.SEVENTY_FIFTH_PERCENTILE_METRIC_NAME; + attributes.add(new MBeanAttributeInfo(metricName, + "java.lang.Float", metric.getDescription(), true, false, false)); + extendedAttributes.put(metricName, metric); + + metricName = metric.getName() + MetricsHistogram.NINETY_FIFTH_PERCENTILE_METRIC_NAME; + attributes.add(new MBeanAttributeInfo(metricName, + "java.lang.Float", metric.getDescription(), true, false, false)); + extendedAttributes.put(metricName, metric); + + metricName = metric.getName() + MetricsHistogram.NINETY_NINETH_PERCENTILE_METRIC_NAME; + attributes.add(new MBeanAttributeInfo(metricName, + "java.lang.Float", metric.getDescription(), true, false, false)); + extendedAttributes.put(metricName, metric); } // else, its probably a hadoop metric already registered. Skip it. } @@ -150,6 +198,32 @@ public class MetricsMBeanBase extends MetricsDynamicMBeanBase { return ((MetricsRate) metric).getPreviousIntervalValue(); } else if (metric instanceof MetricsString) { return ((MetricsString)metric).getValue(); + } else if (metric instanceof MetricsHistogram) { + MetricsHistogram hist = (MetricsHistogram) metric; + if (name.endsWith(MetricsHistogram.NUM_OPS_METRIC_NAME)) { + return hist.getCount(); + } else if (name.endsWith(MetricsHistogram.MIN_METRIC_NAME)) { + return hist.getMin(); + } else if (name.endsWith(MetricsHistogram.MAX_METRIC_NAME)) { + return hist.getMax(); + } else if (name.endsWith(MetricsHistogram.MEAN_METRIC_NAME)) { + return (float) hist.getMean(); + } else if (name.endsWith(MetricsHistogram.STD_DEV_METRIC_NAME)) { + return (float) hist.getStdDev(); + } else if (name.endsWith(MetricsHistogram.MEDIAN_METRIC_NAME)) { + Snapshot s = hist.getSnapshot(); + return (float) s.getMedian(); + } else if (name.endsWith(MetricsHistogram.SEVENTY_FIFTH_PERCENTILE_METRIC_NAME)) { + Snapshot s = hist.getSnapshot(); + return (float) s.get75thPercentile(); + } else if (name.endsWith(MetricsHistogram.NINETY_FIFTH_PERCENTILE_METRIC_NAME)) { + Snapshot s = hist.getSnapshot(); + return (float) s.get95thPercentile(); + } else if (name.endsWith(MetricsHistogram.NINETY_NINETH_PERCENTILE_METRIC_NAME)) { + Snapshot s = hist.getSnapshot(); + return (float) s.get99thPercentile(); + } + } else { LOG.warn( String.format("unknown metrics type %s for attribute %s", metric.getClass().getName(), name) ); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/metrics/histogram/MetricsHistogram.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/metrics/histogram/MetricsHistogram.java index 7b65a8fabda..392cbf9876a 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/metrics/histogram/MetricsHistogram.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/metrics/histogram/MetricsHistogram.java @@ -39,6 +39,15 @@ public class MetricsHistogram extends MetricsBase { // the bias towards sampling from more recent data. // Per Cormode et al. an alpha of 0.015 strongly biases to the last 5 minutes private static final double DEFAULT_ALPHA = 0.015; + public static final String NUM_OPS_METRIC_NAME = "_num_ops"; + public static final String MIN_METRIC_NAME = "_min"; + public static final String MAX_METRIC_NAME = "_max"; + public static final String MEAN_METRIC_NAME = "_mean"; + public static final String STD_DEV_METRIC_NAME = "_std_dev"; + public static final String MEDIAN_METRIC_NAME = "_median"; + public static final String SEVENTY_FIFTH_PERCENTILE_METRIC_NAME = "_75th_percentile"; + public static final String NINETY_FIFTH_PERCENTILE_METRIC_NAME = "_95th_percentile"; + public static final String NINETY_NINETH_PERCENTILE_METRIC_NAME = "_99th_percentile"; /** * Constructor to create a new histogram metric @@ -212,19 +221,19 @@ public class MetricsHistogram extends MetricsBase { @Override public void pushMetric(MetricsRecord mr) { final Snapshot s = this.getSnapshot(); - mr.setMetric(getName() + "_num_ops", this.getCount()); - mr.setMetric(getName() + "_min", this.getMin()); - mr.setMetric(getName() + "_max", this.getMax()); - - mr.setMetric(getName() + "_mean", (float) this.getMean()); - mr.setMetric(getName() + "_std_dev", (float) this.getStdDev()); - - mr.setMetric(getName() + "_median", (float) s.getMedian()); - mr.setMetric(getName() + "_75th_percentile", + mr.setMetric(getName() + NUM_OPS_METRIC_NAME, this.getCount()); + mr.setMetric(getName() + MIN_METRIC_NAME, this.getMin()); + mr.setMetric(getName() + MAX_METRIC_NAME, this.getMax()); + + mr.setMetric(getName() + MEAN_METRIC_NAME, (float) this.getMean()); + mr.setMetric(getName() + STD_DEV_METRIC_NAME, (float) this.getStdDev()); + + mr.setMetric(getName() + MEDIAN_METRIC_NAME, (float) s.getMedian()); + mr.setMetric(getName() + SEVENTY_FIFTH_PERCENTILE_METRIC_NAME, (float) s.get75thPercentile()); - mr.setMetric(getName() + "_95th_percentile", + mr.setMetric(getName() + NINETY_FIFTH_PERCENTILE_METRIC_NAME, (float) s.get95thPercentile()); - mr.setMetric(getName() + "_99th_percentile", + mr.setMetric(getName() + NINETY_NINETH_PERCENTILE_METRIC_NAME, (float) s.get99thPercentile()); } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/metrics/TestMetricsMBeanBase.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/metrics/TestMetricsMBeanBase.java index 1a6e0ebdfad..ad824583c52 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/metrics/TestMetricsMBeanBase.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/metrics/TestMetricsMBeanBase.java @@ -24,10 +24,15 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.management.AttributeNotFoundException; import javax.management.MBeanAttributeInfo; +import javax.management.MBeanException; import javax.management.MBeanInfo; +import javax.management.ReflectionException; +import com.yammer.metrics.stats.Snapshot; import org.apache.hadoop.hbase.SmallTests; +import org.apache.hadoop.hbase.metrics.histogram.MetricsHistogram; import org.apache.hadoop.metrics.MetricsContext; import org.apache.hadoop.metrics.MetricsRecord; import org.apache.hadoop.metrics.MetricsUtil; @@ -38,6 +43,9 @@ import org.apache.hadoop.metrics.util.MetricsTimeVaryingRate; import junit.framework.TestCase; import org.junit.experimental.categories.Category; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + @Category(SmallTests.class) public class TestMetricsMBeanBase extends TestCase { @@ -114,6 +122,52 @@ public class TestMetricsMBeanBase extends TestCase { "varyRateNumOps", "java.lang.Integer", "test"); } + public void testMetricsMBeanBaseHistogram() + throws ReflectionException, AttributeNotFoundException, MBeanException { + MetricsRegistry mr = new MetricsRegistry(); + MetricsHistogram histo = mock(MetricsHistogram.class); + Snapshot snap = mock(Snapshot.class); + + //Set up the mocks + String histoName = "MockHisto"; + when(histo.getName()).thenReturn(histoName); + when(histo.getCount()).thenReturn(20l); + when(histo.getMin()).thenReturn(1l); + when(histo.getMax()).thenReturn(999l); + when(histo.getMean()).thenReturn(500.2); + when(histo.getStdDev()).thenReturn(1.2); + when(histo.getSnapshot()).thenReturn(snap); + + when(snap.getMedian()).thenReturn(490.0); + when(snap.get75thPercentile()).thenReturn(550.0); + when(snap.get95thPercentile()).thenReturn(900.0); + when(snap.get99thPercentile()).thenReturn(990.0); + + mr.add("myTestHisto", histo); + + MetricsMBeanBase mBeanBase = new MetricsMBeanBase(mr, "test"); + + assertEquals(new Long(20), mBeanBase + .getAttribute(histoName + MetricsHistogram.NUM_OPS_METRIC_NAME)); + assertEquals(new Long(1), mBeanBase + .getAttribute(histoName + MetricsHistogram.MIN_METRIC_NAME)); + assertEquals(new Long(999), mBeanBase + .getAttribute(histoName + MetricsHistogram.MAX_METRIC_NAME)); + assertEquals(new Float(500.2), mBeanBase + .getAttribute(histoName + MetricsHistogram.MEAN_METRIC_NAME)); + assertEquals(new Float(1.2), mBeanBase + .getAttribute(histoName + MetricsHistogram.STD_DEV_METRIC_NAME)); + + assertEquals(new Float(490.0), mBeanBase + .getAttribute(histoName + MetricsHistogram.MEDIAN_METRIC_NAME)); + assertEquals(new Float(550.0), mBeanBase + .getAttribute(histoName + MetricsHistogram.SEVENTY_FIFTH_PERCENTILE_METRIC_NAME)); + assertEquals(new Float(900.0), mBeanBase + .getAttribute(histoName + MetricsHistogram.NINETY_FIFTH_PERCENTILE_METRIC_NAME)); + assertEquals(new Float(990.0), mBeanBase + .getAttribute(histoName + MetricsHistogram.NINETY_NINETH_PERCENTILE_METRIC_NAME)); + } + protected void assertAttribute(MBeanAttributeInfo attr, String name, String type, String description) {