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 edu.umd.cs.findbugs.annotations.Nullable; 021import java.util.Collections; 022import java.util.EnumSet; 023import java.util.List; 024import java.util.Map; 025import java.util.TreeMap; 026import java.util.stream.Collectors; 027import org.apache.hadoop.hbase.client.RegionStatesCount; 028import org.apache.hadoop.hbase.master.RegionState; 029import org.apache.yetus.audience.InterfaceAudience; 030 031import org.apache.hbase.thirdparty.com.google.common.base.Preconditions; 032import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations; 033 034import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 035import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos; 036import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.Option; 037import org.apache.hadoop.hbase.shaded.protobuf.generated.FSProtos; 038import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos; 039 040@InterfaceAudience.Private 041public final class ClusterMetricsBuilder { 042 043 public static ClusterStatusProtos.ClusterStatus toClusterStatus(ClusterMetrics metrics) { 044 ClusterStatusProtos.ClusterStatus.Builder builder = 045 ClusterStatusProtos.ClusterStatus.newBuilder() 046 .addAllBackupMasters(metrics.getBackupMasterNames().stream().map(ProtobufUtil::toServerName) 047 .collect(Collectors.toList())) 048 .addAllDeadServers(metrics.getDeadServerNames().stream().map(ProtobufUtil::toServerName) 049 .collect(Collectors.toList())) 050 .addAllUnknownServers(metrics.getUnknownServerNames().stream() 051 .map(ProtobufUtil::toServerName).collect(Collectors.toList())) 052 .addAllLiveServers(metrics.getLiveServerMetrics().entrySet().stream() 053 .map(s -> ClusterStatusProtos.LiveServerInfo.newBuilder() 054 .setServer(ProtobufUtil.toServerName(s.getKey())) 055 .setServerLoad(ServerMetricsBuilder.toServerLoad(s.getValue())).build()) 056 .collect(Collectors.toList())) 057 .addAllMasterCoprocessors(metrics.getMasterCoprocessorNames().stream() 058 .map(n -> HBaseProtos.Coprocessor.newBuilder().setName(n).build()) 059 .collect(Collectors.toList())) 060 .addAllRegionsInTransition(metrics.getRegionStatesInTransition().stream() 061 .map(r -> ClusterStatusProtos.RegionInTransition.newBuilder() 062 .setSpec(HBaseProtos.RegionSpecifier.newBuilder() 063 .setType(HBaseProtos.RegionSpecifier.RegionSpecifierType.REGION_NAME) 064 .setValue(UnsafeByteOperations.unsafeWrap(r.getRegion().getRegionName())).build()) 065 .setRegionState(r.convert()).build()) 066 .collect(Collectors.toList())) 067 .setMasterInfoPort(metrics.getMasterInfoPort()) 068 .addAllServersName(metrics.getServersName().stream().map(ProtobufUtil::toServerName) 069 .collect(Collectors.toList())) 070 .addAllTableRegionStatesCount(metrics.getTableRegionStatesCount().entrySet().stream() 071 .map(status -> ClusterStatusProtos.TableRegionStatesCount.newBuilder() 072 .setTableName(ProtobufUtil.toProtoTableName(status.getKey())) 073 .setRegionStatesCount(ProtobufUtil.toTableRegionStatesCount(status.getValue())).build()) 074 .collect(Collectors.toList())) 075 .addAllDecommissionedServers(metrics.getDecommissionedServerNames().stream() 076 .map(ProtobufUtil::toServerName).collect(Collectors.toList())); 077 if (metrics.getMasterName() != null) { 078 builder.setMaster(ProtobufUtil.toServerName(metrics.getMasterName())); 079 } 080 if (metrics.getMasterTasks() != null) { 081 builder.addAllMasterTasks(metrics.getMasterTasks().stream() 082 .map(t -> ProtobufUtil.toServerTask(t)).collect(Collectors.toList())); 083 } 084 if (metrics.getBalancerOn() != null) { 085 builder.setBalancerOn(metrics.getBalancerOn()); 086 } 087 if (metrics.getClusterId() != null) { 088 builder.setClusterId(new ClusterId(metrics.getClusterId()).convert()); 089 } 090 if (metrics.getHBaseVersion() != null) { 091 builder.setHbaseVersion( 092 FSProtos.HBaseVersionFileContent.newBuilder().setVersion(metrics.getHBaseVersion())); 093 } 094 095 return builder.build(); 096 } 097 098 public static ClusterMetrics toClusterMetrics(ClusterStatusProtos.ClusterStatus proto) { 099 ClusterMetricsBuilder builder = ClusterMetricsBuilder.newBuilder(); 100 builder 101 .setLiveServerMetrics(proto.getLiveServersList().stream() 102 .collect(Collectors.toMap(e -> ProtobufUtil.toServerName(e.getServer()), 103 ServerMetricsBuilder::toServerMetrics))) 104 .setDeadServerNames(proto.getDeadServersList().stream().map(ProtobufUtil::toServerName) 105 .collect(Collectors.toList())) 106 .setUnknownServerNames(proto.getUnknownServersList().stream().map(ProtobufUtil::toServerName) 107 .collect(Collectors.toList())) 108 .setBackerMasterNames(proto.getBackupMastersList().stream().map(ProtobufUtil::toServerName) 109 .collect(Collectors.toList())) 110 .setRegionsInTransition(proto.getRegionsInTransitionList().stream() 111 .map(ClusterStatusProtos.RegionInTransition::getRegionState).map(RegionState::convert) 112 .collect(Collectors.toList())) 113 .setMasterCoprocessorNames(proto.getMasterCoprocessorsList().stream() 114 .map(HBaseProtos.Coprocessor::getName).collect(Collectors.toList())) 115 .setServerNames(proto.getServersNameList().stream().map(ProtobufUtil::toServerName) 116 .collect(Collectors.toList())) 117 .setTableRegionStatesCount(proto.getTableRegionStatesCountList().stream() 118 .collect(Collectors.toMap(e -> ProtobufUtil.toTableName(e.getTableName()), 119 e -> ProtobufUtil.toTableRegionStatesCount(e.getRegionStatesCount())))) 120 .setMasterTasks(proto.getMasterTasksList().stream().map(t -> ProtobufUtil.getServerTask(t)) 121 .collect(Collectors.toList())) 122 .setDecommissionedServerNames(proto.getDecommissionedServersList().stream() 123 .map(ProtobufUtil::toServerName).collect(Collectors.toList())); 124 if (proto.hasClusterId()) { 125 builder.setClusterId(ClusterId.convert(proto.getClusterId()).toString()); 126 } 127 128 if (proto.hasHbaseVersion()) { 129 builder.setHBaseVersion(proto.getHbaseVersion().getVersion()); 130 } 131 132 if (proto.hasMaster()) { 133 builder.setMasterName(ProtobufUtil.toServerName(proto.getMaster())); 134 } 135 136 if (proto.hasBalancerOn()) { 137 builder.setBalancerOn(proto.getBalancerOn()); 138 } 139 140 if (proto.hasMasterInfoPort()) { 141 builder.setMasterInfoPort(proto.getMasterInfoPort()); 142 } 143 return builder.build(); 144 } 145 146 /** 147 * Convert ClusterStatusProtos.Option to ClusterMetrics.Option 148 * @param option a ClusterStatusProtos.Option 149 * @return converted ClusterMetrics.Option 150 */ 151 public static ClusterMetrics.Option toOption(ClusterStatusProtos.Option option) { 152 switch (option) { 153 case HBASE_VERSION: 154 return ClusterMetrics.Option.HBASE_VERSION; 155 case LIVE_SERVERS: 156 return ClusterMetrics.Option.LIVE_SERVERS; 157 case DEAD_SERVERS: 158 return ClusterMetrics.Option.DEAD_SERVERS; 159 case UNKNOWN_SERVERS: 160 return ClusterMetrics.Option.UNKNOWN_SERVERS; 161 case REGIONS_IN_TRANSITION: 162 return ClusterMetrics.Option.REGIONS_IN_TRANSITION; 163 case CLUSTER_ID: 164 return ClusterMetrics.Option.CLUSTER_ID; 165 case MASTER_COPROCESSORS: 166 return ClusterMetrics.Option.MASTER_COPROCESSORS; 167 case MASTER: 168 return ClusterMetrics.Option.MASTER; 169 case BACKUP_MASTERS: 170 return ClusterMetrics.Option.BACKUP_MASTERS; 171 case BALANCER_ON: 172 return ClusterMetrics.Option.BALANCER_ON; 173 case SERVERS_NAME: 174 return ClusterMetrics.Option.SERVERS_NAME; 175 case MASTER_INFO_PORT: 176 return ClusterMetrics.Option.MASTER_INFO_PORT; 177 case TABLE_TO_REGIONS_COUNT: 178 return ClusterMetrics.Option.TABLE_TO_REGIONS_COUNT; 179 case TASKS: 180 return ClusterMetrics.Option.TASKS; 181 case DECOMMISSIONED_SERVERS: 182 return ClusterMetrics.Option.DECOMMISSIONED_SERVERS; 183 // should not reach here 184 default: 185 throw new IllegalArgumentException("Invalid option: " + option); 186 } 187 } 188 189 /** 190 * Convert ClusterMetrics.Option to ClusterStatusProtos.Option 191 * @param option a ClusterMetrics.Option 192 * @return converted ClusterStatusProtos.Option 193 */ 194 public static ClusterStatusProtos.Option toOption(ClusterMetrics.Option option) { 195 switch (option) { 196 case HBASE_VERSION: 197 return ClusterStatusProtos.Option.HBASE_VERSION; 198 case LIVE_SERVERS: 199 return ClusterStatusProtos.Option.LIVE_SERVERS; 200 case DEAD_SERVERS: 201 return ClusterStatusProtos.Option.DEAD_SERVERS; 202 case UNKNOWN_SERVERS: 203 return ClusterStatusProtos.Option.UNKNOWN_SERVERS; 204 case REGIONS_IN_TRANSITION: 205 return ClusterStatusProtos.Option.REGIONS_IN_TRANSITION; 206 case CLUSTER_ID: 207 return ClusterStatusProtos.Option.CLUSTER_ID; 208 case MASTER_COPROCESSORS: 209 return ClusterStatusProtos.Option.MASTER_COPROCESSORS; 210 case MASTER: 211 return ClusterStatusProtos.Option.MASTER; 212 case BACKUP_MASTERS: 213 return ClusterStatusProtos.Option.BACKUP_MASTERS; 214 case BALANCER_ON: 215 return ClusterStatusProtos.Option.BALANCER_ON; 216 case SERVERS_NAME: 217 return Option.SERVERS_NAME; 218 case MASTER_INFO_PORT: 219 return ClusterStatusProtos.Option.MASTER_INFO_PORT; 220 case TABLE_TO_REGIONS_COUNT: 221 return ClusterStatusProtos.Option.TABLE_TO_REGIONS_COUNT; 222 case TASKS: 223 return ClusterStatusProtos.Option.TASKS; 224 case DECOMMISSIONED_SERVERS: 225 return ClusterStatusProtos.Option.DECOMMISSIONED_SERVERS; 226 // should not reach here 227 default: 228 throw new IllegalArgumentException("Invalid option: " + option); 229 } 230 } 231 232 /** 233 * Convert a list of ClusterStatusProtos.Option to an enum set of ClusterMetrics.Option 234 * @param options the pb options 235 * @return an enum set of ClusterMetrics.Option 236 */ 237 public static EnumSet<ClusterMetrics.Option> toOptions(List<ClusterStatusProtos.Option> options) { 238 return options.stream().map(ClusterMetricsBuilder::toOption) 239 .collect(Collectors.toCollection(() -> EnumSet.noneOf(ClusterMetrics.Option.class))); 240 } 241 242 /** 243 * Convert an enum set of ClusterMetrics.Option to a list of ClusterStatusProtos.Option 244 * @param options the ClusterMetrics options 245 * @return a list of ClusterStatusProtos.Option 246 */ 247 public static List<ClusterStatusProtos.Option> toOptions(EnumSet<ClusterMetrics.Option> options) { 248 return options.stream().map(ClusterMetricsBuilder::toOption).collect(Collectors.toList()); 249 } 250 251 public static ClusterMetricsBuilder newBuilder() { 252 return new ClusterMetricsBuilder(); 253 } 254 255 @Nullable 256 private String hbaseVersion; 257 private List<ServerName> deadServerNames = Collections.emptyList(); 258 private List<ServerName> unknownServerNames = Collections.emptyList(); 259 private Map<ServerName, ServerMetrics> liveServerMetrics = new TreeMap<>(); 260 @Nullable 261 private ServerName masterName; 262 private List<ServerName> backupMasterNames = Collections.emptyList(); 263 private List<RegionState> regionsInTransition = Collections.emptyList(); 264 @Nullable 265 private String clusterId; 266 private List<String> masterCoprocessorNames = Collections.emptyList(); 267 @Nullable 268 private Boolean balancerOn; 269 private int masterInfoPort; 270 private List<ServerName> serversName = Collections.emptyList(); 271 private Map<TableName, RegionStatesCount> tableRegionStatesCount = Collections.emptyMap(); 272 @Nullable 273 private List<ServerTask> masterTasks; 274 private List<ServerName> decommissionedServerNames = Collections.emptyList(); 275 276 private ClusterMetricsBuilder() { 277 } 278 279 public ClusterMetricsBuilder setHBaseVersion(String value) { 280 this.hbaseVersion = value; 281 return this; 282 } 283 284 public ClusterMetricsBuilder setDeadServerNames(List<ServerName> value) { 285 this.deadServerNames = value; 286 return this; 287 } 288 289 public ClusterMetricsBuilder setUnknownServerNames(List<ServerName> value) { 290 this.unknownServerNames = value; 291 return this; 292 } 293 294 public ClusterMetricsBuilder setLiveServerMetrics(Map<ServerName, ServerMetrics> value) { 295 liveServerMetrics.putAll(value); 296 return this; 297 } 298 299 public ClusterMetricsBuilder setMasterName(ServerName value) { 300 this.masterName = value; 301 return this; 302 } 303 304 public ClusterMetricsBuilder setBackerMasterNames(List<ServerName> value) { 305 this.backupMasterNames = value; 306 return this; 307 } 308 309 public ClusterMetricsBuilder setRegionsInTransition(List<RegionState> value) { 310 this.regionsInTransition = value; 311 return this; 312 } 313 314 public ClusterMetricsBuilder setClusterId(String value) { 315 this.clusterId = value; 316 return this; 317 } 318 319 public ClusterMetricsBuilder setMasterCoprocessorNames(List<String> value) { 320 this.masterCoprocessorNames = value; 321 return this; 322 } 323 324 public ClusterMetricsBuilder setBalancerOn(@Nullable Boolean value) { 325 this.balancerOn = value; 326 return this; 327 } 328 329 public ClusterMetricsBuilder setMasterInfoPort(int value) { 330 this.masterInfoPort = value; 331 return this; 332 } 333 334 public ClusterMetricsBuilder setServerNames(List<ServerName> serversName) { 335 this.serversName = serversName; 336 return this; 337 } 338 339 public ClusterMetricsBuilder setMasterTasks(List<ServerTask> masterTasks) { 340 this.masterTasks = masterTasks; 341 return this; 342 } 343 344 public ClusterMetricsBuilder setDecommissionedServerNames(List<ServerName> value) { 345 this.decommissionedServerNames = value; 346 return this; 347 } 348 349 public ClusterMetricsBuilder 350 setTableRegionStatesCount(Map<TableName, RegionStatesCount> tableRegionStatesCount) { 351 this.tableRegionStatesCount = tableRegionStatesCount; 352 return this; 353 } 354 355 public ClusterMetrics build() { 356 return new ClusterMetricsImpl(hbaseVersion, deadServerNames, unknownServerNames, 357 liveServerMetrics, masterName, backupMasterNames, regionsInTransition, clusterId, 358 masterCoprocessorNames, balancerOn, masterInfoPort, serversName, tableRegionStatesCount, 359 masterTasks, decommissionedServerNames); 360 } 361 362 private static class ClusterMetricsImpl implements ClusterMetrics { 363 @Nullable 364 private final String hbaseVersion; 365 private final List<ServerName> deadServerNames; 366 private final List<ServerName> unknownServerNames; 367 private final List<ServerName> decommissionedServerNames; 368 private final Map<ServerName, ServerMetrics> liveServerMetrics; 369 @Nullable 370 private final ServerName masterName; 371 private final List<ServerName> backupMasterNames; 372 private final List<RegionState> regionsInTransition; 373 @Nullable 374 private final String clusterId; 375 private final List<String> masterCoprocessorNames; 376 @Nullable 377 private final Boolean balancerOn; 378 private final int masterInfoPort; 379 private final List<ServerName> serversName; 380 private final Map<TableName, RegionStatesCount> tableRegionStatesCount; 381 private final List<ServerTask> masterTasks; 382 383 ClusterMetricsImpl(String hbaseVersion, List<ServerName> deadServerNames, 384 List<ServerName> unknownServerNames, Map<ServerName, ServerMetrics> liveServerMetrics, 385 ServerName masterName, List<ServerName> backupMasterNames, 386 List<RegionState> regionsInTransition, String clusterId, List<String> masterCoprocessorNames, 387 Boolean balancerOn, int masterInfoPort, List<ServerName> serversName, 388 Map<TableName, RegionStatesCount> tableRegionStatesCount, List<ServerTask> masterTasks, 389 List<ServerName> decommissionedServerNames) { 390 this.hbaseVersion = hbaseVersion; 391 this.deadServerNames = Preconditions.checkNotNull(deadServerNames); 392 this.unknownServerNames = Preconditions.checkNotNull(unknownServerNames); 393 this.decommissionedServerNames = Preconditions.checkNotNull(decommissionedServerNames); 394 this.liveServerMetrics = Preconditions.checkNotNull(liveServerMetrics); 395 this.masterName = masterName; 396 this.backupMasterNames = Preconditions.checkNotNull(backupMasterNames); 397 this.regionsInTransition = Preconditions.checkNotNull(regionsInTransition); 398 this.clusterId = clusterId; 399 this.masterCoprocessorNames = Preconditions.checkNotNull(masterCoprocessorNames); 400 this.balancerOn = balancerOn; 401 this.masterInfoPort = masterInfoPort; 402 this.serversName = serversName; 403 this.tableRegionStatesCount = Preconditions.checkNotNull(tableRegionStatesCount); 404 this.masterTasks = masterTasks; 405 } 406 407 @Override 408 public String getHBaseVersion() { 409 return hbaseVersion; 410 } 411 412 @Override 413 public List<ServerName> getDeadServerNames() { 414 return Collections.unmodifiableList(deadServerNames); 415 } 416 417 @Override 418 public List<ServerName> getUnknownServerNames() { 419 return Collections.unmodifiableList(unknownServerNames); 420 } 421 422 @Override 423 public List<ServerName> getDecommissionedServerNames() { 424 return Collections.unmodifiableList(decommissionedServerNames); 425 } 426 427 @Override 428 public Map<ServerName, ServerMetrics> getLiveServerMetrics() { 429 return Collections.unmodifiableMap(liveServerMetrics); 430 } 431 432 @Override 433 public ServerName getMasterName() { 434 return masterName; 435 } 436 437 @Override 438 public List<ServerName> getBackupMasterNames() { 439 return Collections.unmodifiableList(backupMasterNames); 440 } 441 442 @Override 443 public List<RegionState> getRegionStatesInTransition() { 444 return Collections.unmodifiableList(regionsInTransition); 445 } 446 447 @Override 448 public String getClusterId() { 449 return clusterId; 450 } 451 452 @Override 453 public List<String> getMasterCoprocessorNames() { 454 return Collections.unmodifiableList(masterCoprocessorNames); 455 } 456 457 @Override 458 public Boolean getBalancerOn() { 459 return balancerOn; 460 } 461 462 @Override 463 public int getMasterInfoPort() { 464 return masterInfoPort; 465 } 466 467 @Override 468 public List<ServerName> getServersName() { 469 return Collections.unmodifiableList(serversName); 470 } 471 472 @Override 473 public Map<TableName, RegionStatesCount> getTableRegionStatesCount() { 474 return Collections.unmodifiableMap(tableRegionStatesCount); 475 } 476 477 @Override 478 public List<ServerTask> getMasterTasks() { 479 return masterTasks; 480 } 481 482 @Override 483 public String toString() { 484 StringBuilder sb = new StringBuilder(1024); 485 sb.append("Master: " + getMasterName()); 486 487 int backupMastersSize = getBackupMasterNames().size(); 488 sb.append("\nNumber of backup masters: " + backupMastersSize); 489 if (backupMastersSize > 0) { 490 for (ServerName serverName : getBackupMasterNames()) { 491 sb.append("\n " + serverName); 492 } 493 } 494 495 int serversSize = getLiveServerMetrics().size(); 496 int serversNameSize = getServersName().size(); 497 sb.append( 498 "\nNumber of live region servers: " + (serversSize > 0 ? serversSize : serversNameSize)); 499 if (serversSize > 0) { 500 for (ServerName serverName : getLiveServerMetrics().keySet()) { 501 sb.append("\n " + serverName.getServerName()); 502 } 503 } else if (serversNameSize > 0) { 504 for (ServerName serverName : getServersName()) { 505 sb.append("\n " + serverName.getServerName()); 506 } 507 } 508 509 int deadServerSize = getDeadServerNames().size(); 510 sb.append("\nNumber of dead region servers: " + deadServerSize); 511 if (deadServerSize > 0) { 512 for (ServerName serverName : getDeadServerNames()) { 513 sb.append("\n " + serverName); 514 } 515 } 516 517 int unknownServerSize = getUnknownServerNames().size(); 518 sb.append("\nNumber of unknown region servers: " + unknownServerSize); 519 if (unknownServerSize > 0) { 520 for (ServerName serverName : getUnknownServerNames()) { 521 sb.append("\n " + serverName); 522 } 523 } 524 525 sb.append("\nAverage load: " + getAverageLoad()); 526 sb.append("\nNumber of requests: " + getRequestCount()); 527 sb.append("\nNumber of regions: " + getRegionCount()); 528 529 int ritSize = getRegionStatesInTransition().size(); 530 sb.append("\nNumber of regions in transition: " + ritSize); 531 if (ritSize > 0) { 532 for (RegionState state : getRegionStatesInTransition()) { 533 sb.append("\n " + state.toDescriptiveString()); 534 } 535 } 536 return sb.toString(); 537 } 538 } 539}