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.ArrayList;
022import java.util.Collection;
023import java.util.Collections;
024import java.util.HashMap;
025import java.util.List;
026import java.util.Map;
027import java.util.Set;
028import java.util.TreeMap;
029import java.util.TreeSet;
030import java.util.stream.Collectors;
031import org.apache.hadoop.hbase.replication.ReplicationLoadSink;
032import org.apache.hadoop.hbase.replication.ReplicationLoadSource;
033import org.apache.hadoop.hbase.util.Bytes;
034import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
035import org.apache.hadoop.hbase.util.Strings;
036import org.apache.yetus.audience.InterfaceAudience;
037
038import org.apache.hbase.thirdparty.com.google.common.base.Preconditions;
039
040import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
041import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos;
042import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
043
044@InterfaceAudience.Private
045public final class ServerMetricsBuilder {
046
047  public static ServerMetrics of(ServerName sn) {
048    return newBuilder(sn).build();
049  }
050
051  public static ServerMetrics of(ServerName sn, int versionNumber, String version) {
052    return newBuilder(sn).setVersionNumber(versionNumber).setVersion(version).build();
053  }
054
055  public static ServerMetrics toServerMetrics(ClusterStatusProtos.LiveServerInfo serverInfo) {
056    return toServerMetrics(ProtobufUtil.toServerName(serverInfo.getServer()), 0, "0.0.0",
057      serverInfo.getServerLoad());
058  }
059
060  public static ServerMetrics toServerMetrics(ServerName serverName,
061    ClusterStatusProtos.ServerLoad serverLoadPB) {
062    return toServerMetrics(serverName, 0, "0.0.0", serverLoadPB);
063  }
064
065  public static ServerMetrics toServerMetrics(ServerName serverName, int versionNumber,
066    String version, ClusterStatusProtos.ServerLoad serverLoadPB) {
067    ServerMetricsBuilder builder = ServerMetricsBuilder.newBuilder(serverName)
068      .setRequestCountPerSecond(serverLoadPB.getNumberOfRequests())
069      .setRequestCount(serverLoadPB.getTotalNumberOfRequests())
070      .setInfoServerPort(serverLoadPB.getInfoServerPort())
071      .setReadRequestCount(serverLoadPB.getReadRequestsCount())
072      .setWriteRequestCount(serverLoadPB.getWriteRequestsCount())
073      .setMaxHeapSize(new Size(serverLoadPB.getMaxHeapMB(), Size.Unit.MEGABYTE))
074      .setUsedHeapSize(new Size(serverLoadPB.getUsedHeapMB(), Size.Unit.MEGABYTE))
075      .setCoprocessorNames(serverLoadPB.getCoprocessorsList().stream()
076        .map(HBaseProtos.Coprocessor::getName).collect(Collectors.toList()))
077      .setRegionMetrics(serverLoadPB.getRegionLoadsList().stream()
078        .map(RegionMetricsBuilder::toRegionMetrics).collect(Collectors.toList()))
079      .setUserMetrics(serverLoadPB.getUserLoadsList().stream()
080        .map(UserMetricsBuilder::toUserMetrics).collect(Collectors.toList()))
081      .setReplicationLoadSources(serverLoadPB.getReplLoadSourceList().stream()
082        .map(ProtobufUtil::toReplicationLoadSource).collect(Collectors.toList()))
083      .setReplicationLoadSink(serverLoadPB.hasReplLoadSink()
084        ? ProtobufUtil.toReplicationLoadSink(serverLoadPB.getReplLoadSink())
085        : null)
086      .setTasks(serverLoadPB.getTasksList().stream().map(ProtobufUtil::getServerTask)
087        .collect(Collectors.toList()))
088      .setRegionCachedInfo(serverLoadPB.getRegionCachedInfoMap())
089      .setReportTimestamp(serverLoadPB.getReportEndTime())
090      .setLastReportTimestamp(serverLoadPB.getReportStartTime()).setVersionNumber(versionNumber)
091      .setVersion(version)
092      .setCacheFreeSize(serverLoadPB.hasCacheFreeSize() ? serverLoadPB.getCacheFreeSize() : 0L)
093      .setRegionColdDataInfo(serverLoadPB.getRegionColdDataMap());
094    return builder.build();
095  }
096
097  public static List<HBaseProtos.Coprocessor> toCoprocessor(Collection<String> names) {
098    return names.stream().map(n -> HBaseProtos.Coprocessor.newBuilder().setName(n).build())
099      .collect(Collectors.toList());
100  }
101
102  public static ClusterStatusProtos.ServerLoad toServerLoad(ServerMetrics metrics) {
103    ClusterStatusProtos.ServerLoad.Builder builder = ClusterStatusProtos.ServerLoad.newBuilder()
104      .setNumberOfRequests(metrics.getRequestCountPerSecond())
105      .setTotalNumberOfRequests(metrics.getRequestCount())
106      .setInfoServerPort(metrics.getInfoServerPort())
107      .setMaxHeapMB((int) metrics.getMaxHeapSize().get(Size.Unit.MEGABYTE))
108      .setUsedHeapMB((int) metrics.getUsedHeapSize().get(Size.Unit.MEGABYTE))
109      .addAllCoprocessors(toCoprocessor(metrics.getCoprocessorNames()))
110      .addAllRegionLoads(metrics.getRegionMetrics().values().stream()
111        .map(RegionMetricsBuilder::toRegionLoad).collect(Collectors.toList()))
112      .addAllUserLoads(metrics.getUserMetrics().values().stream()
113        .map(UserMetricsBuilder::toUserMetrics).collect(Collectors.toList()))
114      .addAllReplLoadSource(metrics.getReplicationLoadSourceList().stream()
115        .map(ProtobufUtil::toReplicationLoadSource).collect(Collectors.toList()))
116      .addAllTasks(
117        metrics.getTasks().stream().map(ProtobufUtil::toServerTask).collect(Collectors.toList()))
118      .putAllRegionCachedInfo(metrics.getRegionCachedInfo())
119      .setReportStartTime(metrics.getLastReportTimestamp())
120      .setReportEndTime(metrics.getReportTimestamp());
121    if (metrics.getReplicationLoadSink() != null) {
122      builder.setReplLoadSink(ProtobufUtil.toReplicationLoadSink(metrics.getReplicationLoadSink()));
123    }
124    builder.setCacheFreeSize(metrics.getCacheFreeSize());
125    return builder.build();
126  }
127
128  public static ServerMetricsBuilder newBuilder(ServerName sn) {
129    return new ServerMetricsBuilder(sn);
130  }
131
132  private final ServerName serverName;
133  private int versionNumber;
134  private String version = "0.0.0";
135  private long requestCountPerSecond;
136  private long requestCount;
137  private long readRequestCount;
138  private long writeRequestCount;
139  private Size usedHeapSize = Size.ZERO;
140  private Size maxHeapSize = Size.ZERO;
141  private int infoServerPort;
142  private List<ReplicationLoadSource> sources = Collections.emptyList();
143  @Nullable
144  private ReplicationLoadSink sink = null;
145  private final Map<byte[], RegionMetrics> regionStatus = new TreeMap<>(Bytes.BYTES_COMPARATOR);
146  private final Map<byte[], UserMetrics> userMetrics = new TreeMap<>(Bytes.BYTES_COMPARATOR);
147  private final Set<String> coprocessorNames = new TreeSet<>();
148  private long reportTimestamp = EnvironmentEdgeManager.currentTime();
149  private long lastReportTimestamp = 0;
150  private final List<ServerTask> tasks = new ArrayList<>();
151  private Map<String, Integer> regionCachedInfo = new HashMap<>();
152  private long cacheFreeSize;
153  private Map<String, Integer> regionColdDataInfo = Collections.emptyMap();
154
155  private ServerMetricsBuilder(ServerName serverName) {
156    this.serverName = serverName;
157  }
158
159  public ServerMetricsBuilder setVersionNumber(int versionNumber) {
160    this.versionNumber = versionNumber;
161    return this;
162  }
163
164  public ServerMetricsBuilder setVersion(String version) {
165    this.version = version;
166    return this;
167  }
168
169  public ServerMetricsBuilder setRequestCountPerSecond(long value) {
170    this.requestCountPerSecond = value;
171    return this;
172  }
173
174  public ServerMetricsBuilder setRequestCount(long value) {
175    this.requestCount = value;
176    return this;
177  }
178
179  public ServerMetricsBuilder setReadRequestCount(long value) {
180    this.readRequestCount = value;
181    return this;
182  }
183
184  public ServerMetricsBuilder setWriteRequestCount(long value) {
185    this.writeRequestCount = value;
186    return this;
187  }
188
189  public ServerMetricsBuilder setUsedHeapSize(Size value) {
190    this.usedHeapSize = value;
191    return this;
192  }
193
194  public ServerMetricsBuilder setMaxHeapSize(Size value) {
195    this.maxHeapSize = value;
196    return this;
197  }
198
199  public ServerMetricsBuilder setInfoServerPort(int value) {
200    this.infoServerPort = value;
201    return this;
202  }
203
204  public ServerMetricsBuilder setReplicationLoadSources(List<ReplicationLoadSource> value) {
205    this.sources = value;
206    return this;
207  }
208
209  public ServerMetricsBuilder setReplicationLoadSink(ReplicationLoadSink value) {
210    this.sink = value;
211    return this;
212  }
213
214  public ServerMetricsBuilder setRegionMetrics(List<RegionMetrics> value) {
215    value.forEach(v -> this.regionStatus.put(v.getRegionName(), v));
216    return this;
217  }
218
219  public ServerMetricsBuilder setUserMetrics(List<UserMetrics> value) {
220    value.forEach(v -> this.userMetrics.put(v.getUserName(), v));
221    return this;
222  }
223
224  public ServerMetricsBuilder setCoprocessorNames(List<String> value) {
225    coprocessorNames.addAll(value);
226    return this;
227  }
228
229  public ServerMetricsBuilder setReportTimestamp(long value) {
230    this.reportTimestamp = value;
231    return this;
232  }
233
234  public ServerMetricsBuilder setLastReportTimestamp(long value) {
235    this.lastReportTimestamp = value;
236    return this;
237  }
238
239  public ServerMetricsBuilder setTasks(List<ServerTask> tasks) {
240    this.tasks.addAll(tasks);
241    return this;
242  }
243
244  public ServerMetricsBuilder setRegionCachedInfo(Map<String, Integer> value) {
245    this.regionCachedInfo = value;
246    return this;
247  }
248
249  public ServerMetricsBuilder setCacheFreeSize(long blockCacheFreeSize) {
250    this.cacheFreeSize = blockCacheFreeSize;
251    return this;
252  }
253
254  public ServerMetricsBuilder setRegionColdDataInfo(Map<String, Integer> regionColdDataInfo) {
255    this.regionColdDataInfo = regionColdDataInfo;
256    return this;
257  }
258
259  public ServerMetrics build() {
260    return new ServerMetricsImpl(serverName, versionNumber, version, requestCountPerSecond,
261      requestCount, readRequestCount, writeRequestCount, usedHeapSize, maxHeapSize, infoServerPort,
262      sources, sink, regionStatus, coprocessorNames, reportTimestamp, lastReportTimestamp,
263      userMetrics, tasks, regionCachedInfo, cacheFreeSize, regionColdDataInfo);
264  }
265
266  private static class ServerMetricsImpl implements ServerMetrics {
267    private final ServerName serverName;
268    private final int versionNumber;
269    private final String version;
270    private final long requestCountPerSecond;
271    private final long requestCount;
272    private final long readRequestsCount;
273    private final long writeRequestsCount;
274    private final Size usedHeapSize;
275    private final Size maxHeapSize;
276    private final int infoServerPort;
277    private final List<ReplicationLoadSource> sources;
278    @Nullable
279    private final ReplicationLoadSink sink;
280    private final Map<byte[], RegionMetrics> regionStatus;
281    private final Set<String> coprocessorNames;
282    private final long reportTimestamp;
283    private final long lastReportTimestamp;
284    private final Map<byte[], UserMetrics> userMetrics;
285    private final List<ServerTask> tasks;
286    private final Map<String, Integer> regionCachedInfo;
287    private final long cacheFreeSize;
288    private final Map<String, Integer> regionColdDataInfo;
289
290    ServerMetricsImpl(ServerName serverName, int versionNumber, String version,
291      long requestCountPerSecond, long requestCount, long readRequestsCount,
292      long writeRequestsCount, Size usedHeapSize, Size maxHeapSize, int infoServerPort,
293      List<ReplicationLoadSource> sources, ReplicationLoadSink sink,
294      Map<byte[], RegionMetrics> regionStatus, Set<String> coprocessorNames, long reportTimestamp,
295      long lastReportTimestamp, Map<byte[], UserMetrics> userMetrics, List<ServerTask> tasks,
296      Map<String, Integer> regionCachedInfo, long cacheFreeSize,
297      Map<String, Integer> regionColdDataInfo) {
298      this.serverName = Preconditions.checkNotNull(serverName);
299      this.versionNumber = versionNumber;
300      this.version = version;
301      this.requestCountPerSecond = requestCountPerSecond;
302      this.requestCount = requestCount;
303      this.readRequestsCount = readRequestsCount;
304      this.writeRequestsCount = writeRequestsCount;
305      this.usedHeapSize = Preconditions.checkNotNull(usedHeapSize);
306      this.maxHeapSize = Preconditions.checkNotNull(maxHeapSize);
307      this.infoServerPort = infoServerPort;
308      this.sources = Preconditions.checkNotNull(sources);
309      this.sink = sink;
310      this.regionStatus = Preconditions.checkNotNull(regionStatus);
311      this.userMetrics = Preconditions.checkNotNull(userMetrics);
312      this.coprocessorNames = Preconditions.checkNotNull(coprocessorNames);
313      this.reportTimestamp = reportTimestamp;
314      this.lastReportTimestamp = lastReportTimestamp;
315      this.tasks = tasks;
316      this.regionCachedInfo = regionCachedInfo;
317      this.cacheFreeSize = cacheFreeSize;
318      this.regionColdDataInfo = regionColdDataInfo;
319    }
320
321    @Override
322    public ServerName getServerName() {
323      return serverName;
324    }
325
326    @Override
327    public int getVersionNumber() {
328      return versionNumber;
329    }
330
331    @Override
332    public String getVersion() {
333      return version;
334    }
335
336    @Override
337    public long getRequestCountPerSecond() {
338      return requestCountPerSecond;
339    }
340
341    @Override
342    public long getRequestCount() {
343      return requestCount;
344    }
345
346    @Override
347    public long getReadRequestsCount() {
348      return readRequestsCount;
349    }
350
351    @Override
352    public long getWriteRequestsCount() {
353      return writeRequestsCount;
354    }
355
356    @Override
357    public Size getUsedHeapSize() {
358      return usedHeapSize;
359    }
360
361    @Override
362    public Size getMaxHeapSize() {
363      return maxHeapSize;
364    }
365
366    @Override
367    public int getInfoServerPort() {
368      return infoServerPort;
369    }
370
371    @Override
372    public List<ReplicationLoadSource> getReplicationLoadSourceList() {
373      return Collections.unmodifiableList(sources);
374    }
375
376    @Override
377    public Map<String, List<ReplicationLoadSource>> getReplicationLoadSourceMap() {
378      Map<String, List<ReplicationLoadSource>> sourcesMap = new HashMap<>();
379      for (ReplicationLoadSource loadSource : sources) {
380        sourcesMap.computeIfAbsent(loadSource.getPeerID(), peerId -> new ArrayList<>())
381          .add(loadSource);
382      }
383      return sourcesMap;
384    }
385
386    @Override
387    public ReplicationLoadSink getReplicationLoadSink() {
388      return sink;
389    }
390
391    @Override
392    public Map<byte[], RegionMetrics> getRegionMetrics() {
393      return Collections.unmodifiableMap(regionStatus);
394    }
395
396    @Override
397    public Map<byte[], UserMetrics> getUserMetrics() {
398      return Collections.unmodifiableMap(userMetrics);
399    }
400
401    @Override
402    public Set<String> getCoprocessorNames() {
403      return Collections.unmodifiableSet(coprocessorNames);
404    }
405
406    @Override
407    public long getReportTimestamp() {
408      return reportTimestamp;
409    }
410
411    @Override
412    public long getLastReportTimestamp() {
413      return lastReportTimestamp;
414    }
415
416    @Override
417    public List<ServerTask> getTasks() {
418      return tasks;
419    }
420
421    @Override
422    public Map<String, Integer> getRegionCachedInfo() {
423      return Collections.unmodifiableMap(regionCachedInfo);
424    }
425
426    @Override
427    public long getCacheFreeSize() {
428      return cacheFreeSize;
429    }
430
431    @Override
432    public Map<String, Integer> getRegionColdDataSize() {
433      return Collections
434        .unmodifiableMap(regionColdDataInfo != null ? regionColdDataInfo : Collections.emptyMap());
435    }
436
437    @Override
438    public String toString() {
439      int storeCount = 0;
440      int storeFileCount = 0;
441      int storeRefCount = 0;
442      int maxCompactedStoreFileRefCount = 0;
443      long uncompressedStoreFileSizeMB = 0;
444      long storeFileSizeMB = 0;
445      long memStoreSizeMB = 0;
446      long storefileIndexSizeKB = 0;
447      long rootLevelIndexSizeKB = 0;
448      long readRequestsCount = 0;
449      long cpRequestsCount = 0;
450      long writeRequestsCount = 0;
451      long filteredReadRequestsCount = 0;
452      long bloomFilterSizeMB = 0;
453      long compactingCellCount = 0;
454      long compactedCellCount = 0;
455      for (RegionMetrics r : getRegionMetrics().values()) {
456        storeCount += r.getStoreCount();
457        storeFileCount += r.getStoreFileCount();
458        storeRefCount += r.getStoreRefCount();
459        int currentMaxCompactedStoreFileRefCount = r.getMaxCompactedStoreFileRefCount();
460        maxCompactedStoreFileRefCount =
461          Math.max(maxCompactedStoreFileRefCount, currentMaxCompactedStoreFileRefCount);
462        uncompressedStoreFileSizeMB +=
463          (long) r.getUncompressedStoreFileSize().get(Size.Unit.MEGABYTE);
464        storeFileSizeMB += (long) r.getStoreFileSize().get(Size.Unit.MEGABYTE);
465        memStoreSizeMB += (long) r.getMemStoreSize().get(Size.Unit.MEGABYTE);
466        storefileIndexSizeKB +=
467          (long) r.getStoreFileUncompressedDataIndexSize().get(Size.Unit.KILOBYTE);
468        readRequestsCount += r.getReadRequestCount();
469        cpRequestsCount += r.getCpRequestCount();
470        writeRequestsCount += r.getWriteRequestCount();
471        filteredReadRequestsCount += r.getFilteredReadRequestCount();
472        rootLevelIndexSizeKB += (long) r.getStoreFileRootLevelIndexSize().get(Size.Unit.KILOBYTE);
473        bloomFilterSizeMB += (long) r.getBloomFilterSize().get(Size.Unit.MEGABYTE);
474        compactedCellCount += r.getCompactedCellCount();
475        compactingCellCount += r.getCompactingCellCount();
476      }
477      StringBuilder sb = Strings.appendKeyValue(new StringBuilder(), "requestsPerSecond",
478        Double.valueOf(getRequestCountPerSecond()));
479      Strings.appendKeyValue(sb, "numberOfOnlineRegions",
480        Integer.valueOf(getRegionMetrics().size()));
481      Strings.appendKeyValue(sb, "usedHeapMB", getUsedHeapSize());
482      Strings.appendKeyValue(sb, "maxHeapMB", getMaxHeapSize());
483      Strings.appendKeyValue(sb, "numberOfStores", storeCount);
484      Strings.appendKeyValue(sb, "numberOfStorefiles", storeFileCount);
485      Strings.appendKeyValue(sb, "storeRefCount", storeRefCount);
486      Strings.appendKeyValue(sb, "maxCompactedStoreFileRefCount", maxCompactedStoreFileRefCount);
487      Strings.appendKeyValue(sb, "storefileUncompressedSizeMB", uncompressedStoreFileSizeMB);
488      Strings.appendKeyValue(sb, "storefileSizeMB", storeFileSizeMB);
489      if (uncompressedStoreFileSizeMB != 0) {
490        Strings.appendKeyValue(sb, "compressionRatio",
491          String.format("%.4f", (float) storeFileSizeMB / (float) uncompressedStoreFileSizeMB));
492      }
493      Strings.appendKeyValue(sb, "memstoreSizeMB", memStoreSizeMB);
494      Strings.appendKeyValue(sb, "readRequestsCount", readRequestsCount);
495      Strings.appendKeyValue(sb, "cpRequestsCount", cpRequestsCount);
496      Strings.appendKeyValue(sb, "filteredReadRequestsCount", filteredReadRequestsCount);
497      Strings.appendKeyValue(sb, "writeRequestsCount", writeRequestsCount);
498      Strings.appendKeyValue(sb, "rootIndexSizeKB", rootLevelIndexSizeKB);
499      Strings.appendKeyValue(sb, "totalStaticIndexSizeKB", storefileIndexSizeKB);
500      Strings.appendKeyValue(sb, "totalStaticBloomSizeKB", bloomFilterSizeMB);
501      Strings.appendKeyValue(sb, "totalCompactingKVs", compactingCellCount);
502      Strings.appendKeyValue(sb, "currentCompactedKVs", compactedCellCount);
503      float compactionProgressPct = Float.NaN;
504      if (compactingCellCount > 0) {
505        compactionProgressPct = Float.valueOf((float) compactedCellCount / compactingCellCount);
506      }
507      Strings.appendKeyValue(sb, "compactionProgressPct", compactionProgressPct);
508      Strings.appendKeyValue(sb, "coprocessors", getCoprocessorNames());
509      return sb.toString();
510    }
511  }
512}