001/**
002 * Copyright The Apache Software Foundation
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 * http://www.apache.org/licenses/LICENSE-2.0
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.hadoop.hbase;
019
020import edu.umd.cs.findbugs.annotations.Nullable;
021import java.util.Collection;
022import java.util.Collections;
023import java.util.List;
024import java.util.Map;
025import java.util.Set;
026import java.util.TreeMap;
027import java.util.TreeSet;
028import java.util.stream.Collectors;
029import org.apache.hadoop.hbase.replication.ReplicationLoadSink;
030import org.apache.hadoop.hbase.replication.ReplicationLoadSource;
031import org.apache.hadoop.hbase.util.Bytes;
032import org.apache.hadoop.hbase.util.Strings;
033import org.apache.yetus.audience.InterfaceAudience;
034
035import org.apache.hbase.thirdparty.com.google.common.base.Preconditions;
036import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
037import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos;
038import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
039
040@InterfaceAudience.Private
041public final class ServerMetricsBuilder {
042
043  /**
044   * @param sn the server name
045   * @return a empty metrics
046   */
047  public static ServerMetrics of(ServerName sn) {
048    return newBuilder(sn).build();
049  }
050
051  public static ServerMetrics of(ServerName sn, int versionNumber) {
052    return newBuilder(sn).setVersionNumber(versionNumber).build();
053  }
054
055  public static ServerMetrics toServerMetrics(ClusterStatusProtos.LiveServerInfo serverInfo) {
056    return toServerMetrics(ProtobufUtil.toServerName(serverInfo.getServer()), 0,
057        serverInfo.getServerLoad());
058  }
059
060  public static ServerMetrics toServerMetrics(ServerName serverName,
061      ClusterStatusProtos.ServerLoad serverLoadPB) {
062    return toServerMetrics(serverName, 0, serverLoadPB);
063  }
064
065  public static ServerMetrics toServerMetrics(ServerName serverName, int versionNumber,
066      ClusterStatusProtos.ServerLoad serverLoadPB) {
067    return ServerMetricsBuilder.newBuilder(serverName).setVersionNumber(versionNumber)
068        .setRequestCountPerSecond(serverLoadPB.getNumberOfRequests())
069        .setRequestCount(serverLoadPB.getTotalNumberOfRequests())
070        .setInfoServerPort(serverLoadPB.getInfoServerPort())
071        .setMaxHeapSize(new Size(serverLoadPB.getMaxHeapMB(), Size.Unit.MEGABYTE))
072        .setUsedHeapSize(new Size(serverLoadPB.getUsedHeapMB(), Size.Unit.MEGABYTE))
073        .setCoprocessorNames(serverLoadPB.getCoprocessorsList().stream()
074            .map(HBaseProtos.Coprocessor::getName).collect(Collectors.toList()))
075        .setRegionMetrics(serverLoadPB.getRegionLoadsList().stream()
076            .map(RegionMetricsBuilder::toRegionMetrics)
077            .collect(Collectors.toList()))
078        .setReplicationLoadSources(serverLoadPB.getReplLoadSourceList().stream()
079            .map(ProtobufUtil::toReplicationLoadSource)
080            .collect(Collectors.toList()))
081        .setReplicationLoadSink(serverLoadPB.hasReplLoadSink() ?
082            ProtobufUtil.toReplicationLoadSink(serverLoadPB.getReplLoadSink()) : null)
083        .setReportTimestamp(serverLoadPB.getReportEndTime())
084        .setLastReportTimestamp(serverLoadPB.getReportStartTime())
085        .build();
086  }
087
088  public static List<HBaseProtos.Coprocessor> toCoprocessor(Collection<String> names) {
089    return names.stream()
090        .map(n -> HBaseProtos.Coprocessor.newBuilder().setName(n).build())
091        .collect(Collectors.toList());
092  }
093
094  public static ClusterStatusProtos.ServerLoad toServerLoad(ServerMetrics metrics) {
095    ClusterStatusProtos.ServerLoad.Builder builder = ClusterStatusProtos.ServerLoad.newBuilder()
096        .setNumberOfRequests(metrics.getRequestCountPerSecond())
097        .setTotalNumberOfRequests(metrics.getRequestCount())
098        .setInfoServerPort(metrics.getInfoServerPort())
099        .setMaxHeapMB((int) metrics.getMaxHeapSize().get(Size.Unit.MEGABYTE))
100        .setUsedHeapMB((int) metrics.getUsedHeapSize().get(Size.Unit.MEGABYTE))
101        .addAllCoprocessors(toCoprocessor(metrics.getCoprocessorNames()))
102        .addAllRegionLoads(metrics.getRegionMetrics().values().stream()
103            .map(RegionMetricsBuilder::toRegionLoad)
104            .collect(Collectors.toList()))
105        .addAllReplLoadSource(metrics.getReplicationLoadSourceList().stream()
106            .map(ProtobufUtil::toReplicationLoadSource)
107            .collect(Collectors.toList()))
108        .setReportStartTime(metrics.getLastReportTimestamp())
109        .setReportEndTime(metrics.getReportTimestamp());
110    if (metrics.getReplicationLoadSink() != null) {
111      builder.setReplLoadSink(ProtobufUtil.toReplicationLoadSink(
112          metrics.getReplicationLoadSink()));
113    }
114    return builder.build();
115  }
116
117  public static ServerMetricsBuilder newBuilder(ServerName sn) {
118    return new ServerMetricsBuilder(sn);
119  }
120
121  private final ServerName serverName;
122  private int versionNumber;
123  private long requestCountPerSecond;
124  private long requestCount;
125  private Size usedHeapSize = Size.ZERO;
126  private Size maxHeapSize = Size.ZERO;
127  private int infoServerPort;
128  private List<ReplicationLoadSource> sources = Collections.emptyList();
129  @Nullable
130  private ReplicationLoadSink sink = null;
131  private final Map<byte[], RegionMetrics> regionStatus = new TreeMap<>(Bytes.BYTES_COMPARATOR);
132  private final Set<String> coprocessorNames = new TreeSet<>();
133  private long reportTimestamp = System.currentTimeMillis();
134  private long lastReportTimestamp = 0;
135  private ServerMetricsBuilder(ServerName serverName) {
136    this.serverName = serverName;
137  }
138
139  public ServerMetricsBuilder setVersionNumber(int versionNumber) {
140    this.versionNumber = versionNumber;
141    return this;
142  }
143
144  public ServerMetricsBuilder setRequestCountPerSecond(long value) {
145    this.requestCountPerSecond = value;
146    return this;
147  }
148
149  public ServerMetricsBuilder setRequestCount(long value) {
150    this.requestCount = value;
151    return this;
152  }
153
154  public ServerMetricsBuilder setUsedHeapSize(Size value) {
155    this.usedHeapSize = value;
156    return this;
157  }
158
159  public ServerMetricsBuilder setMaxHeapSize(Size value) {
160    this.maxHeapSize = value;
161    return this;
162  }
163
164  public ServerMetricsBuilder setInfoServerPort(int value) {
165    this.infoServerPort = value;
166    return this;
167  }
168
169  public ServerMetricsBuilder setReplicationLoadSources(List<ReplicationLoadSource> value) {
170    this.sources = value;
171    return this;
172  }
173
174  public ServerMetricsBuilder setReplicationLoadSink(ReplicationLoadSink value) {
175    this.sink = value;
176    return this;
177  }
178
179  public ServerMetricsBuilder setRegionMetrics(List<RegionMetrics> value) {
180    value.forEach(v -> this.regionStatus.put(v.getRegionName(), v));
181    return this;
182  }
183
184  public ServerMetricsBuilder setCoprocessorNames(List<String> value) {
185    coprocessorNames.addAll(value);
186    return this;
187  }
188
189  public ServerMetricsBuilder setReportTimestamp(long value) {
190    this.reportTimestamp = value;
191    return this;
192  }
193
194  public ServerMetricsBuilder setLastReportTimestamp(long value) {
195    this.lastReportTimestamp = value;
196    return this;
197  }
198
199  public ServerMetrics build() {
200    return new ServerMetricsImpl(
201        serverName,
202        versionNumber,
203        requestCountPerSecond,
204        requestCount,
205        usedHeapSize,
206        maxHeapSize,
207        infoServerPort,
208        sources,
209        sink,
210        regionStatus,
211        coprocessorNames,
212        reportTimestamp,
213        lastReportTimestamp);
214  }
215
216  private static class ServerMetricsImpl implements ServerMetrics {
217    private final ServerName serverName;
218    private final int versionNumber;
219    private final long requestCountPerSecond;
220    private final long requestCount;
221    private final Size usedHeapSize;
222    private final Size maxHeapSize;
223    private final int infoServerPort;
224    private final List<ReplicationLoadSource> sources;
225    @Nullable
226    private final ReplicationLoadSink sink;
227    private final Map<byte[], RegionMetrics> regionStatus;
228    private final Set<String> coprocessorNames;
229    private final long reportTimestamp;
230    private final long lastReportTimestamp;
231
232    ServerMetricsImpl(ServerName serverName, int versionNumber, long requestCountPerSecond,
233        long requestCount, Size usedHeapSize, Size maxHeapSize, int infoServerPort,
234        List<ReplicationLoadSource> sources, ReplicationLoadSink sink,
235        Map<byte[], RegionMetrics> regionStatus, Set<String> coprocessorNames, long reportTimestamp,
236        long lastReportTimestamp) {
237      this.serverName = Preconditions.checkNotNull(serverName);
238      this.versionNumber = versionNumber;
239      this.requestCountPerSecond = requestCountPerSecond;
240      this.requestCount = requestCount;
241      this.usedHeapSize = Preconditions.checkNotNull(usedHeapSize);
242      this.maxHeapSize = Preconditions.checkNotNull(maxHeapSize);
243      this.infoServerPort = infoServerPort;
244      this.sources = Preconditions.checkNotNull(sources);
245      this.sink = sink;
246      this.regionStatus = Preconditions.checkNotNull(regionStatus);
247      this.coprocessorNames =Preconditions.checkNotNull(coprocessorNames);
248      this.reportTimestamp = reportTimestamp;
249      this.lastReportTimestamp = lastReportTimestamp;
250    }
251
252    @Override
253    public ServerName getServerName() {
254      return serverName;
255    }
256
257    @Override
258    public int getVersionNumber() {
259      return versionNumber;
260    }
261
262    @Override
263    public long getRequestCountPerSecond() {
264      return requestCountPerSecond;
265    }
266
267    @Override
268    public long getRequestCount() {
269      return requestCount;
270    }
271
272    @Override
273    public Size getUsedHeapSize() {
274      return usedHeapSize;
275    }
276
277    @Override
278    public Size getMaxHeapSize() {
279      return maxHeapSize;
280    }
281
282    @Override
283    public int getInfoServerPort() {
284      return infoServerPort;
285    }
286
287    @Override
288    public List<ReplicationLoadSource> getReplicationLoadSourceList() {
289      return Collections.unmodifiableList(sources);
290    }
291
292    @Override
293    public ReplicationLoadSink getReplicationLoadSink() {
294      return sink;
295    }
296
297    @Override
298    public Map<byte[], RegionMetrics> getRegionMetrics() {
299      return Collections.unmodifiableMap(regionStatus);
300    }
301
302    @Override
303    public Set<String> getCoprocessorNames() {
304      return Collections.unmodifiableSet(coprocessorNames);
305    }
306
307    @Override
308    public long getReportTimestamp() {
309      return reportTimestamp;
310    }
311
312    @Override
313    public long getLastReportTimestamp() {
314      return lastReportTimestamp;
315    }
316
317    @Override
318    public String toString() {
319      int storeCount = 0;
320      int storeFileCount = 0;
321      long uncompressedStoreFileSizeMB = 0;
322      long storeFileSizeMB = 0;
323      long memStoreSizeMB = 0;
324      long storefileIndexSizeKB = 0;
325      long rootLevelIndexSizeKB = 0;
326      long readRequestsCount = 0;
327      long writeRequestsCount = 0;
328      long filteredReadRequestsCount = 0;
329      long bloomFilterSizeMB = 0;
330      long compactingCellCount = 0;
331      long compactedCellCount = 0;
332      for (RegionMetrics r : getRegionMetrics().values()) {
333        storeCount += r.getStoreCount();
334        storeFileCount += r.getStoreFileCount();
335        uncompressedStoreFileSizeMB += r.getUncompressedStoreFileSize().get(Size.Unit.MEGABYTE);
336        storeFileSizeMB += r.getStoreFileSize().get(Size.Unit.MEGABYTE);
337        memStoreSizeMB += r.getMemStoreSize().get(Size.Unit.MEGABYTE);
338        storefileIndexSizeKB += r.getStoreFileUncompressedDataIndexSize().get(Size.Unit.KILOBYTE);
339        readRequestsCount += r.getReadRequestCount();
340        writeRequestsCount += r.getWriteRequestCount();
341        filteredReadRequestsCount += r.getFilteredReadRequestCount();
342        rootLevelIndexSizeKB += r.getStoreFileRootLevelIndexSize().get(Size.Unit.KILOBYTE);
343        bloomFilterSizeMB += r.getBloomFilterSize().get(Size.Unit.MEGABYTE);
344        compactedCellCount += r.getCompactedCellCount();
345        compactingCellCount += r.getCompactingCellCount();
346      }
347      StringBuilder sb = Strings.appendKeyValue(new StringBuilder(), "requestsPerSecond",
348            Double.valueOf(getRequestCountPerSecond()));
349      Strings.appendKeyValue(sb, "numberOfOnlineRegions",
350          Integer.valueOf(getRegionMetrics().size()));
351      Strings.appendKeyValue(sb, "usedHeapMB", getUsedHeapSize());
352      Strings.appendKeyValue(sb, "maxHeapMB", getMaxHeapSize());
353      Strings.appendKeyValue(sb, "numberOfStores", storeCount);
354      Strings.appendKeyValue(sb, "numberOfStorefiles", storeFileCount);
355      Strings.appendKeyValue(sb, "storefileUncompressedSizeMB", uncompressedStoreFileSizeMB);
356      Strings.appendKeyValue(sb, "storefileSizeMB", storeFileSizeMB);
357      if (uncompressedStoreFileSizeMB != 0) {
358        Strings.appendKeyValue(sb, "compressionRatio", String.format("%.4f",
359            (float) storeFileSizeMB / (float) uncompressedStoreFileSizeMB));
360      }
361      Strings.appendKeyValue(sb, "memstoreSizeMB", memStoreSizeMB);
362      Strings.appendKeyValue(sb, "readRequestsCount", readRequestsCount);
363      Strings.appendKeyValue(sb, "filteredReadRequestsCount", filteredReadRequestsCount);
364      Strings.appendKeyValue(sb, "writeRequestsCount", writeRequestsCount);
365      Strings.appendKeyValue(sb, "rootIndexSizeKB", rootLevelIndexSizeKB);
366      Strings.appendKeyValue(sb, "totalStaticIndexSizeKB", storefileIndexSizeKB);
367      Strings.appendKeyValue(sb, "totalStaticBloomSizeKB", bloomFilterSizeMB);
368      Strings.appendKeyValue(sb, "totalCompactingKVs", compactingCellCount);
369      Strings.appendKeyValue(sb, "currentCompactedKVs", compactedCellCount);
370      float compactionProgressPct = Float.NaN;
371      if (compactingCellCount > 0) {
372        compactionProgressPct =
373            Float.valueOf((float) compactedCellCount / compactingCellCount);
374      }
375      Strings.appendKeyValue(sb, "compactionProgressPct", compactionProgressPct);
376      Strings.appendKeyValue(sb, "coprocessors", getCoprocessorNames());
377      return sb.toString();
378    }
379  }
380}