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, 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    return ServerMetricsBuilder.newBuilder(serverName)
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).collect(Collectors.toList()))
077      .setReplicationLoadSources(serverLoadPB.getReplLoadSourceList().stream()
078        .map(ProtobufUtil::toReplicationLoadSource).collect(Collectors.toList()))
079      .setReplicationLoadSink(serverLoadPB.hasReplLoadSink()
080        ? ProtobufUtil.toReplicationLoadSink(serverLoadPB.getReplLoadSink())
081        : null)
082      .setReportTimestamp(serverLoadPB.getReportEndTime())
083      .setLastReportTimestamp(serverLoadPB.getReportStartTime()).setVersionNumber(versionNumber)
084      .setVersion(version).build();
085  }
086
087  public static List<HBaseProtos.Coprocessor> toCoprocessor(Collection<String> names) {
088    return names.stream()
089        .map(n -> HBaseProtos.Coprocessor.newBuilder().setName(n).build())
090        .collect(Collectors.toList());
091  }
092
093  public static ClusterStatusProtos.ServerLoad toServerLoad(ServerMetrics metrics) {
094    ClusterStatusProtos.ServerLoad.Builder builder = ClusterStatusProtos.ServerLoad.newBuilder()
095        .setNumberOfRequests(metrics.getRequestCountPerSecond())
096        .setTotalNumberOfRequests(metrics.getRequestCount())
097        .setInfoServerPort(metrics.getInfoServerPort())
098        .setMaxHeapMB((int) metrics.getMaxHeapSize().get(Size.Unit.MEGABYTE))
099        .setUsedHeapMB((int) metrics.getUsedHeapSize().get(Size.Unit.MEGABYTE))
100        .addAllCoprocessors(toCoprocessor(metrics.getCoprocessorNames()))
101        .addAllRegionLoads(metrics.getRegionMetrics().values().stream()
102            .map(RegionMetricsBuilder::toRegionLoad)
103            .collect(Collectors.toList()))
104        .addAllReplLoadSource(metrics.getReplicationLoadSourceList().stream()
105            .map(ProtobufUtil::toReplicationLoadSource)
106            .collect(Collectors.toList()))
107        .setReportStartTime(metrics.getLastReportTimestamp())
108        .setReportEndTime(metrics.getReportTimestamp());
109    if (metrics.getReplicationLoadSink() != null) {
110      builder.setReplLoadSink(ProtobufUtil.toReplicationLoadSink(
111          metrics.getReplicationLoadSink()));
112    }
113    return builder.build();
114  }
115
116  public static ServerMetricsBuilder newBuilder(ServerName sn) {
117    return new ServerMetricsBuilder(sn);
118  }
119
120  private final ServerName serverName;
121  private int versionNumber;
122  private String version = "0.0.0";
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 setVersion(String version) {
145    this.version = version;
146    return this;
147  }
148
149  public ServerMetricsBuilder setRequestCountPerSecond(long value) {
150    this.requestCountPerSecond = value;
151    return this;
152  }
153
154  public ServerMetricsBuilder setRequestCount(long value) {
155    this.requestCount = value;
156    return this;
157  }
158
159  public ServerMetricsBuilder setUsedHeapSize(Size value) {
160    this.usedHeapSize = value;
161    return this;
162  }
163
164  public ServerMetricsBuilder setMaxHeapSize(Size value) {
165    this.maxHeapSize = value;
166    return this;
167  }
168
169  public ServerMetricsBuilder setInfoServerPort(int value) {
170    this.infoServerPort = value;
171    return this;
172  }
173
174  public ServerMetricsBuilder setReplicationLoadSources(List<ReplicationLoadSource> value) {
175    this.sources = value;
176    return this;
177  }
178
179  public ServerMetricsBuilder setReplicationLoadSink(ReplicationLoadSink value) {
180    this.sink = value;
181    return this;
182  }
183
184  public ServerMetricsBuilder setRegionMetrics(List<RegionMetrics> value) {
185    value.forEach(v -> this.regionStatus.put(v.getRegionName(), v));
186    return this;
187  }
188
189  public ServerMetricsBuilder setCoprocessorNames(List<String> value) {
190    coprocessorNames.addAll(value);
191    return this;
192  }
193
194  public ServerMetricsBuilder setReportTimestamp(long value) {
195    this.reportTimestamp = value;
196    return this;
197  }
198
199  public ServerMetricsBuilder setLastReportTimestamp(long value) {
200    this.lastReportTimestamp = value;
201    return this;
202  }
203
204  public ServerMetrics build() {
205    return new ServerMetricsImpl(
206        serverName,
207        versionNumber,
208        version,
209        requestCountPerSecond,
210        requestCount,
211        usedHeapSize,
212        maxHeapSize,
213        infoServerPort,
214        sources,
215        sink,
216        regionStatus,
217        coprocessorNames,
218        reportTimestamp,
219        lastReportTimestamp);
220  }
221
222  private static class ServerMetricsImpl implements ServerMetrics {
223    private final ServerName serverName;
224    private final int versionNumber;
225    private final String version;
226    private final long requestCountPerSecond;
227    private final long requestCount;
228    private final Size usedHeapSize;
229    private final Size maxHeapSize;
230    private final int infoServerPort;
231    private final List<ReplicationLoadSource> sources;
232    @Nullable
233    private final ReplicationLoadSink sink;
234    private final Map<byte[], RegionMetrics> regionStatus;
235    private final Set<String> coprocessorNames;
236    private final long reportTimestamp;
237    private final long lastReportTimestamp;
238
239    ServerMetricsImpl(ServerName serverName, int versionNumber, String version,
240        long requestCountPerSecond, long requestCount, Size usedHeapSize, Size maxHeapSize,
241        int infoServerPort, List<ReplicationLoadSource> sources, ReplicationLoadSink sink,
242        Map<byte[], RegionMetrics> regionStatus, Set<String> coprocessorNames, long reportTimestamp,
243        long lastReportTimestamp) {
244      this.serverName = Preconditions.checkNotNull(serverName);
245      this.versionNumber = versionNumber;
246      this.version = version;
247      this.requestCountPerSecond = requestCountPerSecond;
248      this.requestCount = requestCount;
249      this.usedHeapSize = Preconditions.checkNotNull(usedHeapSize);
250      this.maxHeapSize = Preconditions.checkNotNull(maxHeapSize);
251      this.infoServerPort = infoServerPort;
252      this.sources = Preconditions.checkNotNull(sources);
253      this.sink = sink;
254      this.regionStatus = Preconditions.checkNotNull(regionStatus);
255      this.coprocessorNames =Preconditions.checkNotNull(coprocessorNames);
256      this.reportTimestamp = reportTimestamp;
257      this.lastReportTimestamp = lastReportTimestamp;
258    }
259
260    @Override
261    public ServerName getServerName() {
262      return serverName;
263    }
264
265    @Override
266    public int getVersionNumber() {
267      return versionNumber;
268    }
269
270    public String getVersion() {
271      return version;
272    }
273
274    @Override
275    public long getRequestCountPerSecond() {
276      return requestCountPerSecond;
277    }
278
279    @Override
280    public long getRequestCount() {
281      return requestCount;
282    }
283
284    @Override
285    public Size getUsedHeapSize() {
286      return usedHeapSize;
287    }
288
289    @Override
290    public Size getMaxHeapSize() {
291      return maxHeapSize;
292    }
293
294    @Override
295    public int getInfoServerPort() {
296      return infoServerPort;
297    }
298
299    @Override
300    public List<ReplicationLoadSource> getReplicationLoadSourceList() {
301      return Collections.unmodifiableList(sources);
302    }
303
304    @Override
305    public ReplicationLoadSink getReplicationLoadSink() {
306      return sink;
307    }
308
309    @Override
310    public Map<byte[], RegionMetrics> getRegionMetrics() {
311      return Collections.unmodifiableMap(regionStatus);
312    }
313
314    @Override
315    public Set<String> getCoprocessorNames() {
316      return Collections.unmodifiableSet(coprocessorNames);
317    }
318
319    @Override
320    public long getReportTimestamp() {
321      return reportTimestamp;
322    }
323
324    @Override
325    public long getLastReportTimestamp() {
326      return lastReportTimestamp;
327    }
328
329    @Override
330    public String toString() {
331      int storeCount = 0;
332      int storeFileCount = 0;
333      long uncompressedStoreFileSizeMB = 0;
334      long storeFileSizeMB = 0;
335      long memStoreSizeMB = 0;
336      long storefileIndexSizeKB = 0;
337      long rootLevelIndexSizeKB = 0;
338      long readRequestsCount = 0;
339      long writeRequestsCount = 0;
340      long filteredReadRequestsCount = 0;
341      long bloomFilterSizeMB = 0;
342      long compactingCellCount = 0;
343      long compactedCellCount = 0;
344      for (RegionMetrics r : getRegionMetrics().values()) {
345        storeCount += r.getStoreCount();
346        storeFileCount += r.getStoreFileCount();
347        uncompressedStoreFileSizeMB += r.getUncompressedStoreFileSize().get(Size.Unit.MEGABYTE);
348        storeFileSizeMB += r.getStoreFileSize().get(Size.Unit.MEGABYTE);
349        memStoreSizeMB += r.getMemStoreSize().get(Size.Unit.MEGABYTE);
350        storefileIndexSizeKB += r.getStoreFileUncompressedDataIndexSize().get(Size.Unit.KILOBYTE);
351        readRequestsCount += r.getReadRequestCount();
352        writeRequestsCount += r.getWriteRequestCount();
353        filteredReadRequestsCount += r.getFilteredReadRequestCount();
354        rootLevelIndexSizeKB += r.getStoreFileRootLevelIndexSize().get(Size.Unit.KILOBYTE);
355        bloomFilterSizeMB += r.getBloomFilterSize().get(Size.Unit.MEGABYTE);
356        compactedCellCount += r.getCompactedCellCount();
357        compactingCellCount += r.getCompactingCellCount();
358      }
359      StringBuilder sb = Strings.appendKeyValue(new StringBuilder(), "requestsPerSecond",
360            Double.valueOf(getRequestCountPerSecond()));
361      Strings.appendKeyValue(sb, "numberOfOnlineRegions",
362          Integer.valueOf(getRegionMetrics().size()));
363      Strings.appendKeyValue(sb, "usedHeapMB", getUsedHeapSize());
364      Strings.appendKeyValue(sb, "maxHeapMB", getMaxHeapSize());
365      Strings.appendKeyValue(sb, "numberOfStores", storeCount);
366      Strings.appendKeyValue(sb, "numberOfStorefiles", storeFileCount);
367      Strings.appendKeyValue(sb, "storefileUncompressedSizeMB", uncompressedStoreFileSizeMB);
368      Strings.appendKeyValue(sb, "storefileSizeMB", storeFileSizeMB);
369      if (uncompressedStoreFileSizeMB != 0) {
370        Strings.appendKeyValue(sb, "compressionRatio", String.format("%.4f",
371            (float) storeFileSizeMB / (float) uncompressedStoreFileSizeMB));
372      }
373      Strings.appendKeyValue(sb, "memstoreSizeMB", memStoreSizeMB);
374      Strings.appendKeyValue(sb, "readRequestsCount", readRequestsCount);
375      Strings.appendKeyValue(sb, "filteredReadRequestsCount", filteredReadRequestsCount);
376      Strings.appendKeyValue(sb, "writeRequestsCount", writeRequestsCount);
377      Strings.appendKeyValue(sb, "rootIndexSizeKB", rootLevelIndexSizeKB);
378      Strings.appendKeyValue(sb, "totalStaticIndexSizeKB", storefileIndexSizeKB);
379      Strings.appendKeyValue(sb, "totalStaticBloomSizeKB", bloomFilterSizeMB);
380      Strings.appendKeyValue(sb, "totalCompactingKVs", compactingCellCount);
381      Strings.appendKeyValue(sb, "currentCompactedKVs", compactedCellCount);
382      float compactionProgressPct = Float.NaN;
383      if (compactingCellCount > 0) {
384        compactionProgressPct =
385            Float.valueOf((float) compactedCellCount / compactingCellCount);
386      }
387      Strings.appendKeyValue(sb, "compactionProgressPct", compactionProgressPct);
388      Strings.appendKeyValue(sb, "coprocessors", getCoprocessorNames());
389      return sb.toString();
390    }
391  }
392}