HBASE-26474 Implement connection-level attributes (addendum)
[hbase.git] / hbase-client / src / main / java / org / apache / hadoop / hbase / ClusterMetricsBuilder.java
blob493fe71b8b0f321f09bb6a3f70679451f0d44f72
1 /**
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 package org.apache.hadoop.hbase;
22 import edu.umd.cs.findbugs.annotations.Nullable;
23 import java.util.Collections;
24 import java.util.EnumSet;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.TreeMap;
28 import java.util.stream.Collectors;
30 import org.apache.hadoop.hbase.client.RegionStatesCount;
31 import org.apache.hadoop.hbase.master.RegionState;
32 import org.apache.yetus.audience.InterfaceAudience;
34 import org.apache.hbase.thirdparty.com.google.common.base.Preconditions;
35 import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations;
36 import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
37 import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos;
38 import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.Option;
39 import org.apache.hadoop.hbase.shaded.protobuf.generated.FSProtos;
40 import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
42 @InterfaceAudience.Private
43 public final class ClusterMetricsBuilder {
45 public static ClusterStatusProtos.ClusterStatus toClusterStatus(ClusterMetrics metrics) {
46 ClusterStatusProtos.ClusterStatus.Builder builder
47 = ClusterStatusProtos.ClusterStatus.newBuilder()
48 .addAllBackupMasters(metrics.getBackupMasterNames().stream()
49 .map(ProtobufUtil::toServerName).collect(Collectors.toList()))
50 .addAllDeadServers(metrics.getDeadServerNames().stream()
51 .map(ProtobufUtil::toServerName).collect(Collectors.toList()))
52 .addAllLiveServers(metrics.getLiveServerMetrics().entrySet().stream()
53 .map(s -> ClusterStatusProtos.LiveServerInfo
54 .newBuilder()
55 .setServer(ProtobufUtil.toServerName(s.getKey()))
56 .setServerLoad(ServerMetricsBuilder.toServerLoad(s.getValue()))
57 .build())
58 .collect(Collectors.toList()))
59 .addAllMasterCoprocessors(metrics.getMasterCoprocessorNames().stream()
60 .map(n -> HBaseProtos.Coprocessor.newBuilder().setName(n).build())
61 .collect(Collectors.toList()))
62 .addAllRegionsInTransition(metrics.getRegionStatesInTransition().stream()
63 .map(r -> ClusterStatusProtos.RegionInTransition
64 .newBuilder()
65 .setSpec(HBaseProtos.RegionSpecifier
66 .newBuilder()
67 .setType(HBaseProtos.RegionSpecifier.RegionSpecifierType.REGION_NAME)
68 .setValue(UnsafeByteOperations.unsafeWrap(r.getRegion().getRegionName()))
69 .build())
70 .setRegionState(r.convert())
71 .build())
72 .collect(Collectors.toList()))
73 .setMasterInfoPort(metrics.getMasterInfoPort())
74 .addAllServersName(metrics.getServersName().stream().map(ProtobufUtil::toServerName)
75 .collect(Collectors.toList()))
76 .addAllTableRegionStatesCount(metrics.getTableRegionStatesCount().entrySet().stream()
77 .map(status ->
78 ClusterStatusProtos.TableRegionStatesCount.newBuilder()
79 .setTableName(ProtobufUtil.toProtoTableName((status.getKey())))
80 .setRegionStatesCount(ProtobufUtil.toTableRegionStatesCount(status.getValue()))
81 .build())
82 .collect(Collectors.toList()));
83 if (metrics.getMasterName() != null) {
84 builder.setMaster(ProtobufUtil.toServerName((metrics.getMasterName())));
86 if (metrics.getBalancerOn() != null) {
87 builder.setBalancerOn(metrics.getBalancerOn());
89 if (metrics.getClusterId() != null) {
90 builder.setClusterId(new ClusterId(metrics.getClusterId()).convert());
92 if (metrics.getHBaseVersion() != null) {
93 builder.setHbaseVersion(
94 FSProtos.HBaseVersionFileContent.newBuilder()
95 .setVersion(metrics.getHBaseVersion()));
97 return builder.build();
100 public static ClusterMetrics toClusterMetrics(
101 ClusterStatusProtos.ClusterStatus proto) {
102 ClusterMetricsBuilder builder = ClusterMetricsBuilder.newBuilder();
103 builder.setLiveServerMetrics(proto.getLiveServersList().stream()
104 .collect(Collectors.toMap(e -> ProtobufUtil.toServerName(e.getServer()),
105 ServerMetricsBuilder::toServerMetrics)))
106 .setDeadServerNames(proto.getDeadServersList().stream()
107 .map(ProtobufUtil::toServerName)
108 .collect(Collectors.toList()))
109 .setBackerMasterNames(proto.getBackupMastersList().stream()
110 .map(ProtobufUtil::toServerName)
111 .collect(Collectors.toList()))
112 .setRegionsInTransition(proto.getRegionsInTransitionList().stream()
113 .map(ClusterStatusProtos.RegionInTransition::getRegionState)
114 .map(RegionState::convert)
115 .collect(Collectors.toList()))
116 .setMasterCoprocessorNames(proto.getMasterCoprocessorsList().stream()
117 .map(HBaseProtos.Coprocessor::getName)
118 .collect(Collectors.toList()))
119 .setServerNames(proto.getServersNameList().stream().map(ProtobufUtil::toServerName)
120 .collect(Collectors.toList()))
121 .setTableRegionStatesCount(
122 proto.getTableRegionStatesCountList().stream()
123 .collect(Collectors.toMap(
124 e -> ProtobufUtil.toTableName(e.getTableName()),
125 e -> ProtobufUtil.toTableRegionStatesCount(e.getRegionStatesCount()))));
126 if (proto.hasClusterId()) {
127 builder.setClusterId(ClusterId.convert(proto.getClusterId()).toString());
130 if (proto.hasHbaseVersion()) {
131 builder.setHBaseVersion(proto.getHbaseVersion().getVersion());
134 if (proto.hasMaster()) {
135 builder.setMasterName(ProtobufUtil.toServerName(proto.getMaster()));
138 if (proto.hasBalancerOn()) {
139 builder.setBalancerOn(proto.getBalancerOn());
142 if (proto.hasMasterInfoPort()) {
143 builder.setMasterInfoPort(proto.getMasterInfoPort());
145 return builder.build();
149 * Convert ClusterStatusProtos.Option to ClusterMetrics.Option
150 * @param option a ClusterStatusProtos.Option
151 * @return converted ClusterMetrics.Option
153 public static ClusterMetrics.Option toOption(ClusterStatusProtos.Option option) {
154 switch (option) {
155 case HBASE_VERSION: return ClusterMetrics.Option.HBASE_VERSION;
156 case LIVE_SERVERS: return ClusterMetrics.Option.LIVE_SERVERS;
157 case DEAD_SERVERS: return ClusterMetrics.Option.DEAD_SERVERS;
158 case REGIONS_IN_TRANSITION: return ClusterMetrics.Option.REGIONS_IN_TRANSITION;
159 case CLUSTER_ID: return ClusterMetrics.Option.CLUSTER_ID;
160 case MASTER_COPROCESSORS: return ClusterMetrics.Option.MASTER_COPROCESSORS;
161 case MASTER: return ClusterMetrics.Option.MASTER;
162 case BACKUP_MASTERS: return ClusterMetrics.Option.BACKUP_MASTERS;
163 case BALANCER_ON: return ClusterMetrics.Option.BALANCER_ON;
164 case SERVERS_NAME: return ClusterMetrics.Option.SERVERS_NAME;
165 case MASTER_INFO_PORT: return ClusterMetrics.Option.MASTER_INFO_PORT;
166 case TABLE_TO_REGIONS_COUNT: return ClusterMetrics.Option.TABLE_TO_REGIONS_COUNT;
167 // should not reach here
168 default: throw new IllegalArgumentException("Invalid option: " + option);
173 * Convert ClusterMetrics.Option to ClusterStatusProtos.Option
174 * @param option a ClusterMetrics.Option
175 * @return converted ClusterStatusProtos.Option
177 public static ClusterStatusProtos.Option toOption(ClusterMetrics.Option option) {
178 switch (option) {
179 case HBASE_VERSION: return ClusterStatusProtos.Option.HBASE_VERSION;
180 case LIVE_SERVERS: return ClusterStatusProtos.Option.LIVE_SERVERS;
181 case DEAD_SERVERS: return ClusterStatusProtos.Option.DEAD_SERVERS;
182 case REGIONS_IN_TRANSITION: return ClusterStatusProtos.Option.REGIONS_IN_TRANSITION;
183 case CLUSTER_ID: return ClusterStatusProtos.Option.CLUSTER_ID;
184 case MASTER_COPROCESSORS: return ClusterStatusProtos.Option.MASTER_COPROCESSORS;
185 case MASTER: return ClusterStatusProtos.Option.MASTER;
186 case BACKUP_MASTERS: return ClusterStatusProtos.Option.BACKUP_MASTERS;
187 case BALANCER_ON: return ClusterStatusProtos.Option.BALANCER_ON;
188 case SERVERS_NAME: return Option.SERVERS_NAME;
189 case MASTER_INFO_PORT: return ClusterStatusProtos.Option.MASTER_INFO_PORT;
190 case TABLE_TO_REGIONS_COUNT: return ClusterStatusProtos.Option.TABLE_TO_REGIONS_COUNT;
191 // should not reach here
192 default: throw new IllegalArgumentException("Invalid option: " + option);
197 * Convert a list of ClusterStatusProtos.Option to an enum set of ClusterMetrics.Option
198 * @param options the pb options
199 * @return an enum set of ClusterMetrics.Option
201 public static EnumSet<ClusterMetrics.Option> toOptions(List<ClusterStatusProtos.Option> options) {
202 return options.stream().map(ClusterMetricsBuilder::toOption)
203 .collect(Collectors.toCollection(() -> EnumSet.noneOf(ClusterMetrics.Option.class)));
207 * Convert an enum set of ClusterMetrics.Option to a list of ClusterStatusProtos.Option
208 * @param options the ClusterMetrics options
209 * @return a list of ClusterStatusProtos.Option
211 public static List<ClusterStatusProtos.Option> toOptions(EnumSet<ClusterMetrics.Option> options) {
212 return options.stream().map(ClusterMetricsBuilder::toOption).collect(Collectors.toList());
215 public static ClusterMetricsBuilder newBuilder() {
216 return new ClusterMetricsBuilder();
218 @Nullable
219 private String hbaseVersion;
220 private List<ServerName> deadServerNames = Collections.emptyList();
221 private Map<ServerName, ServerMetrics> liveServerMetrics = new TreeMap<>();
222 @Nullable
223 private ServerName masterName;
224 private List<ServerName> backupMasterNames = Collections.emptyList();
225 private List<RegionState> regionsInTransition = Collections.emptyList();
226 @Nullable
227 private String clusterId;
228 private List<String> masterCoprocessorNames = Collections.emptyList();
229 @Nullable
230 private Boolean balancerOn;
231 private int masterInfoPort;
232 private List<ServerName> serversName = Collections.emptyList();
233 private Map<TableName, RegionStatesCount> tableRegionStatesCount = Collections.emptyMap();
235 private ClusterMetricsBuilder() {
237 public ClusterMetricsBuilder setHBaseVersion(String value) {
238 this.hbaseVersion = value;
239 return this;
241 public ClusterMetricsBuilder setDeadServerNames(List<ServerName> value) {
242 this.deadServerNames = value;
243 return this;
246 public ClusterMetricsBuilder setLiveServerMetrics(Map<ServerName, ServerMetrics> value) {
247 liveServerMetrics.putAll(value);
248 return this;
251 public ClusterMetricsBuilder setMasterName(ServerName value) {
252 this.masterName = value;
253 return this;
255 public ClusterMetricsBuilder setBackerMasterNames(List<ServerName> value) {
256 this.backupMasterNames = value;
257 return this;
259 public ClusterMetricsBuilder setRegionsInTransition(List<RegionState> value) {
260 this.regionsInTransition = value;
261 return this;
263 public ClusterMetricsBuilder setClusterId(String value) {
264 this.clusterId = value;
265 return this;
267 public ClusterMetricsBuilder setMasterCoprocessorNames(List<String> value) {
268 this.masterCoprocessorNames = value;
269 return this;
271 public ClusterMetricsBuilder setBalancerOn(@Nullable Boolean value) {
272 this.balancerOn = value;
273 return this;
275 public ClusterMetricsBuilder setMasterInfoPort(int value) {
276 this.masterInfoPort = value;
277 return this;
279 public ClusterMetricsBuilder setServerNames(List<ServerName> serversName) {
280 this.serversName = serversName;
281 return this;
284 public ClusterMetricsBuilder setTableRegionStatesCount(
285 Map<TableName, RegionStatesCount> tableRegionStatesCount) {
286 this.tableRegionStatesCount = tableRegionStatesCount;
287 return this;
290 public ClusterMetrics build() {
291 return new ClusterMetricsImpl(
292 hbaseVersion,
293 deadServerNames,
294 liveServerMetrics,
295 masterName,
296 backupMasterNames,
297 regionsInTransition,
298 clusterId,
299 masterCoprocessorNames,
300 balancerOn,
301 masterInfoPort,
302 serversName,
303 tableRegionStatesCount
306 private static class ClusterMetricsImpl implements ClusterMetrics {
307 @Nullable
308 private final String hbaseVersion;
309 private final List<ServerName> deadServerNames;
310 private final Map<ServerName, ServerMetrics> liveServerMetrics;
311 @Nullable
312 private final ServerName masterName;
313 private final List<ServerName> backupMasterNames;
314 private final List<RegionState> regionsInTransition;
315 @Nullable
316 private final String clusterId;
317 private final List<String> masterCoprocessorNames;
318 @Nullable
319 private final Boolean balancerOn;
320 private final int masterInfoPort;
321 private final List<ServerName> serversName;
322 private final Map<TableName, RegionStatesCount> tableRegionStatesCount;
324 ClusterMetricsImpl(String hbaseVersion, List<ServerName> deadServerNames,
325 Map<ServerName, ServerMetrics> liveServerMetrics,
326 ServerName masterName,
327 List<ServerName> backupMasterNames,
328 List<RegionState> regionsInTransition,
329 String clusterId,
330 List<String> masterCoprocessorNames,
331 Boolean balancerOn,
332 int masterInfoPort,
333 List<ServerName> serversName,
334 Map<TableName, RegionStatesCount> tableRegionStatesCount) {
335 this.hbaseVersion = hbaseVersion;
336 this.deadServerNames = Preconditions.checkNotNull(deadServerNames);
337 this.liveServerMetrics = Preconditions.checkNotNull(liveServerMetrics);
338 this.masterName = masterName;
339 this.backupMasterNames = Preconditions.checkNotNull(backupMasterNames);
340 this.regionsInTransition = Preconditions.checkNotNull(regionsInTransition);
341 this.clusterId = clusterId;
342 this.masterCoprocessorNames = Preconditions.checkNotNull(masterCoprocessorNames);
343 this.balancerOn = balancerOn;
344 this.masterInfoPort = masterInfoPort;
345 this.serversName = serversName;
346 this.tableRegionStatesCount = Preconditions.checkNotNull(tableRegionStatesCount);
349 @Override
350 public String getHBaseVersion() {
351 return hbaseVersion;
354 @Override
355 public List<ServerName> getDeadServerNames() {
356 return Collections.unmodifiableList(deadServerNames);
359 @Override
360 public Map<ServerName, ServerMetrics> getLiveServerMetrics() {
361 return Collections.unmodifiableMap(liveServerMetrics);
364 @Override
365 public ServerName getMasterName() {
366 return masterName;
369 @Override
370 public List<ServerName> getBackupMasterNames() {
371 return Collections.unmodifiableList(backupMasterNames);
374 @Override
375 public List<RegionState> getRegionStatesInTransition() {
376 return Collections.unmodifiableList(regionsInTransition);
379 @Override
380 public String getClusterId() {
381 return clusterId;
384 @Override
385 public List<String> getMasterCoprocessorNames() {
386 return Collections.unmodifiableList(masterCoprocessorNames);
389 @Override
390 public Boolean getBalancerOn() {
391 return balancerOn;
394 @Override
395 public int getMasterInfoPort() {
396 return masterInfoPort;
399 @Override
400 public List<ServerName> getServersName() {
401 return Collections.unmodifiableList(serversName);
404 @Override
405 public Map<TableName, RegionStatesCount> getTableRegionStatesCount() {
406 return Collections.unmodifiableMap(tableRegionStatesCount);
409 @Override
410 public String toString() {
411 StringBuilder sb = new StringBuilder(1024);
412 sb.append("Master: " + getMasterName());
414 int backupMastersSize = getBackupMasterNames().size();
415 sb.append("\nNumber of backup masters: " + backupMastersSize);
416 if (backupMastersSize > 0) {
417 for (ServerName serverName: getBackupMasterNames()) {
418 sb.append("\n " + serverName);
422 int serversSize = getLiveServerMetrics().size();
423 int serversNameSize = getServersName().size();
424 sb.append("\nNumber of live region servers: "
425 + (serversSize > 0 ? serversSize : serversNameSize));
426 if (serversSize > 0) {
427 for (ServerName serverName : getLiveServerMetrics().keySet()) {
428 sb.append("\n " + serverName.getServerName());
430 } else if (serversNameSize > 0) {
431 for (ServerName serverName : getServersName()) {
432 sb.append("\n " + serverName.getServerName());
436 int deadServerSize = getDeadServerNames().size();
437 sb.append("\nNumber of dead region servers: " + deadServerSize);
438 if (deadServerSize > 0) {
439 for (ServerName serverName : getDeadServerNames()) {
440 sb.append("\n " + serverName);
444 sb.append("\nAverage load: " + getAverageLoad());
445 sb.append("\nNumber of requests: " + getRequestCount());
446 sb.append("\nNumber of regions: " + getRegionCount());
448 int ritSize = getRegionStatesInTransition().size();
449 sb.append("\nNumber of regions in transition: " + ritSize);
450 if (ritSize > 0) {
451 for (RegionState state : getRegionStatesInTransition()) {
452 sb.append("\n " + state.toDescriptiveString());
455 return sb.toString();