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