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.master;
019
020import java.io.IOException;
021import java.util.AbstractMap.SimpleImmutableEntry;
022import java.util.Collections;
023import java.util.HashMap;
024import java.util.List;
025import java.util.Map;
026import java.util.Map.Entry;
027import org.apache.commons.lang3.StringUtils;
028import org.apache.hadoop.hbase.ServerName;
029import org.apache.hadoop.hbase.TableName;
030import org.apache.hadoop.hbase.client.MasterSwitchType;
031import org.apache.hadoop.hbase.client.RegionInfo;
032import org.apache.hadoop.hbase.client.TableDescriptor;
033import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;
034import org.apache.hadoop.hbase.procedure2.Procedure;
035import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
036import org.apache.hadoop.hbase.quotas.MasterQuotaManager;
037import org.apache.hadoop.hbase.quotas.QuotaObserverChore;
038import org.apache.hadoop.hbase.quotas.QuotaUtil;
039import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshot;
040import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
041import org.apache.hadoop.hbase.util.PairOfSameType;
042import org.apache.hadoop.hbase.zookeeper.ZKWatcher;
043import org.apache.yetus.audience.InterfaceAudience;
044
045/**
046 * Impl for exposing HMaster Information through JMX
047 */
048@InterfaceAudience.Private
049public class MetricsMasterWrapperImpl implements MetricsMasterWrapper {
050
051  private final HMaster master;
052
053  public MetricsMasterWrapperImpl(final HMaster master) {
054    this.master = master;
055  }
056
057  @Override
058  public double getAverageLoad() {
059    return master.getAverageLoad();
060  }
061
062  @Override
063  public long getSplitPlanCount() {
064    if (master.getRegionNormalizerManager() == null) {
065      return 0;
066    }
067    return master.getRegionNormalizerManager().getSplitPlanCount();
068  }
069
070  @Override
071  public long getMergePlanCount() {
072    if (master.getRegionNormalizerManager() == null) {
073      return 0;
074    }
075    return master.getRegionNormalizerManager().getMergePlanCount();
076  }
077
078  @Override
079  public long getMasterInitializationTime() {
080    return master.getMasterFinishedInitializationTime();
081  }
082
083  @Override
084  public String getClusterId() {
085    return master.getClusterId();
086  }
087
088  @Override
089  public String getZookeeperQuorum() {
090    ZKWatcher zk = master.getZooKeeper();
091    if (zk == null) {
092      return "";
093    }
094    return zk.getQuorum();
095  }
096
097  @Override
098  public String[] getCoprocessors() {
099    return master.getMasterCoprocessors();
100  }
101
102  @Override
103  public long getStartTime() {
104    return master.getMasterStartTime();
105  }
106
107  @Override
108  public long getActiveTime() {
109    return master.getMasterActiveTime();
110  }
111
112  @Override
113  public String getRegionServers() {
114    ServerManager serverManager = this.master.getServerManager();
115    if (serverManager == null) {
116      return "";
117    }
118    return StringUtils.join(serverManager.getOnlineServers().keySet(), ";");
119  }
120
121  @Override
122  public int getNumRegionServers() {
123    ServerManager serverManager = this.master.getServerManager();
124    if (serverManager == null) {
125      return 0;
126    }
127    return serverManager.getOnlineServers().size();
128  }
129
130  @Override
131  public String getDeadRegionServers() {
132    ServerManager serverManager = this.master.getServerManager();
133    if (serverManager == null) {
134      return "";
135    }
136    return StringUtils.join(serverManager.getDeadServers().copyServerNames(), ";");
137  }
138
139  @Override
140  public int getNumDeadRegionServers() {
141    ServerManager serverManager = this.master.getServerManager();
142    if (serverManager == null) {
143      return 0;
144    }
145    return serverManager.getDeadServers().size();
146  }
147
148  @Override
149  public boolean isRunning() {
150    return !(master.isStopped() || master.isStopping());
151  }
152
153  @Override
154  public String getDrainingRegionServers() {
155    ServerManager serverManager = this.master.getServerManager();
156    if (serverManager == null) {
157      return "";
158    }
159    return StringUtils.join(serverManager.getDrainingServersList(), ";");
160  }
161
162  @Override
163  public int getNumDrainingRegionServers() {
164    ServerManager serverManager = this.master.getServerManager();
165    if (serverManager == null) {
166      return 0;
167    }
168    return serverManager.getDrainingServersList().size();
169  }
170
171  @Override
172  public String getServerName() {
173    ServerName serverName = master.getServerName();
174    if (serverName == null) {
175      return "";
176    }
177    return serverName.getServerName();
178  }
179
180  @Override
181  public boolean getIsActiveMaster() {
182    return master.isActiveMaster();
183  }
184
185  @Override
186  public long getNumWALFiles() {
187    return master.getNumWALFiles();
188  }
189
190  @Override
191  public Map<String, Long> getOldestProcedureAgeByType() {
192    ProcedureExecutor<MasterProcedureEnv> procedureExecutor = master.getMasterProcedureExecutor();
193    if (procedureExecutor == null) {
194      return Collections.emptyMap();
195    }
196    long now = EnvironmentEdgeManager.currentTime();
197    Map<String, Long> oldestProcedureAgeByType = new HashMap<>();
198    for (Procedure<MasterProcedureEnv> procedure : procedureExecutor.getProcedures()) {
199      if (!procedure.isFinished()) {
200        long age = Math.max(0L, now - procedure.getSubmittedTime());
201        oldestProcedureAgeByType.merge(procedure.getClass().getSimpleName(), age, Math::max);
202      }
203    }
204    return oldestProcedureAgeByType;
205  }
206
207  @Override
208  public Map<String, Entry<Long, Long>> getTableSpaceUtilization() {
209    if (master == null) {
210      return Collections.emptyMap();
211    }
212    QuotaObserverChore quotaChore = master.getQuotaObserverChore();
213    if (quotaChore == null) {
214      return Collections.emptyMap();
215    }
216    Map<TableName, SpaceQuotaSnapshot> tableSnapshots = quotaChore.getTableQuotaSnapshots();
217    Map<String, Entry<Long, Long>> convertedData = new HashMap<>();
218    for (Entry<TableName, SpaceQuotaSnapshot> entry : tableSnapshots.entrySet()) {
219      convertedData.put(entry.getKey().toString(), convertSnapshot(entry.getValue()));
220    }
221    return convertedData;
222  }
223
224  @Override
225  public Map<String, Entry<Long, Long>> getNamespaceSpaceUtilization() {
226    QuotaObserverChore quotaChore = master.getQuotaObserverChore();
227    if (quotaChore == null) {
228      return Collections.emptyMap();
229    }
230    Map<String, SpaceQuotaSnapshot> namespaceSnapshots = quotaChore.getNamespaceQuotaSnapshots();
231    Map<String, Entry<Long, Long>> convertedData = new HashMap<>();
232    for (Entry<String, SpaceQuotaSnapshot> entry : namespaceSnapshots.entrySet()) {
233      convertedData.put(entry.getKey(), convertSnapshot(entry.getValue()));
234    }
235    return convertedData;
236  }
237
238  Entry<Long, Long> convertSnapshot(SpaceQuotaSnapshot snapshot) {
239    return new SimpleImmutableEntry<Long, Long>(snapshot.getUsage(), snapshot.getLimit());
240  }
241
242  @Override
243  public PairOfSameType<Integer> getRegionCounts() {
244    try {
245      if (!master.isInitialized()) {
246        return new PairOfSameType<>(0, 0);
247      }
248      Integer onlineRegionCount = 0;
249      Integer offlineRegionCount = 0;
250
251      List<TableDescriptor> descriptors = master.listTableDescriptors(null, null, null, false);
252
253      for (TableDescriptor htDesc : descriptors) {
254        TableName tableName = htDesc.getTableName();
255        Map<RegionState.State, List<RegionInfo>> tableRegions =
256          master.getAssignmentManager().getRegionStates().getRegionByStateOfTable(tableName);
257        onlineRegionCount += tableRegions.get(RegionState.State.OPEN).size();
258        offlineRegionCount += tableRegions.get(RegionState.State.OFFLINE).size();
259      }
260      return new PairOfSameType<>(onlineRegionCount, offlineRegionCount);
261    } catch (IOException e) {
262      return new PairOfSameType<>(0, 0);
263    }
264  }
265
266  @Override
267  public long getOldWALsDirSize() {
268    if (master == null || !master.isInitialized()) {
269      return 0;
270    }
271    return master.getMasterWalManager().getOldWALsDirSize();
272  }
273
274  @Override
275  public Map<String, Integer> getSwitchStates() {
276    if (!master.isActiveMaster() || !master.isInitialized()) {
277      return Collections.emptyMap();
278    }
279    Map<String, Integer> states = new HashMap<>();
280    states.put(MetricsMasterSource.BALANCER_ENABLED_NAME, master.isBalancerOn() ? 1 : 0);
281    states.put(MetricsMasterSource.NORMALIZER_ENABLED_NAME, master.isNormalizerOn() ? 1 : 0);
282    states.put(MetricsMasterSource.SPLIT_ENABLED_NAME,
283      master.isSplitOrMergeEnabled(MasterSwitchType.SPLIT) ? 1 : 0);
284    states.put(MetricsMasterSource.MERGE_ENABLED_NAME,
285      master.isSplitOrMergeEnabled(MasterSwitchType.MERGE) ? 1 : 0);
286    states.put(MetricsMasterSource.CLEANER_CHORE_ENABLED_NAME,
287      master.isCleanerChoreEnabled() ? 1 : 0);
288    states.put(MetricsMasterSource.CATALOG_JANITOR_ENABLED_NAME,
289      master.isCatalogJanitorEnabled() ? 1 : 0);
290    states.put(MetricsMasterSource.SNAPSHOT_CLEANUP_ENABLED_NAME,
291      master.snapshotCleanupStateStore.get() ? 1 : 0);
292    states.put(MetricsMasterSource.REPLICATION_PEER_MODIFICATION_ENABLED_NAME,
293      master.isReplicationPeerModificationEnabled() ? 1 : 0);
294    MasterQuotaManager quotaManager = master.getMasterQuotaManager();
295    if (quotaManager != null) {
296      states.put(MetricsMasterSource.RPC_THROTTLE_ENABLED_NAME,
297        quotaManager.isRpcThrottleEnabled() ? 1 : 0);
298    } else if (!QuotaUtil.isQuotaEnabled(master.getConfiguration())) {
299      states.put(MetricsMasterSource.RPC_THROTTLE_ENABLED_NAME, 0);
300    }
301    return states;
302  }
303}