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
;
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
55 .setServer(ProtobufUtil
.toServerName(s
.getKey()))
56 .setServerLoad(ServerMetricsBuilder
.toServerLoad(s
.getValue()))
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
65 .setSpec(HBaseProtos
.RegionSpecifier
67 .setType(HBaseProtos
.RegionSpecifier
.RegionSpecifierType
.REGION_NAME
)
68 .setValue(UnsafeByteOperations
.unsafeWrap(r
.getRegion().getRegionName()))
70 .setRegionState(r
.convert())
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()
78 ClusterStatusProtos
.TableRegionStatesCount
.newBuilder()
79 .setTableName(ProtobufUtil
.toProtoTableName((status
.getKey())))
80 .setRegionStatesCount(ProtobufUtil
.toTableRegionStatesCount(status
.getValue()))
82 .collect(Collectors
.toList()));
83 if (metrics
.getMasterName() != null) {
84 builder
.setMaster(ProtobufUtil
.toServerName((metrics
.getMasterName())));
86 if (metrics
.getMasterTasks() != null) {
87 builder
.addAllMasterTasks(metrics
.getMasterTasks().stream()
88 .map(t
-> ProtobufUtil
.toServerTask(t
)).collect(Collectors
.toList()));
90 if (metrics
.getBalancerOn() != null) {
91 builder
.setBalancerOn(metrics
.getBalancerOn());
93 if (metrics
.getClusterId() != null) {
94 builder
.setClusterId(new ClusterId(metrics
.getClusterId()).convert());
96 if (metrics
.getHBaseVersion() != null) {
97 builder
.setHbaseVersion(
98 FSProtos
.HBaseVersionFileContent
.newBuilder()
99 .setVersion(metrics
.getHBaseVersion()));
101 return builder
.build();
104 public static ClusterMetrics
toClusterMetrics(
105 ClusterStatusProtos
.ClusterStatus proto
) {
106 ClusterMetricsBuilder builder
= ClusterMetricsBuilder
.newBuilder();
107 builder
.setLiveServerMetrics(proto
.getLiveServersList().stream()
108 .collect(Collectors
.toMap(e
-> ProtobufUtil
.toServerName(e
.getServer()),
109 ServerMetricsBuilder
::toServerMetrics
)))
110 .setDeadServerNames(proto
.getDeadServersList().stream()
111 .map(ProtobufUtil
::toServerName
)
112 .collect(Collectors
.toList()))
113 .setBackerMasterNames(proto
.getBackupMastersList().stream()
114 .map(ProtobufUtil
::toServerName
)
115 .collect(Collectors
.toList()))
116 .setRegionsInTransition(proto
.getRegionsInTransitionList().stream()
117 .map(ClusterStatusProtos
.RegionInTransition
::getRegionState
)
118 .map(RegionState
::convert
)
119 .collect(Collectors
.toList()))
120 .setMasterCoprocessorNames(proto
.getMasterCoprocessorsList().stream()
121 .map(HBaseProtos
.Coprocessor
::getName
)
122 .collect(Collectors
.toList()))
123 .setServerNames(proto
.getServersNameList().stream().map(ProtobufUtil
::toServerName
)
124 .collect(Collectors
.toList()))
125 .setTableRegionStatesCount(
126 proto
.getTableRegionStatesCountList().stream()
127 .collect(Collectors
.toMap(
128 e
-> ProtobufUtil
.toTableName(e
.getTableName()),
129 e
-> ProtobufUtil
.toTableRegionStatesCount(e
.getRegionStatesCount()))))
130 .setMasterTasks(proto
.getMasterTasksList().stream()
131 .map(t
-> ProtobufUtil
.getServerTask(t
)).collect(Collectors
.toList()));
132 if (proto
.hasClusterId()) {
133 builder
.setClusterId(ClusterId
.convert(proto
.getClusterId()).toString());
136 if (proto
.hasHbaseVersion()) {
137 builder
.setHBaseVersion(proto
.getHbaseVersion().getVersion());
140 if (proto
.hasMaster()) {
141 builder
.setMasterName(ProtobufUtil
.toServerName(proto
.getMaster()));
144 if (proto
.hasBalancerOn()) {
145 builder
.setBalancerOn(proto
.getBalancerOn());
148 if (proto
.hasMasterInfoPort()) {
149 builder
.setMasterInfoPort(proto
.getMasterInfoPort());
151 return builder
.build();
155 * Convert ClusterStatusProtos.Option to ClusterMetrics.Option
156 * @param option a ClusterStatusProtos.Option
157 * @return converted ClusterMetrics.Option
159 public static ClusterMetrics
.Option
toOption(ClusterStatusProtos
.Option option
) {
161 case HBASE_VERSION
: return ClusterMetrics
.Option
.HBASE_VERSION
;
162 case LIVE_SERVERS
: return ClusterMetrics
.Option
.LIVE_SERVERS
;
163 case DEAD_SERVERS
: return ClusterMetrics
.Option
.DEAD_SERVERS
;
164 case REGIONS_IN_TRANSITION
: return ClusterMetrics
.Option
.REGIONS_IN_TRANSITION
;
165 case CLUSTER_ID
: return ClusterMetrics
.Option
.CLUSTER_ID
;
166 case MASTER_COPROCESSORS
: return ClusterMetrics
.Option
.MASTER_COPROCESSORS
;
167 case MASTER
: return ClusterMetrics
.Option
.MASTER
;
168 case BACKUP_MASTERS
: return ClusterMetrics
.Option
.BACKUP_MASTERS
;
169 case BALANCER_ON
: return ClusterMetrics
.Option
.BALANCER_ON
;
170 case SERVERS_NAME
: return ClusterMetrics
.Option
.SERVERS_NAME
;
171 case MASTER_INFO_PORT
: return ClusterMetrics
.Option
.MASTER_INFO_PORT
;
172 case TABLE_TO_REGIONS_COUNT
: return ClusterMetrics
.Option
.TABLE_TO_REGIONS_COUNT
;
173 case TASKS
: return ClusterMetrics
.Option
.TASKS
;
174 // should not reach here
175 default: throw new IllegalArgumentException("Invalid option: " + option
);
180 * Convert ClusterMetrics.Option to ClusterStatusProtos.Option
181 * @param option a ClusterMetrics.Option
182 * @return converted ClusterStatusProtos.Option
184 public static ClusterStatusProtos
.Option
toOption(ClusterMetrics
.Option option
) {
186 case HBASE_VERSION
: return ClusterStatusProtos
.Option
.HBASE_VERSION
;
187 case LIVE_SERVERS
: return ClusterStatusProtos
.Option
.LIVE_SERVERS
;
188 case DEAD_SERVERS
: return ClusterStatusProtos
.Option
.DEAD_SERVERS
;
189 case REGIONS_IN_TRANSITION
: return ClusterStatusProtos
.Option
.REGIONS_IN_TRANSITION
;
190 case CLUSTER_ID
: return ClusterStatusProtos
.Option
.CLUSTER_ID
;
191 case MASTER_COPROCESSORS
: return ClusterStatusProtos
.Option
.MASTER_COPROCESSORS
;
192 case MASTER
: return ClusterStatusProtos
.Option
.MASTER
;
193 case BACKUP_MASTERS
: return ClusterStatusProtos
.Option
.BACKUP_MASTERS
;
194 case BALANCER_ON
: return ClusterStatusProtos
.Option
.BALANCER_ON
;
195 case SERVERS_NAME
: return Option
.SERVERS_NAME
;
196 case MASTER_INFO_PORT
: return ClusterStatusProtos
.Option
.MASTER_INFO_PORT
;
197 case TABLE_TO_REGIONS_COUNT
: return ClusterStatusProtos
.Option
.TABLE_TO_REGIONS_COUNT
;
198 case TASKS
: return ClusterStatusProtos
.Option
.TASKS
;
199 // should not reach here
200 default: throw new IllegalArgumentException("Invalid option: " + option
);
205 * Convert a list of ClusterStatusProtos.Option to an enum set of ClusterMetrics.Option
206 * @param options the pb options
207 * @return an enum set of ClusterMetrics.Option
209 public static EnumSet
<ClusterMetrics
.Option
> toOptions(List
<ClusterStatusProtos
.Option
> options
) {
210 return options
.stream().map(ClusterMetricsBuilder
::toOption
)
211 .collect(Collectors
.toCollection(() -> EnumSet
.noneOf(ClusterMetrics
.Option
.class)));
215 * Convert an enum set of ClusterMetrics.Option to a list of ClusterStatusProtos.Option
216 * @param options the ClusterMetrics options
217 * @return a list of ClusterStatusProtos.Option
219 public static List
<ClusterStatusProtos
.Option
> toOptions(EnumSet
<ClusterMetrics
.Option
> options
) {
220 return options
.stream().map(ClusterMetricsBuilder
::toOption
).collect(Collectors
.toList());
223 public static ClusterMetricsBuilder
newBuilder() {
224 return new ClusterMetricsBuilder();
227 private String hbaseVersion
;
228 private List
<ServerName
> deadServerNames
= Collections
.emptyList();
229 private Map
<ServerName
, ServerMetrics
> liveServerMetrics
= new TreeMap
<>();
231 private ServerName masterName
;
232 private List
<ServerName
> backupMasterNames
= Collections
.emptyList();
233 private List
<RegionState
> regionsInTransition
= Collections
.emptyList();
235 private String clusterId
;
236 private List
<String
> masterCoprocessorNames
= Collections
.emptyList();
238 private Boolean balancerOn
;
239 private int masterInfoPort
;
240 private List
<ServerName
> serversName
= Collections
.emptyList();
241 private Map
<TableName
, RegionStatesCount
> tableRegionStatesCount
= Collections
.emptyMap();
243 private List
<ServerTask
> masterTasks
;
245 private ClusterMetricsBuilder() {
247 public ClusterMetricsBuilder
setHBaseVersion(String value
) {
248 this.hbaseVersion
= value
;
251 public ClusterMetricsBuilder
setDeadServerNames(List
<ServerName
> value
) {
252 this.deadServerNames
= value
;
256 public ClusterMetricsBuilder
setLiveServerMetrics(Map
<ServerName
, ServerMetrics
> value
) {
257 liveServerMetrics
.putAll(value
);
261 public ClusterMetricsBuilder
setMasterName(ServerName value
) {
262 this.masterName
= value
;
265 public ClusterMetricsBuilder
setBackerMasterNames(List
<ServerName
> value
) {
266 this.backupMasterNames
= value
;
269 public ClusterMetricsBuilder
setRegionsInTransition(List
<RegionState
> value
) {
270 this.regionsInTransition
= value
;
273 public ClusterMetricsBuilder
setClusterId(String value
) {
274 this.clusterId
= value
;
277 public ClusterMetricsBuilder
setMasterCoprocessorNames(List
<String
> value
) {
278 this.masterCoprocessorNames
= value
;
281 public ClusterMetricsBuilder
setBalancerOn(@Nullable Boolean value
) {
282 this.balancerOn
= value
;
285 public ClusterMetricsBuilder
setMasterInfoPort(int value
) {
286 this.masterInfoPort
= value
;
289 public ClusterMetricsBuilder
setServerNames(List
<ServerName
> serversName
) {
290 this.serversName
= serversName
;
293 public ClusterMetricsBuilder
setMasterTasks(List
<ServerTask
> masterTasks
) {
294 this.masterTasks
= masterTasks
;
298 public ClusterMetricsBuilder
setTableRegionStatesCount(
299 Map
<TableName
, RegionStatesCount
> tableRegionStatesCount
) {
300 this.tableRegionStatesCount
= tableRegionStatesCount
;
304 public ClusterMetrics
build() {
305 return new ClusterMetricsImpl(
313 masterCoprocessorNames
,
317 tableRegionStatesCount
,
321 private static class ClusterMetricsImpl
implements ClusterMetrics
{
323 private final String hbaseVersion
;
324 private final List
<ServerName
> deadServerNames
;
325 private final Map
<ServerName
, ServerMetrics
> liveServerMetrics
;
327 private final ServerName masterName
;
328 private final List
<ServerName
> backupMasterNames
;
329 private final List
<RegionState
> regionsInTransition
;
331 private final String clusterId
;
332 private final List
<String
> masterCoprocessorNames
;
334 private final Boolean balancerOn
;
335 private final int masterInfoPort
;
336 private final List
<ServerName
> serversName
;
337 private final Map
<TableName
, RegionStatesCount
> tableRegionStatesCount
;
338 private final List
<ServerTask
> masterTasks
;
340 ClusterMetricsImpl(String hbaseVersion
, List
<ServerName
> deadServerNames
,
341 Map
<ServerName
, ServerMetrics
> liveServerMetrics
,
342 ServerName masterName
,
343 List
<ServerName
> backupMasterNames
,
344 List
<RegionState
> regionsInTransition
,
346 List
<String
> masterCoprocessorNames
,
349 List
<ServerName
> serversName
,
350 Map
<TableName
, RegionStatesCount
> tableRegionStatesCount
,
351 List
<ServerTask
> masterTasks
) {
352 this.hbaseVersion
= hbaseVersion
;
353 this.deadServerNames
= Preconditions
.checkNotNull(deadServerNames
);
354 this.liveServerMetrics
= Preconditions
.checkNotNull(liveServerMetrics
);
355 this.masterName
= masterName
;
356 this.backupMasterNames
= Preconditions
.checkNotNull(backupMasterNames
);
357 this.regionsInTransition
= Preconditions
.checkNotNull(regionsInTransition
);
358 this.clusterId
= clusterId
;
359 this.masterCoprocessorNames
= Preconditions
.checkNotNull(masterCoprocessorNames
);
360 this.balancerOn
= balancerOn
;
361 this.masterInfoPort
= masterInfoPort
;
362 this.serversName
= serversName
;
363 this.tableRegionStatesCount
= Preconditions
.checkNotNull(tableRegionStatesCount
);
364 this.masterTasks
= masterTasks
;
368 public String
getHBaseVersion() {
373 public List
<ServerName
> getDeadServerNames() {
374 return Collections
.unmodifiableList(deadServerNames
);
378 public Map
<ServerName
, ServerMetrics
> getLiveServerMetrics() {
379 return Collections
.unmodifiableMap(liveServerMetrics
);
383 public ServerName
getMasterName() {
388 public List
<ServerName
> getBackupMasterNames() {
389 return Collections
.unmodifiableList(backupMasterNames
);
393 public List
<RegionState
> getRegionStatesInTransition() {
394 return Collections
.unmodifiableList(regionsInTransition
);
398 public String
getClusterId() {
403 public List
<String
> getMasterCoprocessorNames() {
404 return Collections
.unmodifiableList(masterCoprocessorNames
);
408 public Boolean
getBalancerOn() {
413 public int getMasterInfoPort() {
414 return masterInfoPort
;
418 public List
<ServerName
> getServersName() {
419 return Collections
.unmodifiableList(serversName
);
423 public Map
<TableName
, RegionStatesCount
> getTableRegionStatesCount() {
424 return Collections
.unmodifiableMap(tableRegionStatesCount
);
428 public List
<ServerTask
> getMasterTasks() {
433 public String
toString() {
434 StringBuilder sb
= new StringBuilder(1024);
435 sb
.append("Master: " + getMasterName());
437 int backupMastersSize
= getBackupMasterNames().size();
438 sb
.append("\nNumber of backup masters: " + backupMastersSize
);
439 if (backupMastersSize
> 0) {
440 for (ServerName serverName
: getBackupMasterNames()) {
441 sb
.append("\n " + serverName
);
445 int serversSize
= getLiveServerMetrics().size();
446 int serversNameSize
= getServersName().size();
447 sb
.append("\nNumber of live region servers: "
448 + (serversSize
> 0 ? serversSize
: serversNameSize
));
449 if (serversSize
> 0) {
450 for (ServerName serverName
: getLiveServerMetrics().keySet()) {
451 sb
.append("\n " + serverName
.getServerName());
453 } else if (serversNameSize
> 0) {
454 for (ServerName serverName
: getServersName()) {
455 sb
.append("\n " + serverName
.getServerName());
459 int deadServerSize
= getDeadServerNames().size();
460 sb
.append("\nNumber of dead region servers: " + deadServerSize
);
461 if (deadServerSize
> 0) {
462 for (ServerName serverName
: getDeadServerNames()) {
463 sb
.append("\n " + serverName
);
467 sb
.append("\nAverage load: " + getAverageLoad());
468 sb
.append("\nNumber of requests: " + getRequestCount());
469 sb
.append("\nNumber of regions: " + getRegionCount());
471 int ritSize
= getRegionStatesInTransition().size();
472 sb
.append("\nNumber of regions in transition: " + ritSize
);
474 for (RegionState state
: getRegionStatesInTransition()) {
475 sb
.append("\n " + state
.toDescriptiveString());
478 return sb
.toString();