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      conf.setInt("hfile.format.version", 3);
68  
69      TEST_UTIL.startMiniCluster(1, 1);
70      cluster = TEST_UTIL.getHBaseCluster();
71  
72      cluster.waitForActiveAndReadyMaster();
73  
74      while (cluster.getLiveRegionServerThreads().size() < 1) {
75        Threads.sleep(100);
76      }
77  
78      rs = cluster.getRegionServer(0);
79      metricsRegionServer = rs.getRegionServerMetrics();
80      serverSource = metricsRegionServer.getMetricsSource();
81    }
82  
83    @AfterClass
84    public static void after() throws Exception {
85      if (TEST_UTIL != null) {
86        TEST_UTIL.shutdownMiniCluster();
87      }
88    }
89  
90    @Test(timeout = 300000)
91    public void testRegionCount() throws Exception {
92      String regionMetricsKey = "regionCount";
93      long regions = metricsHelper.getGaugeLong(regionMetricsKey, serverSource);
94      // Creating a table should add one region
95      TEST_UTIL.createTable(TableName.valueOf("table"), Bytes.toBytes("cf"));
96      metricsHelper.assertGaugeGt(regionMetricsKey, regions, serverSource);
97    }
98  
99    @Test
100   public void testLocalFiles() throws Exception {
101     metricsHelper.assertGauge("percentFilesLocal", 0, serverSource);
102     metricsHelper.assertGauge("percentFilesLocalSecondaryRegions", 0, serverSource);
103   }
104 
105   @Test
106   public void testRequestCount() throws Exception {
107     String tableNameString = "testRequestCount";
108     TableName tName = TableName.valueOf(tableNameString);
109     byte[] cfName = Bytes.toBytes("d");
110     byte[] row = Bytes.toBytes("rk");
111     byte[] qualifier = Bytes.toBytes("qual");
112     byte[] initValue = Bytes.toBytes("Value");
113 
114     TEST_UTIL.createTable(tName, cfName);
115 
116     Connection connection = TEST_UTIL.getConnection();
117     connection.getTable(tName).close(); //wait for the table to come up.
118 
119     // Do a first put to be sure that the connection is established, meta is there and so on.
120     Table table = connection.getTable(tName);
121     Put p = new Put(row);
122     p.add(cfName, qualifier, initValue);
123     table.put(p);
124 
125     metricsRegionServer.getRegionServerWrapper().forceRecompute();
126     long requests = metricsHelper.getCounter("totalRequestCount", serverSource);
127     long readRequests = metricsHelper.getCounter("readRequestCount", serverSource);
128     long writeRequests = metricsHelper.getCounter("writeRequestCount", serverSource);
129 
130     for (int i=0; i< 30; i++) {
131       table.put(p);
132     }
133 
134     metricsRegionServer.getRegionServerWrapper().forceRecompute();
135     metricsHelper.assertCounter("totalRequestCount", requests + 30, serverSource);
136     metricsHelper.assertCounter("readRequestCount", readRequests, serverSource);
137     metricsHelper.assertCounter("writeRequestCount", writeRequests + 30, serverSource);
138 
139     Get g = new Get(row);
140     for (int i=0; i< 10; i++) {
141       table.get(g);
142     }
143 
144     metricsRegionServer.getRegionServerWrapper().forceRecompute();
145     metricsHelper.assertCounter("totalRequestCount", requests + 40, serverSource);
146     metricsHelper.assertCounter("readRequestCount", readRequests + 10, serverSource);
147     metricsHelper.assertCounter("writeRequestCount", writeRequests + 30, serverSource);
148 
149     try (RegionLocator locator = connection.getRegionLocator(tName)) {
150       for ( HRegionLocation location: locator.getAllRegionLocations()) {
151         HRegionInfo i = location.getRegionInfo();
152         MetricsRegionAggregateSource agg = rs.getRegion(i.getRegionName())
153             .getMetrics()
154             .getSource()
155             .getAggregateSource();
156         String prefix = "namespace_"+NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR+
157             "_table_"+tableNameString +
158             "_region_" + i.getEncodedName()+
159             "_metric";
160         metricsHelper.assertCounter(prefix + "_getNumOps", 10, agg);
161         metricsHelper.assertCounter(prefix + "_mutateCount", 31, agg);
162       }
163     }
164     List<Get> gets = new ArrayList<Get>();
165     for (int i=0; i< 10; i++) {
166       gets.add(new Get(row));
167     }
168     table.get(gets);
169 
170     // By default, master doesn't host meta now.
171     // Adding some meta related requests
172     requests += 3;
173     readRequests ++;
174 
175     metricsRegionServer.getRegionServerWrapper().forceRecompute();
176     metricsHelper.assertCounter("totalRequestCount", requests + 50, serverSource);
177     metricsHelper.assertCounter("readRequestCount", readRequests + 20, serverSource);
178     metricsHelper.assertCounter("writeRequestCount", writeRequests + 30, serverSource);
179 
180     List<Put> puts = new ArrayList<>();
181     for (int i=0; i< 30; i++) {
182       puts.add(p);
183     }
184     table.put(puts);
185 
186     metricsRegionServer.getRegionServerWrapper().forceRecompute();
187     metricsHelper.assertCounter("totalRequestCount", requests + 80, serverSource);
188     metricsHelper.assertCounter("readRequestCount", readRequests + 20, serverSource);
189     metricsHelper.assertCounter("writeRequestCount", writeRequests + 60, serverSource);
190 
191     table.close();
192   }
193 
194   @Test
195   public void testMutationsWithoutWal() throws Exception {
196     TableName tableName = TableName.valueOf("testMutationsWithoutWal");
197     byte[] cf = Bytes.toBytes("d");
198     byte[] row = Bytes.toBytes("rk");
199     byte[] qualifier = Bytes.toBytes("qual");
200     byte[] val = Bytes.toBytes("Value");
201 
202     metricsRegionServer.getRegionServerWrapper().forceRecompute();
203 
204     TEST_UTIL.createTable(tableName, cf);
205 
206     Table t = new HTable(conf, tableName);
207 
208     Put p = new Put(row);
209     p.add(cf, qualifier, val);
210     p.setDurability(Durability.SKIP_WAL);
211 
212     t.put(p);
213 
214     metricsRegionServer.getRegionServerWrapper().forceRecompute();
215     metricsHelper.assertGauge("mutationsWithoutWALCount", 1, serverSource);
216     long minLength = row.length + cf.length + qualifier.length + val.length;
217     metricsHelper.assertGaugeGt("mutationsWithoutWALSize", minLength, serverSource);
218 
219     t.close();
220   }
221 
222   @Test
223   public void testStoreCount() throws Exception {
224     TableName tableName = TableName.valueOf("testStoreCount");
225     byte[] cf = Bytes.toBytes("d");
226     byte[] row = Bytes.toBytes("rk");
227     byte[] qualifier = Bytes.toBytes("qual");
228     byte[] val = Bytes.toBytes("Value");
229 
230     metricsRegionServer.getRegionServerWrapper().forceRecompute();
231     long stores = metricsHelper.getGaugeLong("storeCount", serverSource);
232     long storeFiles = metricsHelper.getGaugeLong("storeFileCount", serverSource);
233 
234     TEST_UTIL.createTable(tableName, cf);
235 
236     //Force a hfile.
237     Table t = new HTable(conf, tableName);
238     Put p = new Put(row);
239     p.add(cf, qualifier, val);
240     t.put(p);
241     TEST_UTIL.getHBaseAdmin().flush(tableName);
242 
243     metricsRegionServer.getRegionServerWrapper().forceRecompute();
244     metricsHelper.assertGauge("storeCount", stores +1, serverSource);
245     metricsHelper.assertGauge("storeFileCount", storeFiles + 1, serverSource);
246 
247     t.close();
248   }
249 
250   @Test
251   public void testCheckAndPutCount() throws Exception {
252     String tableNameString = "testCheckAndPutCount";
253     TableName tableName = TableName.valueOf(tableNameString);
254     byte[] cf = Bytes.toBytes("d");
255     byte[] row = Bytes.toBytes("rk");
256     byte[] qualifier = Bytes.toBytes("qual");
257     byte[] valOne = Bytes.toBytes("Value");
258     byte[] valTwo = Bytes.toBytes("ValueTwo");
259     byte[] valThree = Bytes.toBytes("ValueThree");
260 
261     TEST_UTIL.createTable(tableName, cf);
262     Table t = new HTable(conf, tableName);
263     Put p = new Put(row);
264     p.add(cf, qualifier, valOne);
265     t.put(p);
266 
267     Put pTwo = new Put(row);
268     pTwo.add(cf, qualifier, valTwo);
269     t.checkAndPut(row, cf, qualifier, valOne, pTwo);
270 
271     Put pThree = new Put(row);
272     pThree.add(cf, qualifier, valThree);
273     t.checkAndPut(row, cf, qualifier, valOne, pThree);
274 
275     metricsRegionServer.getRegionServerWrapper().forceRecompute();
276     metricsHelper.assertCounter("checkMutateFailedCount", 1, serverSource);
277     metricsHelper.assertCounter("checkMutatePassedCount", 1, serverSource);
278 
279     t.close();
280   }
281 
282   @Test
283   public void testIncrement() throws Exception {
284     String tableNameString = "testIncrement";
285     TableName tableName = TableName.valueOf(tableNameString);
286     byte[] cf = Bytes.toBytes("d");
287     byte[] row = Bytes.toBytes("rk");
288     byte[] qualifier = Bytes.toBytes("qual");
289     byte[] val = Bytes.toBytes(0l);
290 
291 
292     TEST_UTIL.createTable(tableName, cf);
293     Table t = new HTable(conf, tableName);
294 
295     Put p = new Put(row);
296     p.add(cf, qualifier, val);
297     t.put(p);
298 
299     for(int count = 0; count< 13; count++) {
300       Increment inc = new Increment(row);
301       inc.addColumn(cf, qualifier, 100);
302       t.increment(inc);
303     }
304 
305     metricsRegionServer.getRegionServerWrapper().forceRecompute();
306     metricsHelper.assertCounter("incrementNumOps", 13, serverSource);
307 
308     t.close();
309   }
310 
311   @Test
312   public void testAppend() throws Exception {
313     String tableNameString = "testAppend";
314     TableName tableName = TableName.valueOf(tableNameString);
315     byte[] cf = Bytes.toBytes("d");
316     byte[] row = Bytes.toBytes("rk");
317     byte[] qualifier = Bytes.toBytes("qual");
318     byte[] val = Bytes.toBytes("One");
319 
320 
321     TEST_UTIL.createTable(tableName, cf);
322     Table t = new HTable(conf, tableName);
323 
324     Put p = new Put(row);
325     p.add(cf, qualifier, val);
326     t.put(p);
327 
328     for(int count = 0; count< 73; count++) {
329       Append append = new Append(row);
330       append.add(cf, qualifier, Bytes.toBytes(",Test"));
331       t.append(append);
332     }
333 
334     metricsRegionServer.getRegionServerWrapper().forceRecompute();
335     metricsHelper.assertCounter("appendNumOps", 73, serverSource);
336 
337     t.close();
338   }
339 
340   @Test
341   public void testScanNext() throws IOException {
342     String tableNameString = "testScanNext";
343     TableName tableName = TableName.valueOf(tableNameString);
344     byte[] cf = Bytes.toBytes("d");
345     byte[] qualifier = Bytes.toBytes("qual");
346     byte[] val = Bytes.toBytes("One");
347 
348     List<Put> puts = new ArrayList<>();
349     for (int insertCount =0; insertCount < 100; insertCount++) {
350       Put p = new Put(Bytes.toBytes("" + insertCount + "row"));
351       p.add(cf, qualifier, val);
352       puts.add(p);
353     }
354     try (HTable t = TEST_UTIL.createTable(tableName, cf)) {
355       t.put(puts);
356 
357       Scan s = new Scan();
358       s.setBatch(1);
359       s.setCaching(1);
360       ResultScanner resultScanners = t.getScanner(s);
361 
362       for (int nextCount = 0; nextCount < NUM_SCAN_NEXT; nextCount++) {
363         Result result = resultScanners.next();
364         assertNotNull(result);
365         assertEquals(1, result.size());
366       }
367     }
368     numScanNext += NUM_SCAN_NEXT;
369     try (RegionLocator locator = TEST_UTIL.getConnection().getRegionLocator(tableName)) {
370       for ( HRegionLocation location: locator.getAllRegionLocations()) {
371         HRegionInfo i = location.getRegionInfo();
372         MetricsRegionAggregateSource agg = rs.getRegion(i.getRegionName())
373             .getMetrics()
374             .getSource()
375             .getAggregateSource();
376         String prefix = "namespace_"+NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR+
377             "_table_"+tableNameString +
378             "_region_" + i.getEncodedName()+
379             "_metric";
380         metricsHelper.assertCounter(prefix + "_scanNextNumOps", NUM_SCAN_NEXT, agg);
381       }
382       metricsHelper.assertCounterGt("ScanNext_num_ops", numScanNext, serverSource);
383     }
384     try (Admin admin = TEST_UTIL.getHBaseAdmin()) {
385       admin.disableTable(tableName);
386       admin.deleteTable(tableName);
387     }
388   }
389 
390   @Test
391   public void testScanNextForSmallScan() throws IOException {
392     String tableNameString = "testScanNextSmall";
393     TableName tableName = TableName.valueOf(tableNameString);
394     byte[] cf = Bytes.toBytes("d");
395     byte[] qualifier = Bytes.toBytes("qual");
396     byte[] val = Bytes.toBytes("One");
397 
398     List<Put> puts = new ArrayList<>();
399     for (int insertCount =0; insertCount < 100; insertCount++) {
400       Put p = new Put(Bytes.toBytes("" + insertCount + "row"));
401       p.add(cf, qualifier, val);
402       puts.add(p);
403     }
404     try (HTable t = TEST_UTIL.createTable(tableName, cf)) {
405       t.put(puts);
406 
407       Scan s = new Scan();
408       s.setSmall(true);
409       s.setCaching(1);
410       ResultScanner resultScanners = t.getScanner(s);
411 
412       for (int nextCount = 0; nextCount < NUM_SCAN_NEXT; nextCount++) {
413         Result result = resultScanners.next();
414         assertNotNull(result);
415         assertEquals(1, result.size());
416       }
417     }
418     numScanNext += NUM_SCAN_NEXT;
419     try (RegionLocator locator = TEST_UTIL.getConnection().getRegionLocator(tableName)) {
420       int cnt = 0;
421       for (HRegionLocation location: locator.getAllRegionLocations()) {
422         cnt++;
423         HRegionInfo i = location.getRegionInfo();
424         MetricsRegionAggregateSource agg = rs.getRegion(i.getRegionName())
425             .getMetrics()
426             .getSource()
427             .getAggregateSource();
428         String prefix = "namespace_"+NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR+
429             "_table_"+tableNameString +
430             "_region_" + i.getEncodedName()+
431             "_metric";
432         metricsHelper.assertCounter(prefix + "_scanNextNumOps", NUM_SCAN_NEXT, agg);
433       }
434       metricsHelper.assertCounterGt("ScanNext_num_ops", numScanNext, serverSource);
435     }
436     try (Admin admin = TEST_UTIL.getHBaseAdmin()) {
437       admin.disableTable(tableName);
438       admin.deleteTable(tableName);
439     }
440   }
441  
442   @Test
443   public void testRangeCountMetrics() throws Exception {
444     String tableNameString = "testRangeCountMetrics";
445     final long[] timeranges =
446         { 1, 3, 10, 30, 100, 300, 1000, 3000, 10000, 30000, 60000, 120000, 300000, 600000 };
447     final String timeRangeType = "TimeRangeCount";
448     final String timeRangeMetricName = "Mutate";
449     boolean timeRangeCountUpdated = false;
450 
451     TableName tName = TableName.valueOf(tableNameString);
452     byte[] cfName = Bytes.toBytes("d");
453     byte[] row = Bytes.toBytes("rk");
454     byte[] qualifier = Bytes.toBytes("qual");
455     byte[] initValue = Bytes.toBytes("Value");
456 
457     TEST_UTIL.createTable(tName, cfName);
458 
459     Connection connection = TEST_UTIL.getConnection();
460     connection.getTable(tName).close(); // wait for the table to come up.
461 
462     // Do a first put to be sure that the connection is established, meta is there and so on.
463     Table table = connection.getTable(tName);
464     Put p = new Put(row);
465     p.addColumn(cfName, qualifier, initValue);
466     table.put(p);
467 
468     // do some puts and gets
469     for (int i = 0; i < 10; i++) {
470       table.put(p);
471     }
472 
473     Get g = new Get(row);
474     for (int i = 0; i < 10; i++) {
475       table.get(g);
476     }
477 
478     metricsRegionServer.getRegionServerWrapper().forceRecompute();
479 
480     // Check some time range counters were updated
481     long prior = 0;
482 
483     String dynamicMetricName;
484     for (int i = 0; i < timeranges.length; i++) {
485       dynamicMetricName =
486           timeRangeMetricName + "_" + timeRangeType + "_" + prior + "-" + timeranges[i];
487       if (metricsHelper.checkCounterExists(dynamicMetricName, serverSource)) {
488         long count = metricsHelper.getCounter(dynamicMetricName, serverSource);
489         if (count > 0) {
490           timeRangeCountUpdated = true;
491           break;
492         }
493       }
494       prior = timeranges[i];
495     }
496     dynamicMetricName =
497         timeRangeMetricName + "_" + timeRangeType + "_" + timeranges[timeranges.length - 1] + "-inf";
498     if (metricsHelper.checkCounterExists(dynamicMetricName, serverSource)) {
499       long count = metricsHelper.getCounter(dynamicMetricName, serverSource);
500       if (count > 0) {
501         timeRangeCountUpdated = true;
502       }
503     }
504     assertEquals(true, timeRangeCountUpdated);
505 
506     table.close();
507   }
508 
509   @Test
510   public void testMobMetrics() throws IOException, InterruptedException {
511     String tableNameString = "testMobMetrics";
512     TableName tableName = TableName.valueOf(tableNameString);
513     byte[] cf = Bytes.toBytes("d");
514     byte[] qualifier = Bytes.toBytes("qual");
515     byte[] val = Bytes.toBytes("mobdata");
516     int numHfiles = conf.getInt("hbase.hstore.compactionThreshold", 3) - 1;
517     HTableDescriptor htd = new HTableDescriptor(tableName);
518     HColumnDescriptor hcd = new HColumnDescriptor(cf);
519     hcd.setMobEnabled(true);
520     hcd.setMobThreshold(0);
521     htd.addFamily(hcd);
522     HBaseAdmin admin = new HBaseAdmin(conf);
523     HTable t = TEST_UTIL.createTable(htd, new byte[0][0], conf);
524     Region region = rs.getOnlineRegions(tableName).get(0);
525     t.setAutoFlush(true, true);
526     for (int insertCount = 0; insertCount < numHfiles; insertCount++) {
527       Put p = new Put(Bytes.toBytes(insertCount));
528       p.add(cf, qualifier, val);
529       t.put(p);
530       admin.flush(tableName);
531     }
532     metricsRegionServer.getRegionServerWrapper().forceRecompute();
533     metricsHelper.assertCounter("mobFlushCount", numHfiles, serverSource);
534     Scan scan = new Scan(Bytes.toBytes(0), Bytes.toBytes(2));
535     ResultScanner scanner = t.getScanner(scan);
536     scanner.next(100);
537     scanner.close();
538     metricsRegionServer.getRegionServerWrapper().forceRecompute();
539     metricsHelper.assertCounter("mobScanCellsCount", 2, serverSource);
540     region.getTableDesc().getFamily(cf).setMobThreshold(100);
541     ((HRegion)region).initialize();
542     region.compact(true);
543     metricsRegionServer.getRegionServerWrapper().forceRecompute();
544     metricsHelper.assertCounter("mobCompactedFromMobCellsCount", numHfiles, serverSource);
545     metricsHelper.assertCounter("mobCompactedIntoMobCellsCount", 0, serverSource);
546     scanner = t.getScanner(scan);
547     scanner.next(100);
548     metricsRegionServer.getRegionServerWrapper().forceRecompute();
549     // metrics are reset by the region initialization
550     metricsHelper.assertCounter("mobScanCellsCount", 0, serverSource);
551     for (int insertCount = numHfiles;
552         insertCount < 2 * numHfiles - 1; insertCount++) {
553       Put p = new Put(Bytes.toBytes(insertCount));
554       p.add(cf, qualifier, val);
555       t.put(p);
556       admin.flush(tableName);
557     }
558     region.getTableDesc().getFamily(cf).setMobThreshold(0);
559     ((HRegion)region).initialize();
560     region.compact(true);
561     metricsRegionServer.getRegionServerWrapper().forceRecompute();
562     // metrics are reset by the region initialization
563     metricsHelper.assertCounter("mobCompactedFromMobCellsCount", 0, serverSource);
564     metricsHelper.assertCounter("mobCompactedIntoMobCellsCount", 2 * numHfiles - 1,
565         serverSource);
566     t.close();
567     admin.close();
568   }
569 }