Index: hbase-server/src/main/java/org/apache/hadoop/hbase/master/metrics/MasterMetricsV2.java =================================================================== --- hbase-server/src/main/java/org/apache/hadoop/hbase/master/metrics/MasterMetricsV2.java (revision ) +++ hbase-server/src/main/java/org/apache/hadoop/hbase/master/metrics/MasterMetricsV2.java (revision ) @@ -0,0 +1,88 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.hbase.master.metrics; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.metrics2.MetricsBuilder; +import org.apache.hadoop.metrics2.MetricsSource; +import org.apache.hadoop.metrics2.MetricsSystem; +import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; +import org.apache.hadoop.metrics2.lib.MetricMutableCounterInt; +import org.apache.hadoop.metrics2.lib.MetricsRegistry; +import org.apache.hadoop.metrics2.source.JvmMetricsSource; + +/** + * + * This class is for maintaining the various HMaster statistics + * and publishing them through the metrics interfaces. + * This also registers the JMX MBean for RPC. + *
+ * This class has a number of metrics variables that are publicly accessible; + * these variables (objects) have methods to update their values; + * for example: + *
{@link #clusterRequests#incr()} + * + */ +public class MasterMetricsV2 implements MetricsSource { + final String name; + final MetricsRegistry registry = new MetricsRegistry("hmaster"); + + final MetricMutableCounterInt clusterRequests = + registry.newCounter("cluster_requests", "", 0); + + public MasterMetricsV2(final String name, final String sessionId) { + this.name = name; + JvmMetricsSource.create("HMaster", sessionId); + registry.setContext(name).tag("sessionId", "", sessionId); + } + + @Override + public void getMetrics(MetricsBuilder builder, boolean all) { + registry.snapshot(builder.addRecord(registry.name()), all); + } + + public static MasterMetricsV2 create(Configuration conf, + String masterName) { + return create(conf, masterName, DefaultMetricsSystem.INSTANCE); + } + + public static MasterMetricsV2 create(Configuration conf, + String masterName, + MetricsSystem ms) { + String name = "hmaster-" + masterName; + String sessionId = conf.get("session.id"); + return ms.register("HMaster", "HMaster metrics", + new MasterMetricsV2(name, sessionId)); + } + + public String getName() { + return name; + } + + public void incrClusterRequests() { + clusterRequests.incr(); + } + + public void incrClusterRequests(int delta) { + clusterRequests.incr(delta); + } + + public MetricMutableCounterInt getClusterRequests() { + return clusterRequests; + } +} Index: conf/hadoop-metrics2.properties =================================================================== --- conf/hadoop-metrics2.properties (revision ) +++ conf/hadoop-metrics2.properties (revision ) @@ -0,0 +1,23 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# syntax: [prefix].[source|sink].[instance].[options] +# See javadoc of package-info.java for org.apache.hadoop.metrics2 for details + +*.sink.file.class=org.apache.hadoop.metrics2.sink.FileSink +# default sampling period +*.period=10 Index: hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java =================================================================== --- hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java (revision 1358294) +++ hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java (revision ) @@ -79,6 +79,7 @@ import org.apache.hadoop.hbase.MasterMonitorProtocol; import org.apache.hadoop.hbase.MasterAdminProtocol; import org.apache.hadoop.hbase.RegionServerStatusProtocol; +import org.apache.hadoop.hbase.master.metrics.MasterMetricsV2; import org.apache.hadoop.hbase.protobuf.ProtobufUtil; import org.apache.hadoop.hbase.protobuf.RequestConverter; import org.apache.hadoop.hbase.ipc.ProtocolSignature; @@ -116,6 +117,7 @@ import org.apache.hadoop.hbase.zookeeper.ZKUtil; import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher; import org.apache.hadoop.metrics.util.MBeanUtil; +import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; import org.apache.hadoop.net.DNS; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.Watcher; @@ -228,6 +230,10 @@ // Metrics for the HMaster private final MasterMetrics metrics; + + // Metrics for the HMaster, using Metrics v2 + private final MasterMetricsV2 metricsV2; + // file system manager for the master FS operations private MasterFileSystem fileSystemManager; @@ -350,6 +356,11 @@ this.zooKeeper = new ZooKeeperWatcher(conf, MASTER + ":" + isa.getPort(), this, true); this.rpcServer.startThreads(); this.metrics = new MasterMetrics(getServerName().toString()); + + DefaultMetricsSystem.initialize("HMaster"); + // TODO: move to where HMaster starts? + this.metricsV2 = MasterMetricsV2.create(conf, getServerName().toString()); + // metrics interval: using the same property as region server. this.msgInterval = conf.getInt("hbase.regionserver.msginterval", 3 * 1000); } @@ -957,6 +968,10 @@ return this.zooKeeper; } + MasterMetricsV2 getMetrics() { + return metricsV2; + } + /* * Start up all services. If any of these threads gets an unhandled exception * then they just die with a logged message. This should be fine because @@ -965,7 +980,7 @@ * need to install an unexpected exception handler. */ void startServiceThreads() throws IOException{ - + // Start the executor service pools this.executorService.startExecutorService(ExecutorType.MASTER_OPEN_REGION, conf.getInt("hbase.master.executor.openregion.threads", 5)); @@ -1119,6 +1134,10 @@ if (sl != null && this.metrics != null) { // Up our metrics. this.metrics.incrementRequests(sl.getTotalNumberOfRequests()); + } + if (sl != null && this.metricsV2 != null) { + // Up our metrics. + this.metricsV2.incrClusterRequests(sl.getTotalNumberOfRequests()); } } catch (IOException ioe) { throw new ServiceException(ioe); Index: hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMasterMetrics.java =================================================================== --- hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMasterMetrics.java (revision 0) +++ hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMasterMetrics.java (revision 0) @@ -0,0 +1,123 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.hbase.master; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.HBaseConfiguration; +import org.apache.hadoop.hbase.HBaseTestingUtility; +import org.apache.hadoop.hbase.HConstants; +import org.apache.hadoop.hbase.MediumTests; +import org.apache.hadoop.hbase.MiniHBaseCluster; +import org.apache.hadoop.hbase.protobuf.ProtobufUtil; +import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos; +import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos; +import org.apache.hadoop.hbase.regionserver.HRegionServer; +import org.apache.hadoop.hbase.util.Threads; +import org.apache.hadoop.metrics2.MetricsRecordBuilder; +import org.apache.hadoop.metrics2.lib.MetricMutableCounterInt; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.junit.After; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import static org.apache.hadoop.test.MetricsAsserts.assertCounter; + +@Category(MediumTests.class) +public class TestMasterMetrics { + private static final Log LOG = LogFactory.getLog(TestMasterMetrics.class); + + static { + Logger.getLogger("org.apache.hadoop.hbase").setLevel(Level.DEBUG); + } + + private MiniHBaseCluster cluster; + private HMaster master; + private Configuration conf; + private HBaseTestingUtility TEST_UTIL; + + private void startCluster() throws Exception{ + LOG.info("Starting cluster"); + conf = HBaseConfiguration.create(); + conf.getLong("hbase.splitlog.max.resubmit", 0); + // Make the failure test faster + conf.setInt("zookeeper.recovery.retry", 0); + conf.setInt(HConstants.REGIONSERVER_INFO_PORT, -1); + conf.setFloat(HConstants.LOAD_BALANCER_SLOP_KEY, (float) 100.0); // no load balancing + conf.setBoolean(HConstants.DISTRIBUTED_LOG_SPLITTING_KEY, true); + TEST_UTIL = new HBaseTestingUtility(conf); + TEST_UTIL.startMiniCluster(1, 1); + cluster = TEST_UTIL.getHBaseCluster(); + LOG.info("Waiting for active/ready master"); + cluster.waitForActiveAndReadyMaster(); + master = cluster.getMaster(); + + while (cluster.getLiveRegionServerThreads().size() < 1) { + Threads.sleep(1); + } + } + + @After + public void after() throws Exception { + if (TEST_UTIL != null) { + TEST_UTIL.shutdownMiniCluster(); + } + } + + @Test(timeout=300000) + public void testClusterRequests() throws Exception { + startCluster(); + + MetricMutableCounterInt metric = master.getMetrics().getClusterRequests(); + int val = getValue(metric); + + // sending fake request to master to see how metric value has changed + RegionServerStatusProtos.RegionServerReportRequest.Builder request = + RegionServerStatusProtos.RegionServerReportRequest.newBuilder(); + HRegionServer rs = cluster.getRegionServer(0); + request.setServer(ProtobufUtil.toServerName(rs.getServerName())); + + HBaseProtos.ServerLoad sl = HBaseProtos.ServerLoad.newBuilder() + .setTotalNumberOfRequests(10) + .build(); + request.setLoad(sl); + master.regionServerReport(null, request.build()); + + assertCounter("cluster_requests", val + 10, master.getMetrics()); + master.stopMaster(); + } + + private int getValue(MetricMutableCounterInt metric) { + final int[] value = new int[1]; + MetricsRecordBuilder mrb = Mockito.mock(MetricsRecordBuilder.class, new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + Object[] args = invocation.getArguments(); + value[0] = (Integer) args[2]; // args are: name, description, value + return invocation.getMock(); + } + }); + metric.snapshot(mrb); + return value[0]; + } +}