001/** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019 020package org.apache.hadoop.hbase; 021 022import edu.umd.cs.findbugs.annotations.Nullable; 023import java.util.Collections; 024import java.util.EnumSet; 025import java.util.List; 026import java.util.Map; 027import java.util.TreeMap; 028import java.util.stream.Collectors; 029import org.apache.hadoop.hbase.master.RegionState; 030import org.apache.yetus.audience.InterfaceAudience; 031 032import org.apache.hbase.thirdparty.com.google.common.base.Preconditions; 033import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations; 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.FSProtos; 037import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos; 038 039@InterfaceAudience.Private 040public final class ClusterMetricsBuilder { 041 042 public static ClusterStatusProtos.ClusterStatus toClusterStatus(ClusterMetrics metrics) { 043 ClusterStatusProtos.ClusterStatus.Builder builder 044 = ClusterStatusProtos.ClusterStatus.newBuilder() 045 .addAllBackupMasters(metrics.getBackupMasterNames().stream() 046 .map(ProtobufUtil::toServerName).collect(Collectors.toList())) 047 .addAllDeadServers(metrics.getDeadServerNames().stream() 048 .map(ProtobufUtil::toServerName).collect(Collectors.toList())) 049 .addAllLiveServers(metrics.getLiveServerMetrics().entrySet().stream() 050 .map(s -> ClusterStatusProtos.LiveServerInfo 051 .newBuilder() 052 .setServer(ProtobufUtil.toServerName(s.getKey())) 053 .setServerLoad(ServerMetricsBuilder.toServerLoad(s.getValue())) 054 .build()) 055 .collect(Collectors.toList())) 056 .addAllMasterCoprocessors(metrics.getMasterCoprocessorNames().stream() 057 .map(n -> HBaseProtos.Coprocessor.newBuilder().setName(n).build()) 058 .collect(Collectors.toList())) 059 .addAllRegionsInTransition(metrics.getRegionStatesInTransition().stream() 060 .map(r -> ClusterStatusProtos.RegionInTransition 061 .newBuilder() 062 .setSpec(HBaseProtos.RegionSpecifier 063 .newBuilder() 064 .setType(HBaseProtos.RegionSpecifier.RegionSpecifierType.REGION_NAME) 065 .setValue(UnsafeByteOperations.unsafeWrap(r.getRegion().getRegionName())) 066 .build()) 067 .setRegionState(r.convert()) 068 .build()) 069 .collect(Collectors.toList())) 070 .setMasterInfoPort(metrics.getMasterInfoPort()); 071 if (metrics.getMasterName() != null) { 072 builder.setMaster(ProtobufUtil.toServerName((metrics.getMasterName()))); 073 } 074 if (metrics.getBalancerOn() != null) { 075 builder.setBalancerOn(metrics.getBalancerOn()); 076 } 077 if (metrics.getClusterId() != null) { 078 builder.setClusterId(new ClusterId(metrics.getClusterId()).convert()); 079 } 080 if (metrics.getHBaseVersion() != null) { 081 builder.setHbaseVersion( 082 FSProtos.HBaseVersionFileContent.newBuilder() 083 .setVersion(metrics.getHBaseVersion())); 084 } 085 return builder.build(); 086 } 087 088 public static ClusterMetrics toClusterMetrics( 089 ClusterStatusProtos.ClusterStatus proto) { 090 ClusterMetricsBuilder builder = ClusterMetricsBuilder.newBuilder(); 091 builder.setLiveServerMetrics(proto.getLiveServersList().stream() 092 .collect(Collectors.toMap(e -> ProtobufUtil.toServerName(e.getServer()), 093 ServerMetricsBuilder::toServerMetrics))) 094 .setDeadServerNames(proto.getDeadServersList().stream() 095 .map(ProtobufUtil::toServerName) 096 .collect(Collectors.toList())) 097 .setBackerMasterNames(proto.getBackupMastersList().stream() 098 .map(ProtobufUtil::toServerName) 099 .collect(Collectors.toList())) 100 .setRegionsInTransition(proto.getRegionsInTransitionList().stream() 101 .map(ClusterStatusProtos.RegionInTransition::getRegionState) 102 .map(RegionState::convert) 103 .collect(Collectors.toList())) 104 .setMasterCoprocessorNames(proto.getMasterCoprocessorsList().stream() 105 .map(HBaseProtos.Coprocessor::getName) 106 .collect(Collectors.toList())); 107 if (proto.hasClusterId()) { 108 builder.setClusterId(ClusterId.convert(proto.getClusterId()).toString()); 109 } 110 111 if (proto.hasHbaseVersion()) { 112 builder.setHBaseVersion(proto.getHbaseVersion().getVersion()); 113 } 114 115 if (proto.hasMaster()) { 116 builder.setMasterName(ProtobufUtil.toServerName(proto.getMaster())); 117 } 118 119 if (proto.hasBalancerOn()) { 120 builder.setBalancerOn(proto.getBalancerOn()); 121 } 122 123 if (proto.hasMasterInfoPort()) { 124 builder.setMasterInfoPort(proto.getMasterInfoPort()); 125 } 126 return builder.build(); 127 } 128 129 /** 130 * Convert ClusterStatusProtos.Option to ClusterMetrics.Option 131 * @param option a ClusterStatusProtos.Option 132 * @return converted ClusterMetrics.Option 133 */ 134 public static ClusterMetrics.Option toOption(ClusterStatusProtos.Option option) { 135 switch (option) { 136 case HBASE_VERSION: return ClusterMetrics.Option.HBASE_VERSION; 137 case LIVE_SERVERS: return ClusterMetrics.Option.LIVE_SERVERS; 138 case DEAD_SERVERS: return ClusterMetrics.Option.DEAD_SERVERS; 139 case REGIONS_IN_TRANSITION: return ClusterMetrics.Option.REGIONS_IN_TRANSITION; 140 case CLUSTER_ID: return ClusterMetrics.Option.CLUSTER_ID; 141 case MASTER_COPROCESSORS: return ClusterMetrics.Option.MASTER_COPROCESSORS; 142 case MASTER: return ClusterMetrics.Option.MASTER; 143 case BACKUP_MASTERS: return ClusterMetrics.Option.BACKUP_MASTERS; 144 case BALANCER_ON: return ClusterMetrics.Option.BALANCER_ON; 145 case MASTER_INFO_PORT: return ClusterMetrics.Option.MASTER_INFO_PORT; 146 // should not reach here 147 default: throw new IllegalArgumentException("Invalid option: " + option); 148 } 149 } 150 151 /** 152 * Convert ClusterMetrics.Option to ClusterStatusProtos.Option 153 * @param option a ClusterMetrics.Option 154 * @return converted ClusterStatusProtos.Option 155 */ 156 public static ClusterStatusProtos.Option toOption(ClusterMetrics.Option option) { 157 switch (option) { 158 case HBASE_VERSION: return ClusterStatusProtos.Option.HBASE_VERSION; 159 case LIVE_SERVERS: return ClusterStatusProtos.Option.LIVE_SERVERS; 160 case DEAD_SERVERS: return ClusterStatusProtos.Option.DEAD_SERVERS; 161 case REGIONS_IN_TRANSITION: return ClusterStatusProtos.Option.REGIONS_IN_TRANSITION; 162 case CLUSTER_ID: return ClusterStatusProtos.Option.CLUSTER_ID; 163 case MASTER_COPROCESSORS: return ClusterStatusProtos.Option.MASTER_COPROCESSORS; 164 case MASTER: return ClusterStatusProtos.Option.MASTER; 165 case BACKUP_MASTERS: return ClusterStatusProtos.Option.BACKUP_MASTERS; 166 case BALANCER_ON: return ClusterStatusProtos.Option.BALANCER_ON; 167 case MASTER_INFO_PORT: return ClusterStatusProtos.Option.MASTER_INFO_PORT; 168 // should not reach here 169 default: throw new IllegalArgumentException("Invalid option: " + option); 170 } 171 } 172 173 /** 174 * Convert a list of ClusterStatusProtos.Option to an enum set of ClusterMetrics.Option 175 * @param options the pb options 176 * @return an enum set of ClusterMetrics.Option 177 */ 178 public static EnumSet<ClusterMetrics.Option> toOptions(List<ClusterStatusProtos.Option> options) { 179 return options.stream().map(ClusterMetricsBuilder::toOption) 180 .collect(Collectors.toCollection(() -> EnumSet.noneOf(ClusterMetrics.Option.class))); 181 } 182 183 /** 184 * Convert an enum set of ClusterMetrics.Option to a list of ClusterStatusProtos.Option 185 * @param options the ClusterMetrics options 186 * @return a list of ClusterStatusProtos.Option 187 */ 188 public static List<ClusterStatusProtos.Option> toOptions(EnumSet<ClusterMetrics.Option> options) { 189 return options.stream().map(ClusterMetricsBuilder::toOption).collect(Collectors.toList()); 190 } 191 192 public static ClusterMetricsBuilder newBuilder() { 193 return new ClusterMetricsBuilder(); 194 } 195 @Nullable 196 private String hbaseVersion; 197 private List<ServerName> deadServerNames = Collections.emptyList(); 198 private Map<ServerName, ServerMetrics> liveServerMetrics = new TreeMap<>(); 199 @Nullable 200 private ServerName masterName; 201 private List<ServerName> backupMasterNames = Collections.emptyList(); 202 private List<RegionState> regionsInTransition = Collections.emptyList(); 203 @Nullable 204 private String clusterId; 205 private List<String> masterCoprocessorNames = Collections.emptyList(); 206 @Nullable 207 private Boolean balancerOn; 208 private int masterInfoPort; 209 210 private ClusterMetricsBuilder() { 211 } 212 public ClusterMetricsBuilder setHBaseVersion(String value) { 213 this.hbaseVersion = value; 214 return this; 215 } 216 public ClusterMetricsBuilder setDeadServerNames(List<ServerName> value) { 217 this.deadServerNames = value; 218 return this; 219 } 220 221 public ClusterMetricsBuilder setLiveServerMetrics(Map<ServerName, ServerMetrics> value) { 222 liveServerMetrics.putAll(value); 223 return this; 224 } 225 226 public ClusterMetricsBuilder setMasterName(ServerName value) { 227 this.masterName = value; 228 return this; 229 } 230 public ClusterMetricsBuilder setBackerMasterNames(List<ServerName> value) { 231 this.backupMasterNames = value; 232 return this; 233 } 234 public ClusterMetricsBuilder setRegionsInTransition(List<RegionState> value) { 235 this.regionsInTransition = value; 236 return this; 237 } 238 public ClusterMetricsBuilder setClusterId(String value) { 239 this.clusterId = value; 240 return this; 241 } 242 public ClusterMetricsBuilder setMasterCoprocessorNames(List<String> value) { 243 this.masterCoprocessorNames = value; 244 return this; 245 } 246 public ClusterMetricsBuilder setBalancerOn(@Nullable Boolean value) { 247 this.balancerOn = value; 248 return this; 249 } 250 public ClusterMetricsBuilder setMasterInfoPort(int value) { 251 this.masterInfoPort = value; 252 return this; 253 } 254 public ClusterMetrics build() { 255 return new ClusterMetricsImpl( 256 hbaseVersion, 257 deadServerNames, 258 liveServerMetrics, 259 masterName, 260 backupMasterNames, 261 regionsInTransition, 262 clusterId, 263 masterCoprocessorNames, 264 balancerOn, 265 masterInfoPort); 266 } 267 private static class ClusterMetricsImpl implements ClusterMetrics { 268 @Nullable 269 private final String hbaseVersion; 270 private final List<ServerName> deadServerNames; 271 private final Map<ServerName, ServerMetrics> liveServerMetrics; 272 @Nullable 273 private final ServerName masterName; 274 private final List<ServerName> backupMasterNames; 275 private final List<RegionState> regionsInTransition; 276 @Nullable 277 private final String clusterId; 278 private final List<String> masterCoprocessorNames; 279 @Nullable 280 private final Boolean balancerOn; 281 private final int masterInfoPort; 282 283 ClusterMetricsImpl(String hbaseVersion, List<ServerName> deadServerNames, 284 Map<ServerName, ServerMetrics> liveServerMetrics, 285 ServerName masterName, 286 List<ServerName> backupMasterNames, 287 List<RegionState> regionsInTransition, 288 String clusterId, 289 List<String> masterCoprocessorNames, 290 Boolean balancerOn, 291 int masterInfoPort) { 292 this.hbaseVersion = hbaseVersion; 293 this.deadServerNames = Preconditions.checkNotNull(deadServerNames); 294 this.liveServerMetrics = Preconditions.checkNotNull(liveServerMetrics); 295 this.masterName = masterName; 296 this.backupMasterNames = Preconditions.checkNotNull(backupMasterNames); 297 this.regionsInTransition = Preconditions.checkNotNull(regionsInTransition); 298 this.clusterId = clusterId; 299 this.masterCoprocessorNames = Preconditions.checkNotNull(masterCoprocessorNames); 300 this.balancerOn = balancerOn; 301 this.masterInfoPort = masterInfoPort; 302 } 303 304 @Override 305 public String getHBaseVersion() { 306 return hbaseVersion; 307 } 308 309 @Override 310 public List<ServerName> getDeadServerNames() { 311 return Collections.unmodifiableList(deadServerNames); 312 } 313 314 @Override 315 public Map<ServerName, ServerMetrics> getLiveServerMetrics() { 316 return Collections.unmodifiableMap(liveServerMetrics); 317 } 318 319 @Override 320 public ServerName getMasterName() { 321 return masterName; 322 } 323 324 @Override 325 public List<ServerName> getBackupMasterNames() { 326 return Collections.unmodifiableList(backupMasterNames); 327 } 328 329 @Override 330 public List<RegionState> getRegionStatesInTransition() { 331 return Collections.unmodifiableList(regionsInTransition); 332 } 333 334 @Override 335 public String getClusterId() { 336 return clusterId; 337 } 338 339 @Override 340 public List<String> getMasterCoprocessorNames() { 341 return Collections.unmodifiableList(masterCoprocessorNames); 342 } 343 344 @Override 345 public Boolean getBalancerOn() { 346 return balancerOn; 347 } 348 349 @Override 350 public int getMasterInfoPort() { 351 return masterInfoPort; 352 } 353 354 @Override 355 public String toString() { 356 StringBuilder sb = new StringBuilder(1024); 357 sb.append("Master: " + getMasterName()); 358 359 int backupMastersSize = getBackupMasterNames().size(); 360 sb.append("\nNumber of backup masters: " + backupMastersSize); 361 if (backupMastersSize > 0) { 362 for (ServerName serverName: getBackupMasterNames()) { 363 sb.append("\n " + serverName); 364 } 365 } 366 367 int serversSize = getLiveServerMetrics().size(); 368 sb.append("\nNumber of live region servers: " + serversSize); 369 if (serversSize > 0) { 370 for (ServerName serverName : getLiveServerMetrics().keySet()) { 371 sb.append("\n " + serverName.getServerName()); 372 } 373 } 374 375 int deadServerSize = getDeadServerNames().size(); 376 sb.append("\nNumber of dead region servers: " + deadServerSize); 377 if (deadServerSize > 0) { 378 for (ServerName serverName : getDeadServerNames()) { 379 sb.append("\n " + serverName); 380 } 381 } 382 383 sb.append("\nAverage load: " + getAverageLoad()); 384 sb.append("\nNumber of requests: " + getRequestCount()); 385 sb.append("\nNumber of regions: " + getRegionCount()); 386 387 int ritSize = getRegionStatesInTransition().size(); 388 sb.append("\nNumber of regions in transition: " + ritSize); 389 if (ritSize > 0) { 390 for (RegionState state : getRegionStatesInTransition()) { 391 sb.append("\n " + state.toDescriptiveString()); 392 } 393 } 394 return sb.toString(); 395 } 396 } 397}