1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.master.metrics;
20  
21  import static org.junit.Assert.*;
22  
23  import java.lang.management.ManagementFactory;
24  
25  import javax.management.MBeanServer;
26  import javax.management.ObjectName;
27  
28  import org.apache.hadoop.hbase.MediumTests;
29  import org.junit.Before;
30  import org.junit.Test;
31  import org.junit.experimental.categories.Category;
32  
33  /**
34   * Tests {@link MasterMetrics} and access to it through the
35   * {@link MasterStatistics} management bean.
36   * 
37   * Note: this test must always be run in separate fork (process)
38   * because it changes static contents of metrics subsystem and 
39   * is affected itself by that static contents. For that reason 
40   * the test put into {@link MediumTests} Category.   
41   */
42  @Category(MediumTests.class)
43  public class TestMasterStatistics {
44  
45    @Before
46    @SuppressWarnings("deprecation")
47    public void ensureNullContext() throws Exception {
48      // Clean up the factory attributes to instantiate the NullContext,
49      // regardless if the resource "/hadoop-metrics.properties" is present 
50      // in the class-path: 
51      org.apache.hadoop.metrics.ContextFactory factory = 
52          org.apache.hadoop.metrics.ContextFactory.getFactory();
53      String[] attributeNames = factory.getAttributeNames();
54      for (String attributeName: attributeNames) {
55        factory.removeAttribute(attributeName);
56      }
57      // ensure the attributes are cleaned up:
58      attributeNames = factory.getAttributeNames();
59      assertEquals(0, attributeNames.length);
60      // Get the "hbase" context and ensure it is NullContext:  
61      org.apache.hadoop.metrics.MetricsContext context 
62        = org.apache.hadoop.metrics.MetricsUtil.getContext("hbase");
63      assertTrue(context instanceof org.apache.hadoop.metrics.spi.NullContext);
64      assertTrue(!context.isMonitoring());
65    }
66    
67    @Test
68    public void testMasterStatistics() throws Exception {
69      // No timer updates started here since NullContext is used, see #ensureNullContext().
70      // (NullContext never starts the updater thread).
71      MasterMetrics masterMetrics = new MasterMetrics("foo");
72      
73      try {
74        final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
75        final ObjectName objectName = new ObjectName(
76            "hadoop:name=MasterStatistics,service=Master");
77  
78        masterMetrics.doUpdates(null);
79  
80        masterMetrics.resetAllMinMax();
81  
82        masterMetrics.incrementRequests(10);
83        Thread.sleep(1001);
84  
85        masterMetrics.addSnapshot(1L);
86        masterMetrics.addSnapshotClone(2L);
87        masterMetrics.addSnapshotRestore(3L);
88  
89        // 3 times added split, average = (5+3+4)/3 = 4
90        masterMetrics.addSplit(4L, 5L);
91        masterMetrics.addSplit(2L, 3L);
92        masterMetrics.addSplit(13L, 4L);
93  
94        masterMetrics.doUpdates(null);
95  
96        final float f = masterMetrics.getRequests();
97        // f = 10/T, where T >= 1 sec. So, we assert that 0 < f <= 10:
98        if (f <= 0.0f || f > 10.0f) {
99          fail("Unexpected rate value: " + f);
100       }
101       Object attribute = server.getAttribute(objectName, "cluster_requests");
102       float f2 = ((Float) attribute).floatValue();
103       assertEquals("The value obtained through bean server should be equal to the one " +
104           "obtained directly.", f, f2, 1e-4);
105 
106       // NB: these 3 metrics are not pushed upon masterMetrics.doUpdates(),
107       // so they always return null:
108       attribute = server.getAttribute(objectName, "snapshotTimeNumOps");
109       assertEquals(Integer.valueOf(0), attribute);
110       attribute = server.getAttribute(objectName, "snapshotRestoreTimeNumOps");
111       assertEquals(Integer.valueOf(0), attribute);
112       attribute = server.getAttribute(objectName, "snapshotCloneTimeNumOps");
113       assertEquals(Integer.valueOf(0), attribute);
114 
115       attribute = server.getAttribute(objectName, "splitSizeNumOps");
116       assertEquals(Integer.valueOf(3), attribute);
117       attribute = server.getAttribute(objectName, "splitSizeAvgTime");
118       assertEquals(Long.valueOf(4), attribute);
119     } finally {
120       masterMetrics.shutdown();
121     }
122   }
123 
124   @Test
125   public void testHBaseInfoBean() throws Exception {
126     MasterMetrics masterMetrics = new MasterMetrics("foo");
127     try {
128       final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
129       // Test Info bean:
130       final ObjectName objectName2 = new ObjectName(
131           "hadoop:name=Info,service=HBase");
132       Object attribute;
133       attribute = server.getAttribute(objectName2, "revision");
134       assertNotNull(attribute);
135       attribute = server.getAttribute(objectName2, "version");
136       assertNotNull(attribute);
137       attribute = server.getAttribute(objectName2, "hdfsUrl");
138       assertNotNull(attribute);
139       attribute = server.getAttribute(objectName2, "user");
140       assertNotNull(attribute);
141     } finally {
142       masterMetrics.shutdown();
143     }
144   }
145 }