View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.regionserver;
19  
20  import org.apache.hadoop.conf.Configuration;
21  import org.apache.hadoop.hbase.*;
22  import org.apache.hadoop.hbase.client.*;
23  import org.apache.hadoop.hbase.test.MetricsAssertHelper;
24  import org.apache.hadoop.hbase.testclassification.MediumTests;
25  import org.apache.hadoop.hbase.util.Bytes;
26  import org.apache.hadoop.hbase.util.Threads;
27  import org.apache.log4j.Level;
28  import org.apache.log4j.Logger;
29  import org.junit.AfterClass;
30  import org.junit.BeforeClass;
31  import org.junit.Test;
32  import org.junit.experimental.categories.Category;
33  
34  import static org.junit.Assert.*;
35  
36  import java.io.IOException;
37  import java.util.ArrayList;
38  import java.util.List;
39  
40  
41  @Category(MediumTests.class)
42  public class TestRegionServerMetrics {
43    private static MetricsAssertHelper metricsHelper;
44  
45    static {
46      Logger.getLogger("org.apache.hadoop.hbase").setLevel(Level.DEBUG);
47    }
48  
49    private static MiniHBaseCluster cluster;
50    private static HRegionServer rs;
51    private static Configuration conf;
52    private static HBaseTestingUtility TEST_UTIL;
53    private static MetricsRegionServer metricsRegionServer;
54    private static MetricsRegionServerSource serverSource;
55    private static final int NUM_SCAN_NEXT = 30;
56    private static int numScanNext = 0;
57  
58    @BeforeClass
59    public static void startCluster() throws Exception {
60      metricsHelper = CompatibilityFactory.getInstance(MetricsAssertHelper.class);
61      TEST_UTIL = new HBaseTestingUtility();
62      conf = TEST_UTIL.getConfiguration();
63      conf.getLong("hbase.splitlog.max.resubmit", 0);
64      // Make the failure test faster
65      conf.setInt("zookeeper.recovery.retry", 0);
66      conf.setInt(HConstants.REGIONSERVER_INFO_PORT, -1);
67  
68      TEST_UTIL.startMiniCluster(1, 1);
69      cluster = TEST_UTIL.getHBaseCluster();
70  
71      cluster.waitForActiveAndReadyMaster();
72  
73      while (cluster.getLiveRegionServerThreads().size() < 1) {
74        Threads.sleep(100);
75      }
76  
77      rs = cluster.getRegionServer(0);
78      metricsRegionServer = rs.getRegionServerMetrics();
79      serverSource = metricsRegionServer.getMetricsSource();
80    }
81  
82    @AfterClass
83    public static void after() throws Exception {
84      if (TEST_UTIL != null) {
85        TEST_UTIL.shutdownMiniCluster();
86      }
87    }
88  
89    @Test(timeout = 300000)
90    public void testRegionCount() throws Exception {
91      String regionMetricsKey = "regionCount";
92      long regions = metricsHelper.getGaugeLong(regionMetricsKey, serverSource);
93      // Creating a table should add one region
94      TEST_UTIL.createTable(TableName.valueOf("table"), Bytes.toBytes("cf"));
95      metricsHelper.assertGaugeGt(regionMetricsKey, regions, serverSource);
96    }
97  
98    @Test
99    public void testLocalFiles() throws Exception {
100     metricsHelper.assertGauge("percentFilesLocal", 0, serverSource);
101     metricsHelper.assertGauge("percentFilesLocalSecondaryRegions", 0, serverSource);
102   }
103 
104   @Test
105   public void testRequestCount() throws Exception {
106     String tableNameString = "testRequestCount";
107     TableName tName = TableName.valueOf(tableNameString);
108     byte[] cfName = Bytes.toBytes("d");
109     byte[] row = Bytes.toBytes("rk");
110     byte[] qualifier = Bytes.toBytes("qual");
111     byte[] initValue = Bytes.toBytes("Value");
112 
113     TEST_UTIL.createTable(tName, cfName);
114 
115     Connection connection = TEST_UTIL.getConnection();
116     connection.getTable(tName).close(); //wait for the table to come up.
117 
118     // Do a first put to be sure that the connection is established, meta is there and so on.
119     Table table = connection.getTable(tName);
120     Put p = new Put(row);
121     p.add(cfName, qualifier, initValue);
122     table.put(p);
123 
124     metricsRegionServer.getRegionServerWrapper().forceRecompute();
125     long requests = metricsHelper.getCounter("totalRequestCount", serverSource);
126     long readRequests = metricsHelper.getCounter("readRequestCount", serverSource);
127     long writeRequests = metricsHelper.getCounter("writeRequestCount", serverSource);
128 
129     for (int i=0; i< 30; i++) {
130       table.put(p);
131     }
132 
133     metricsRegionServer.getRegionServerWrapper().forceRecompute();
134     metricsHelper.assertCounter("totalRequestCount", requests + 30, serverSource);
135     metricsHelper.assertCounter("readRequestCount", readRequests, serverSource);
136     metricsHelper.assertCounter("writeRequestCount", writeRequests + 30, serverSource);
137 
138     Get g = new Get(row);
139     for (int i=0; i< 10; i++) {
140       table.get(g);
141     }
142 
143     metricsRegionServer.getRegionServerWrapper().forceRecompute();
144     metricsHelper.assertCounter("totalRequestCount", requests + 40, serverSource);
145     metricsHelper.assertCounter("readRequestCount", readRequests + 10, serverSource);
146     metricsHelper.assertCounter("writeRequestCount", writeRequests + 30, serverSource);
147 
148     try (RegionLocator locator = connection.getRegionLocator(tName)) {
149       for ( HRegionLocation location: locator.getAllRegionLocations()) {
150         HRegionInfo i = location.getRegionInfo();
151         MetricsRegionAggregateSource agg = rs.getRegion(i.getRegionName())
152             .getMetrics()
153             .getSource()
154             .getAggregateSource();
155         String prefix = "namespace_"+NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR+
156             "_table_"+tableNameString +
157             "_region_" + i.getEncodedName()+
158             "_metric";
159         metricsHelper.assertCounter(prefix + "_getNumOps", 10, agg);
160         metricsHelper.assertCounter(prefix + "_mutateCount", 31, agg);
161       }
162     }
163     List<Get> gets = new ArrayList<Get>();
164     for (int i=0; i< 10; i++) {
165       gets.add(new Get(row));
166     }
167     table.get(gets);
168 
169     // By default, master doesn't host meta now.
170     // Adding some meta related requests
171     requests += 3;
172     readRequests ++;
173 
174     metricsRegionServer.getRegionServerWrapper().forceRecompute();
175     metricsHelper.assertCounter("totalRequestCount", requests + 50, serverSource);
176     metricsHelper.assertCounter("readRequestCount", readRequests + 20, serverSource);
177     metricsHelper.assertCounter("writeRequestCount", writeRequests + 30, serverSource);
178 
179     List<Put> puts = new ArrayList<>();
180     for (int i=0; i< 30; i++) {
181       puts.add(p);
182     }
183     table.put(puts);
184 
185     metricsRegionServer.getRegionServerWrapper().forceRecompute();
186     metricsHelper.assertCounter("totalRequestCount", requests + 80, serverSource);
187     metricsHelper.assertCounter("readRequestCount", readRequests + 20, serverSource);
188     metricsHelper.assertCounter("writeRequestCount", writeRequests + 60, serverSource);
189 
190     table.close();
191   }
192 
193   @Test
194   public void testMutationsWithoutWal() throws Exception {
195     TableName tableName = TableName.valueOf("testMutationsWithoutWal");
196     byte[] cf = Bytes.toBytes("d");
197     byte[] row = Bytes.toBytes("rk");
198     byte[] qualifier = Bytes.toBytes("qual");
199     byte[] val = Bytes.toBytes("Value");
200 
201     metricsRegionServer.getRegionServerWrapper().forceRecompute();
202 
203     TEST_UTIL.createTable(tableName, cf);
204 
205     Table t = new HTable(conf, tableName);
206 
207     Put p = new Put(row);
208     p.add(cf, qualifier, val);
209     p.setDurability(Durability.SKIP_WAL);
210 
211     t.put(p);
212 
213     metricsRegionServer.getRegionServerWrapper().forceRecompute();
214     metricsHelper.assertGauge("mutationsWithoutWALCount", 1, serverSource);
215     long minLength = row.length + cf.length + qualifier.length + val.length;
216     metricsHelper.assertGaugeGt("mutationsWithoutWALSize", minLength, serverSource);
217 
218     t.close();
219   }
220 
221   @Test
222   public void testStoreCount() throws Exception {
223     TableName tableName = TableName.valueOf("testStoreCount");
224     byte[] cf = Bytes.toBytes("d");
225     byte[] row = Bytes.toBytes("rk");
226     byte[] qualifier = Bytes.toBytes("qual");
227     byte[] val = Bytes.toBytes("Value");
228 
229     metricsRegionServer.getRegionServerWrapper().forceRecompute();
230     long stores = metricsHelper.getGaugeLong("storeCount", serverSource);
231     long storeFiles = metricsHelper.getGaugeLong("storeFileCount", serverSource);
232 
233     TEST_UTIL.createTable(tableName, cf);
234 
235     //Force a hfile.
236     Table t = new HTable(conf, tableName);
237     Put p = new Put(row);
238     p.add(cf, qualifier, val);
239     t.put(p);
240     TEST_UTIL.getHBaseAdmin().flush(tableName);
241 
242     metricsRegionServer.getRegionServerWrapper().forceRecompute();
243     metricsHelper.assertGauge("storeCount", stores +1, serverSource);
244     metricsHelper.assertGauge("storeFileCount", storeFiles + 1, serverSource);
245 
246     t.close();
247   }
248 
249   @Test
250   public void testCheckAndPutCount() throws Exception {
251     String tableNameString = "testCheckAndPutCount";
252     TableName tableName = TableName.valueOf(tableNameString);
253     byte[] cf = Bytes.toBytes("d");
254     byte[] row = Bytes.toBytes("rk");
255     byte[] qualifier = Bytes.toBytes("qual");
256     byte[] valOne = Bytes.toBytes("Value");
257     byte[] valTwo = Bytes.toBytes("ValueTwo");
258     byte[] valThree = Bytes.toBytes("ValueThree");
259 
260     TEST_UTIL.createTable(tableName, cf);
261     Table t = new HTable(conf, tableName);
262     Put p = new Put(row);
263     p.add(cf, qualifier, valOne);
264     t.put(p);
265 
266     Put pTwo = new Put(row);
267     pTwo.add(cf, qualifier, valTwo);
268     t.checkAndPut(row, cf, qualifier, valOne, pTwo);
269 
270     Put pThree = new Put(row);
271     pThree.add(cf, qualifier, valThree);
272     t.checkAndPut(row, cf, qualifier, valOne, pThree);
273 
274     metricsRegionServer.getRegionServerWrapper().forceRecompute();
275     metricsHelper.assertCounter("checkMutateFailedCount", 1, serverSource);
276     metricsHelper.assertCounter("checkMutatePassedCount", 1, serverSource);
277 
278     t.close();
279   }
280 
281   @Test
282   public void testIncrement() throws Exception {
283     String tableNameString = "testIncrement";
284     TableName tableName = TableName.valueOf(tableNameString);
285     byte[] cf = Bytes.toBytes("d");
286     byte[] row = Bytes.toBytes("rk");
287     byte[] qualifier = Bytes.toBytes("qual");
288     byte[] val = Bytes.toBytes(0l);
289 
290 
291     TEST_UTIL.createTable(tableName, cf);
292     Table t = new HTable(conf, tableName);
293 
294     Put p = new Put(row);
295     p.add(cf, qualifier, val);
296     t.put(p);
297 
298     for(int count = 0; count< 13; count++) {
299       Increment inc = new Increment(row);
300       inc.addColumn(cf, qualifier, 100);
301       t.increment(inc);
302     }
303 
304     metricsRegionServer.getRegionServerWrapper().forceRecompute();
305     metricsHelper.assertCounter("incrementNumOps", 13, serverSource);
306 
307     t.close();
308   }
309 
310   @Test
311   public void testAppend() throws Exception {
312     String tableNameString = "testAppend";
313     TableName tableName = TableName.valueOf(tableNameString);
314     byte[] cf = Bytes.toBytes("d");
315     byte[] row = Bytes.toBytes("rk");
316     byte[] qualifier = Bytes.toBytes("qual");
317     byte[] val = Bytes.toBytes("One");
318 
319 
320     TEST_UTIL.createTable(tableName, cf);
321     Table t = new HTable(conf, tableName);
322 
323     Put p = new Put(row);
324     p.add(cf, qualifier, val);
325     t.put(p);
326 
327     for(int count = 0; count< 73; count++) {
328       Append append = new Append(row);
329       append.add(cf, qualifier, Bytes.toBytes(",Test"));
330       t.append(append);
331     }
332 
333     metricsRegionServer.getRegionServerWrapper().forceRecompute();
334     metricsHelper.assertCounter("appendNumOps", 73, serverSource);
335 
336     t.close();
337   }
338 
339   @Test
340   public void testScanNext() throws IOException {
341     String tableNameString = "testScanNext";
342     TableName tableName = TableName.valueOf(tableNameString);
343     byte[] cf = Bytes.toBytes("d");
344     byte[] qualifier = Bytes.toBytes("qual");
345     byte[] val = Bytes.toBytes("One");
346 
347     List<Put> puts = new ArrayList<>();
348     for (int insertCount =0; insertCount < 100; insertCount++) {
349       Put p = new Put(Bytes.toBytes("" + insertCount + "row"));
350       p.add(cf, qualifier, val);
351       puts.add(p);
352     }
353     try (HTable t = TEST_UTIL.createTable(tableName, cf)) {
354       t.put(puts);
355 
356       Scan s = new Scan();
357       s.setBatch(1);
358       s.setCaching(1);
359       ResultScanner resultScanners = t.getScanner(s);
360 
361       for (int nextCount = 0; nextCount < NUM_SCAN_NEXT; nextCount++) {
362         Result result = resultScanners.next();
363         assertNotNull(result);
364         assertEquals(1, result.size());
365       }
366     }
367     numScanNext += NUM_SCAN_NEXT;
368     try (RegionLocator locator = TEST_UTIL.getConnection().getRegionLocator(tableName)) {
369       for ( HRegionLocation location: locator.getAllRegionLocations()) {
370         HRegionInfo i = location.getRegionInfo();
371         MetricsRegionAggregateSource agg = rs.getRegion(i.getRegionName())
372             .getMetrics()
373             .getSource()
374             .getAggregateSource();
375         String prefix = "namespace_"+NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR+
376             "_table_"+tableNameString +
377             "_region_" + i.getEncodedName()+
378             "_metric";
379         metricsHelper.assertCounter(prefix + "_scanNextNumOps", NUM_SCAN_NEXT, agg);
380       }
381       metricsHelper.assertCounterGt("ScanNext_num_ops", numScanNext, serverSource);
382     }
383     try (Admin admin = TEST_UTIL.getHBaseAdmin()) {
384       admin.disableTable(tableName);
385       admin.deleteTable(tableName);
386     }
387   }
388 
389   @Test
390   public void testScanNextForSmallScan() throws IOException {
391     String tableNameString = "testScanNextSmall";
392     TableName tableName = TableName.valueOf(tableNameString);
393     byte[] cf = Bytes.toBytes("d");
394     byte[] qualifier = Bytes.toBytes("qual");
395     byte[] val = Bytes.toBytes("One");
396 
397     List<Put> puts = new ArrayList<>();
398     for (int insertCount =0; insertCount < 100; insertCount++) {
399       Put p = new Put(Bytes.toBytes("" + insertCount + "row"));
400       p.add(cf, qualifier, val);
401       puts.add(p);
402     }
403     try (HTable t = TEST_UTIL.createTable(tableName, cf)) {
404       t.put(puts);
405 
406       Scan s = new Scan();
407       s.setSmall(true);
408       s.setCaching(1);
409       ResultScanner resultScanners = t.getScanner(s);
410 
411       for (int nextCount = 0; nextCount < NUM_SCAN_NEXT; nextCount++) {
412         Result result = resultScanners.next();
413         assertNotNull(result);
414         assertEquals(1, result.size());
415       }
416     }
417     numScanNext += NUM_SCAN_NEXT;
418     try (RegionLocator locator = TEST_UTIL.getConnection().getRegionLocator(tableName)) {
419       int cnt = 0;
420       for (HRegionLocation location: locator.getAllRegionLocations()) {
421         cnt++;
422         HRegionInfo i = location.getRegionInfo();
423         MetricsRegionAggregateSource agg = rs.getRegion(i.getRegionName())
424             .getMetrics()
425             .getSource()
426             .getAggregateSource();
427         String prefix = "namespace_"+NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR+
428             "_table_"+tableNameString +
429             "_region_" + i.getEncodedName()+
430             "_metric";
431         metricsHelper.assertCounter(prefix + "_scanNextNumOps", NUM_SCAN_NEXT, agg);
432       }
433       metricsHelper.assertCounterGt("ScanNext_num_ops", numScanNext, serverSource);
434     }
435     try (Admin admin = TEST_UTIL.getHBaseAdmin()) {
436       admin.disableTable(tableName);
437       admin.deleteTable(tableName);
438     }
439   }
440  
441   @Test
442   public void testRangeCountMetrics() throws Exception {
443     String tableNameString = "testRangeCountMetrics";
444     final long[] timeranges =
445         { 1, 3, 10, 30, 100, 300, 1000, 3000, 10000, 30000, 60000, 120000, 300000, 600000 };
446     final String timeRangeType = "TimeRangeCount";
447     final String timeRangeMetricName = "Mutate";
448     boolean timeRangeCountUpdated = false;
449 
450     TableName tName = TableName.valueOf(tableNameString);
451     byte[] cfName = Bytes.toBytes("d");
452     byte[] row = Bytes.toBytes("rk");
453     byte[] qualifier = Bytes.toBytes("qual");
454     byte[] initValue = Bytes.toBytes("Value");
455 
456     TEST_UTIL.createTable(tName, cfName);
457 
458     Connection connection = TEST_UTIL.getConnection();
459     connection.getTable(tName).close(); // wait for the table to come up.
460 
461     // Do a first put to be sure that the connection is established, meta is there and so on.
462     Table table = connection.getTable(tName);
463     Put p = new Put(row);
464     p.addColumn(cfName, qualifier, initValue);
465     table.put(p);
466 
467     // do some puts and gets
468     for (int i = 0; i < 10; i++) {
469       table.put(p);
470     }
471 
472     Get g = new Get(row);
473     for (int i = 0; i < 10; i++) {
474       table.get(g);
475     }
476 
477     metricsRegionServer.getRegionServerWrapper().forceRecompute();
478 
479     // Check some time range counters were updated
480     long prior = 0;
481 
482     String dynamicMetricName;
483     for (int i = 0; i < timeranges.length; i++) {
484       dynamicMetricName =
485           timeRangeMetricName + "_" + timeRangeType + "_" + prior + "-" + timeranges[i];
486       if (metricsHelper.checkCounterExists(dynamicMetricName, serverSource)) {
487         long count = metricsHelper.getCounter(dynamicMetricName, serverSource);
488         if (count > 0) {
489           timeRangeCountUpdated = true;
490           break;
491         }
492       }
493       prior = timeranges[i];
494     }
495     dynamicMetricName =
496         timeRangeMetricName + "_" + timeRangeType + "_" + timeranges[timeranges.length - 1] + "-inf";
497     if (metricsHelper.checkCounterExists(dynamicMetricName, serverSource)) {
498       long count = metricsHelper.getCounter(dynamicMetricName, serverSource);
499       if (count > 0) {
500         timeRangeCountUpdated = true;
501       }
502     }
503     assertEquals(true, timeRangeCountUpdated);
504 
505     table.close();
506   }
507 }