001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase;
019
020import java.io.IOException;
021import java.security.PrivilegedAction;
022import java.util.EnumSet;
023import java.util.List;
024import java.util.Map;
025import java.util.Optional;
026import java.util.concurrent.CompletableFuture;
027import java.util.concurrent.atomic.AtomicInteger;
028import org.apache.hadoop.conf.Configuration;
029import org.apache.hadoop.hbase.ClusterMetrics.Option;
030import org.apache.hadoop.hbase.Waiter.Predicate;
031import org.apache.hadoop.hbase.client.Admin;
032import org.apache.hadoop.hbase.client.AsyncAdmin;
033import org.apache.hadoop.hbase.client.AsyncConnection;
034import org.apache.hadoop.hbase.client.ClusterConnectionFactory;
035import org.apache.hadoop.hbase.client.Connection;
036import org.apache.hadoop.hbase.client.ConnectionFactory;
037import org.apache.hadoop.hbase.client.Get;
038import org.apache.hadoop.hbase.client.Put;
039import org.apache.hadoop.hbase.client.RegionInfoBuilder;
040import org.apache.hadoop.hbase.client.RegionStatesCount;
041import org.apache.hadoop.hbase.client.Result;
042import org.apache.hadoop.hbase.client.Scan;
043import org.apache.hadoop.hbase.client.Table;
044import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
045import org.apache.hadoop.hbase.coprocessor.MasterCoprocessor;
046import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
047import org.apache.hadoop.hbase.coprocessor.MasterObserver;
048import org.apache.hadoop.hbase.coprocessor.ObserverContext;
049import org.apache.hadoop.hbase.filter.FilterAllFilter;
050import org.apache.hadoop.hbase.master.HMaster;
051import org.apache.hadoop.hbase.monitoring.TaskMonitor;
052import org.apache.hadoop.hbase.regionserver.HRegionServer;
053import org.apache.hadoop.hbase.regionserver.MetricsUserAggregateFactory;
054import org.apache.hadoop.hbase.security.User;
055import org.apache.hadoop.hbase.security.UserProvider;
056import org.apache.hadoop.hbase.testclassification.MediumTests;
057import org.apache.hadoop.hbase.util.Bytes;
058import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
059import org.apache.hadoop.hbase.util.JVMClusterUtil.MasterThread;
060import org.apache.hadoop.hbase.util.JVMClusterUtil.RegionServerThread;
061import org.junit.AfterClass;
062import org.junit.Assert;
063import org.junit.BeforeClass;
064import org.junit.ClassRule;
065import org.junit.Test;
066import org.junit.experimental.categories.Category;
067
068@Category(MediumTests.class)
069public class TestClientClusterMetrics {
070
071  @ClassRule
072  public static final HBaseClassTestRule CLASS_RULE =
073    HBaseClassTestRule.forClass(TestClientClusterMetrics.class);
074
075  private static HBaseTestingUtil UTIL;
076  private static Admin ADMIN;
077  private final static int SLAVES = 5;
078  private final static int MASTERS = 3;
079  private static SingleProcessHBaseCluster CLUSTER;
080  private static HRegionServer DEAD;
081  private static final TableName TABLE_NAME = TableName.valueOf("test");
082  private static final byte[] CF = Bytes.toBytes("cf");
083
084  // We need to promote the visibility of tryRegionServerReport for this test
085  public static class MyRegionServer
086    extends SingleProcessHBaseCluster.MiniHBaseClusterRegionServer {
087    public MyRegionServer(Configuration conf) throws IOException, InterruptedException {
088      super(conf);
089    }
090
091    @Override
092    public void tryRegionServerReport(long reportStartTime, long reportEndTime) throws IOException {
093      super.tryRegionServerReport(reportStartTime, reportEndTime);
094    }
095  }
096
097  @BeforeClass
098  public static void setUpBeforeClass() throws Exception {
099    Configuration conf = HBaseConfiguration.create();
100    conf.set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY, MyObserver.class.getName());
101    UTIL = new HBaseTestingUtil(conf);
102    StartTestingClusterOption option =
103      StartTestingClusterOption.builder().rsClass(TestClientClusterMetrics.MyRegionServer.class)
104        .numMasters(MASTERS).numRegionServers(SLAVES).numDataNodes(SLAVES).build();
105    UTIL.startMiniCluster(option);
106    CLUSTER = UTIL.getHBaseCluster();
107    CLUSTER.waitForActiveAndReadyMaster();
108    ADMIN = UTIL.getAdmin();
109    // Kill one region server
110    List<RegionServerThread> rsts = CLUSTER.getLiveRegionServerThreads();
111    RegionServerThread rst = rsts.get(rsts.size() - 1);
112    DEAD = rst.getRegionServer();
113    DEAD.stop("Test dead servers metrics");
114    while (rst.isAlive()) {
115      Thread.sleep(500);
116    }
117  }
118
119  @Test
120  public void testDefaults() throws Exception {
121    ClusterMetrics origin = ADMIN.getClusterMetrics();
122    ClusterMetrics defaults = ADMIN.getClusterMetrics(EnumSet.allOf(Option.class));
123    Assert.assertEquals(origin.getHBaseVersion(), defaults.getHBaseVersion());
124    Assert.assertEquals(origin.getClusterId(), defaults.getClusterId());
125    Assert.assertEquals(origin.getAverageLoad(), defaults.getAverageLoad(), 0);
126    Assert.assertEquals(origin.getBackupMasterNames().size(),
127      defaults.getBackupMasterNames().size());
128    Assert.assertEquals(origin.getDeadServerNames().size(), defaults.getDeadServerNames().size());
129    Assert.assertEquals(origin.getRegionCount(), defaults.getRegionCount());
130    Assert.assertEquals(origin.getLiveServerMetrics().size(),
131      defaults.getLiveServerMetrics().size());
132    Assert.assertEquals(origin.getMasterInfoPort(), defaults.getMasterInfoPort());
133    Assert.assertEquals(origin.getServersName().size(), defaults.getServersName().size());
134    Assert.assertEquals(ADMIN.getRegionServers().size(), defaults.getServersName().size());
135    // We decommission the first online region server and verify the metrics.
136    List<ServerName> serverNames = origin.getServersName().subList(0, 1);
137    ADMIN.decommissionRegionServers(serverNames, false);
138    Assert.assertEquals(1, ADMIN.getClusterMetrics().getDecommissionedServerNames().size());
139    Assert.assertEquals(ADMIN.getClusterMetrics().getDecommissionedServerNames().get(0),
140      serverNames.get(0));
141  }
142
143  @Test
144  public void testAsyncClient() throws Exception {
145    try (AsyncConnection asyncConnect =
146      ConnectionFactory.createAsyncConnection(UTIL.getConfiguration()).get()) {
147      AsyncAdmin asyncAdmin = asyncConnect.getAdmin();
148      CompletableFuture<ClusterMetrics> originFuture = asyncAdmin.getClusterMetrics();
149      CompletableFuture<ClusterMetrics> defaultsFuture =
150        asyncAdmin.getClusterMetrics(EnumSet.allOf(Option.class));
151      ClusterMetrics origin = originFuture.get();
152      ClusterMetrics defaults = defaultsFuture.get();
153      Assert.assertEquals(origin.getHBaseVersion(), defaults.getHBaseVersion());
154      Assert.assertEquals(origin.getClusterId(), defaults.getClusterId());
155      Assert.assertEquals(origin.getHBaseVersion(), defaults.getHBaseVersion());
156      Assert.assertEquals(origin.getClusterId(), defaults.getClusterId());
157      Assert.assertEquals(origin.getAverageLoad(), defaults.getAverageLoad(), 0);
158      Assert.assertEquals(origin.getBackupMasterNames().size(),
159        defaults.getBackupMasterNames().size());
160      Assert.assertEquals(origin.getDeadServerNames().size(), defaults.getDeadServerNames().size());
161      Assert.assertEquals(origin.getRegionCount(), defaults.getRegionCount());
162      Assert.assertEquals(origin.getLiveServerMetrics().size(),
163        defaults.getLiveServerMetrics().size());
164      Assert.assertEquals(origin.getMasterInfoPort(), defaults.getMasterInfoPort());
165      Assert.assertEquals(origin.getServersName().size(), defaults.getServersName().size());
166      origin.getTableRegionStatesCount().forEach(((tableName, regionStatesCount) -> {
167        RegionStatesCount defaultRegionStatesCount =
168          defaults.getTableRegionStatesCount().get(tableName);
169        Assert.assertEquals(defaultRegionStatesCount, regionStatesCount);
170      }));
171    }
172  }
173
174  @Test
175  public void testLiveAndDeadServersStatus() throws Exception {
176    // Count the number of live regionservers
177    List<RegionServerThread> regionserverThreads = CLUSTER.getLiveRegionServerThreads();
178    int numRs = 0;
179    int len = regionserverThreads.size();
180    for (int i = 0; i < len; i++) {
181      if (regionserverThreads.get(i).isAlive()) {
182        numRs++;
183      }
184    }
185    // Depending on the (random) order of unit execution we may run this unit before the
186    // minicluster is fully up and recovered from the RS shutdown done during test init.
187    Waiter.waitFor(CLUSTER.getConfiguration(), 10 * 1000, 100, new Predicate<Exception>() {
188      @Override
189      public boolean evaluate() throws Exception {
190        ClusterMetrics metrics = ADMIN.getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS));
191        Assert.assertNotNull(metrics);
192        return metrics.getRegionCount() > 0;
193      }
194    });
195    // Retrieve live servers and dead servers info.
196    EnumSet<Option> options =
197      EnumSet.of(Option.LIVE_SERVERS, Option.DEAD_SERVERS, Option.SERVERS_NAME);
198    ClusterMetrics metrics = ADMIN.getClusterMetrics(options);
199    Assert.assertNotNull(metrics);
200    // exclude a dead region server
201    Assert.assertEquals(SLAVES - 1, numRs);
202    // live servers = nums of regionservers
203    // By default, HMaster don't carry any regions so it won't report its load.
204    // Hence, it won't be in the server list.
205    Assert.assertEquals(numRs, metrics.getLiveServerMetrics().size());
206    Assert.assertTrue(metrics.getRegionCount() > 0);
207    Assert.assertNotNull(metrics.getDeadServerNames());
208    Assert.assertEquals(1, metrics.getDeadServerNames().size());
209    ServerName deadServerName = metrics.getDeadServerNames().iterator().next();
210    Assert.assertEquals(DEAD.getServerName(), deadServerName);
211    Assert.assertNotNull(metrics.getServersName());
212    Assert.assertEquals(numRs, metrics.getServersName().size());
213  }
214
215  @Test
216  public void testRegionStatesCount() throws Exception {
217    Table table = UTIL.createTable(TABLE_NAME, CF);
218    table.put(new Put(Bytes.toBytes("k1")).addColumn(CF, Bytes.toBytes("q1"), Bytes.toBytes("v1")));
219    table.put(new Put(Bytes.toBytes("k2")).addColumn(CF, Bytes.toBytes("q2"), Bytes.toBytes("v2")));
220    table.put(new Put(Bytes.toBytes("k3")).addColumn(CF, Bytes.toBytes("q3"), Bytes.toBytes("v3")));
221
222    ClusterMetrics metrics = ADMIN.getClusterMetrics();
223    Assert.assertEquals(metrics.getTableRegionStatesCount().size(), 2);
224    Assert.assertEquals(
225      metrics.getTableRegionStatesCount().get(TableName.META_TABLE_NAME).getRegionsInTransition(),
226      0);
227    Assert.assertEquals(
228      metrics.getTableRegionStatesCount().get(TableName.META_TABLE_NAME).getOpenRegions(), 1);
229    Assert.assertEquals(
230      metrics.getTableRegionStatesCount().get(TableName.META_TABLE_NAME).getTotalRegions(), 1);
231    Assert.assertEquals(
232      metrics.getTableRegionStatesCount().get(TableName.META_TABLE_NAME).getClosedRegions(), 0);
233    Assert.assertEquals(
234      metrics.getTableRegionStatesCount().get(TableName.META_TABLE_NAME).getSplitRegions(), 0);
235    Assert.assertEquals(
236      metrics.getTableRegionStatesCount().get(TABLE_NAME).getRegionsInTransition(), 0);
237    Assert.assertEquals(metrics.getTableRegionStatesCount().get(TABLE_NAME).getOpenRegions(), 1);
238    Assert.assertEquals(metrics.getTableRegionStatesCount().get(TABLE_NAME).getTotalRegions(), 1);
239
240    UTIL.deleteTable(TABLE_NAME);
241  }
242
243  @Test
244  public void testRegionStatesWithSplit() throws Exception {
245    int startRowNum = 20;
246    int rowCount = 80;
247    Table table = UTIL.createTable(TABLE_NAME, CF);
248    table.put(new Put(Bytes.toBytes("k1")).addColumn(CF, Bytes.toBytes("q1"), Bytes.toBytes("v1")));
249    table.put(new Put(Bytes.toBytes("k2")).addColumn(CF, Bytes.toBytes("q2"), Bytes.toBytes("v2")));
250
251    insertData(TABLE_NAME, startRowNum, rowCount);
252
253    ClusterMetrics metrics = ADMIN.getClusterMetrics();
254    Assert.assertEquals(metrics.getTableRegionStatesCount().size(), 2);
255    Assert.assertEquals(
256      metrics.getTableRegionStatesCount().get(TableName.META_TABLE_NAME).getRegionsInTransition(),
257      0);
258    Assert.assertEquals(
259      metrics.getTableRegionStatesCount().get(TableName.META_TABLE_NAME).getOpenRegions(), 1);
260    Assert.assertEquals(
261      metrics.getTableRegionStatesCount().get(TableName.META_TABLE_NAME).getTotalRegions(), 1);
262    Assert.assertEquals(
263      metrics.getTableRegionStatesCount().get(TABLE_NAME).getRegionsInTransition(), 0);
264    Assert.assertEquals(metrics.getTableRegionStatesCount().get(TABLE_NAME).getOpenRegions(), 1);
265    Assert.assertEquals(metrics.getTableRegionStatesCount().get(TABLE_NAME).getTotalRegions(), 1);
266
267    int splitRowNum = startRowNum + rowCount / 2;
268    byte[] splitKey = Bytes.toBytes("" + splitRowNum);
269
270    // Split region of the table
271    ADMIN.split(TABLE_NAME, splitKey);
272
273    metrics = ADMIN.getClusterMetrics();
274    Assert.assertEquals(metrics.getTableRegionStatesCount().size(), 2);
275    Assert.assertEquals(
276      metrics.getTableRegionStatesCount().get(TableName.META_TABLE_NAME).getRegionsInTransition(),
277      0);
278    Assert.assertEquals(
279      metrics.getTableRegionStatesCount().get(TableName.META_TABLE_NAME).getOpenRegions(), 1);
280    Assert.assertEquals(
281      metrics.getTableRegionStatesCount().get(TableName.META_TABLE_NAME).getTotalRegions(), 1);
282    Assert.assertEquals(
283      metrics.getTableRegionStatesCount().get(TABLE_NAME).getRegionsInTransition(), 0);
284    Assert.assertEquals(metrics.getTableRegionStatesCount().get(TABLE_NAME).getOpenRegions(), 2);
285    Assert.assertEquals(metrics.getTableRegionStatesCount().get(TABLE_NAME).getTotalRegions(), 3);
286    Assert.assertEquals(metrics.getTableRegionStatesCount().get(TABLE_NAME).getSplitRegions(), 1);
287    Assert.assertEquals(metrics.getTableRegionStatesCount().get(TABLE_NAME).getClosedRegions(), 0);
288
289    UTIL.deleteTable(TABLE_NAME);
290  }
291
292  @Test
293  public void testMasterAndBackupMastersStatus() throws Exception {
294    // get all the master threads
295    List<MasterThread> masterThreads = CLUSTER.getMasterThreads();
296    int numActive = 0;
297    int activeIndex = 0;
298    ServerName activeName = null;
299    HMaster active = null;
300    for (int i = 0; i < masterThreads.size(); i++) {
301      if (masterThreads.get(i).getMaster().isActiveMaster()) {
302        numActive++;
303        activeIndex = i;
304        active = masterThreads.get(activeIndex).getMaster();
305        activeName = active.getServerName();
306      }
307    }
308    Assert.assertNotNull(active);
309    Assert.assertEquals(1, numActive);
310    Assert.assertEquals(MASTERS, masterThreads.size());
311    // Retrieve master and backup masters infos only.
312    EnumSet<Option> options = EnumSet.of(Option.MASTER, Option.BACKUP_MASTERS);
313    ClusterMetrics metrics = ADMIN.getClusterMetrics(options);
314    Assert.assertTrue(metrics.getMasterName().equals(activeName));
315    Assert.assertEquals(MASTERS - 1, metrics.getBackupMasterNames().size());
316  }
317
318  @Test
319  public void testUserMetrics() throws Exception {
320    Configuration conf = UTIL.getConfiguration();
321    // If metrics for users is not enabled, this test doesn't make sense.
322    if (
323      !conf.getBoolean(MetricsUserAggregateFactory.METRIC_USER_ENABLED_CONF,
324        MetricsUserAggregateFactory.DEFAULT_METRIC_USER_ENABLED_CONF)
325    ) {
326      return;
327    }
328    User userFoo = User.createUserForTesting(conf, "FOO_USER_METRIC_TEST", new String[0]);
329    User userBar = User.createUserForTesting(conf, "BAR_USER_METRIC_TEST", new String[0]);
330    User userTest = User.createUserForTesting(conf, "TEST_USER_METRIC_TEST", new String[0]);
331    UTIL.createTable(TABLE_NAME, CF);
332    waitForUsersMetrics(0);
333    long writeMetaMetricBeforeNextuser = getMetaMetrics().getWriteRequestCount();
334    userFoo.runAs(new PrivilegedAction<Void>() {
335      @Override
336      public Void run() {
337        try {
338          doPut();
339        } catch (IOException e) {
340          Assert.fail("Exception:" + e.getMessage());
341        }
342        return null;
343      }
344    });
345    waitForUsersMetrics(1);
346    long writeMetaMetricForUserFoo =
347      getMetaMetrics().getWriteRequestCount() - writeMetaMetricBeforeNextuser;
348    long readMetaMetricBeforeNextuser = getMetaMetrics().getReadRequestCount();
349    userBar.runAs(new PrivilegedAction<Void>() {
350      @Override
351      public Void run() {
352        try {
353          doGet();
354        } catch (IOException e) {
355          Assert.fail("Exception:" + e.getMessage());
356        }
357        return null;
358      }
359    });
360    waitForUsersMetrics(2);
361    long readMetaMetricForUserBar =
362      getMetaMetrics().getReadRequestCount() - readMetaMetricBeforeNextuser;
363    long filteredMetaReqeust = getMetaMetrics().getFilteredReadRequestCount();
364    userTest.runAs(new PrivilegedAction<Void>() {
365      @Override
366      public Void run() {
367        try {
368          Table table = createConnection(UTIL.getConfiguration()).getTable(TABLE_NAME);
369          for (Result result : table.getScanner(new Scan().setFilter(new FilterAllFilter()))) {
370            Assert.fail("Should have filtered all rows");
371          }
372        } catch (IOException e) {
373          Assert.fail("Exception:" + e.getMessage());
374        }
375        return null;
376      }
377    });
378    waitForUsersMetrics(3);
379    long filteredMetaReqeustForTestUser =
380      getMetaMetrics().getFilteredReadRequestCount() - filteredMetaReqeust;
381    Map<byte[], UserMetrics> userMap = ADMIN.getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS))
382      .getLiveServerMetrics().values().iterator().next().getUserMetrics();
383    for (byte[] user : userMap.keySet()) {
384      switch (Bytes.toString(user)) {
385        case "FOO_USER_METRIC_TEST":
386          Assert.assertEquals(1,
387            userMap.get(user).getWriteRequestCount() - writeMetaMetricForUserFoo);
388          break;
389        case "BAR_USER_METRIC_TEST":
390          Assert.assertEquals(1,
391            userMap.get(user).getReadRequestCount() - readMetaMetricForUserBar);
392          Assert.assertEquals(0, userMap.get(user).getWriteRequestCount());
393          break;
394        case "TEST_USER_METRIC_TEST":
395          Assert.assertEquals(1,
396            userMap.get(user).getFilteredReadRequests() - filteredMetaReqeustForTestUser);
397          Assert.assertEquals(0, userMap.get(user).getWriteRequestCount());
398          break;
399        default:
400          // current user
401          Assert.assertEquals(UserProvider.instantiate(conf).getCurrent().getName(),
402            Bytes.toString(user));
403          // Read/write count because of Meta operations
404          Assert.assertTrue(userMap.get(user).getReadRequestCount() > 1);
405          break;
406      }
407    }
408    UTIL.deleteTable(TABLE_NAME);
409  }
410
411  @Test
412  public void testServerTasks() throws Exception {
413    // TaskMonitor is a singleton per VM, so will be shared among all minicluster "servers",
414    // so we only need to look at the first live server's results to find it.
415    final String testTaskName = "TEST TASK";
416    TaskMonitor.get().createStatus(testTaskName).setStatus("Testing 1... 2... 3...");
417    // Of course, first we must trigger regionserver reports.
418    final long now = EnvironmentEdgeManager.currentTime();
419    final long last = now - 1000; // fake a period, or someone might div by zero
420    for (RegionServerThread rs : CLUSTER.getRegionServerThreads()) {
421      ((MyRegionServer) rs.getRegionServer()).tryRegionServerReport(last, now);
422    }
423    // Get status now
424    ClusterMetrics clusterMetrics = ADMIN.getClusterMetrics(EnumSet.of(Option.TASKS));
425    // The test task will be in the master metrics list
426    boolean found = false;
427    for (ServerTask task : clusterMetrics.getMasterTasks()) {
428      if (testTaskName.equals(task.getDescription())) {
429        // Found it
430        found = true;
431        break;
432      }
433    }
434    Assert.assertTrue("Expected task not found in master task list", found);
435    // Get the tasks information (carried in server metrics)
436    found = false;
437    for (ServerMetrics serverMetrics : clusterMetrics.getLiveServerMetrics().values()) {
438      if (serverMetrics.getTasks() != null) {
439        for (ServerTask task : serverMetrics.getTasks()) {
440          if (testTaskName.equals(task.getDescription())) {
441            // Found it
442            found = true;
443            break;
444          }
445        }
446      }
447    }
448    // We will fall through here if getClusterMetrics(TASKS) did not correctly process the
449    // task list.
450    Assert.assertTrue("Expected task not found in server load", found);
451  }
452
453  private RegionMetrics getMetaMetrics() throws IOException {
454    for (ServerMetrics serverMetrics : ADMIN.getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS))
455      .getLiveServerMetrics().values()) {
456      RegionMetrics metaMetrics = serverMetrics.getRegionMetrics()
457        .get(RegionInfoBuilder.FIRST_META_REGIONINFO.getRegionName());
458      if (metaMetrics != null) {
459        return metaMetrics;
460      }
461    }
462    Assert.fail("Should have find meta metrics");
463    return null;
464  }
465
466  private void waitForUsersMetrics(int noOfUsers) throws Exception {
467    // Sleep for metrics to get updated on master
468    Thread.sleep(5000);
469    Waiter.waitFor(CLUSTER.getConfiguration(), 10 * 1000, 100, new Predicate<Exception>() {
470      @Override
471      public boolean evaluate() throws Exception {
472        Map<byte[], UserMetrics> metrics = ADMIN.getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS))
473          .getLiveServerMetrics().values().iterator().next().getUserMetrics();
474        Assert.assertNotNull(metrics);
475        // including current user + noOfUsers
476        return metrics.keySet().size() > noOfUsers;
477      }
478    });
479  }
480
481  private void doPut() throws IOException {
482    Table table = createConnection(UTIL.getConfiguration()).getTable(TABLE_NAME);
483    table.put(new Put(Bytes.toBytes("a")).addColumn(CF, Bytes.toBytes("col1"), Bytes.toBytes("1")));
484
485  }
486
487  private void doGet() throws IOException {
488    Table table = createConnection(UTIL.getConfiguration()).getTable(TABLE_NAME);
489    table.get(new Get(Bytes.toBytes("a")).addColumn(CF, Bytes.toBytes("col1")));
490
491  }
492
493  private Connection createConnection(Configuration conf) throws IOException {
494    User user = UserProvider.instantiate(conf).getCurrent();
495    return ClusterConnectionFactory.createAsyncClusterConnection(conf, null, user).toConnection();
496  }
497
498  @Test
499  public void testOtherStatusInfos() throws Exception {
500    EnumSet<Option> options = EnumSet.of(Option.MASTER_COPROCESSORS, Option.HBASE_VERSION,
501      Option.CLUSTER_ID, Option.BALANCER_ON);
502    ClusterMetrics metrics = ADMIN.getClusterMetrics(options);
503    Assert.assertEquals(1, metrics.getMasterCoprocessorNames().size());
504    Assert.assertNotNull(metrics.getHBaseVersion());
505    Assert.assertNotNull(metrics.getClusterId());
506    Assert.assertTrue(metrics.getAverageLoad() == 0.0);
507    Assert.assertNotNull(metrics.getBalancerOn());
508  }
509
510  @AfterClass
511  public static void tearDownAfterClass() throws Exception {
512    if (ADMIN != null) {
513      ADMIN.close();
514    }
515    UTIL.shutdownMiniCluster();
516  }
517
518  @Test
519  public void testObserver() throws IOException {
520    int preCount = MyObserver.PRE_COUNT.get();
521    int postCount = MyObserver.POST_COUNT.get();
522    Assert.assertTrue(ADMIN.getClusterMetrics().getMasterCoprocessorNames().stream()
523      .anyMatch(s -> s.equals(MyObserver.class.getSimpleName())));
524    Assert.assertEquals(preCount + 1, MyObserver.PRE_COUNT.get());
525    Assert.assertEquals(postCount + 1, MyObserver.POST_COUNT.get());
526  }
527
528  private static void insertData(final TableName tableName, int startRow, int rowCount)
529    throws IOException {
530    Table t = UTIL.getConnection().getTable(tableName);
531    Put p;
532    for (int i = 0; i < rowCount; i++) {
533      p = new Put(Bytes.toBytes("" + (startRow + i)));
534      p.addColumn(CF, Bytes.toBytes("val1"), Bytes.toBytes(i));
535      t.put(p);
536    }
537  }
538
539  public static class MyObserver implements MasterCoprocessor, MasterObserver {
540    private static final AtomicInteger PRE_COUNT = new AtomicInteger(0);
541    private static final AtomicInteger POST_COUNT = new AtomicInteger(0);
542
543    @Override
544    public Optional<MasterObserver> getMasterObserver() {
545      return Optional.of(this);
546    }
547
548    @Override
549    public void preGetClusterMetrics(ObserverContext<MasterCoprocessorEnvironment> ctx)
550      throws IOException {
551      PRE_COUNT.incrementAndGet();
552    }
553
554    @Override
555    public void postGetClusterMetrics(ObserverContext<MasterCoprocessorEnvironment> ctx,
556      ClusterMetrics metrics) throws IOException {
557      POST_COUNT.incrementAndGet();
558    }
559  }
560}