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 */
018
019package org.apache.hadoop.hbase.regionserver.wal;
020
021import java.util.concurrent.ConcurrentHashMap;
022import java.util.concurrent.ConcurrentMap;
023import org.apache.hadoop.hbase.TableName;
024import org.apache.hadoop.hbase.metrics.BaseSourceImpl;
025import org.apache.hadoop.metrics2.MetricHistogram;
026import org.apache.hadoop.metrics2.lib.MutableFastCounter;
027import org.apache.yetus.audience.InterfaceAudience;
028
029/**
030 * Class that transitions metrics from MetricsWAL into the metrics subsystem.
031 *
032 * Implements BaseSource through BaseSourceImpl, following the pattern.
033 * @see org.apache.hadoop.hbase.regionserver.wal.MetricsWALSource
034 */
035@InterfaceAudience.Private
036public class MetricsWALSourceImpl extends BaseSourceImpl implements MetricsWALSource {
037
038  private final MetricHistogram appendSizeHisto;
039  private final MetricHistogram appendTimeHisto;
040  private final MetricHistogram syncTimeHisto;
041  private final MutableFastCounter appendCount;
042  private final MutableFastCounter slowAppendCount;
043  private final MutableFastCounter logRollRequested;
044  private final MutableFastCounter errorRollRequested;
045  private final MutableFastCounter lowReplicationRollRequested;
046  private final MutableFastCounter slowSyncRollRequested;
047  private final MutableFastCounter sizeRollRequested;
048  private final MutableFastCounter writtenBytes;
049  // Per table metrics.
050  private final ConcurrentMap<TableName, MutableFastCounter> perTableAppendCount;
051  private final ConcurrentMap<TableName, MutableFastCounter> perTableAppendSize;
052
053  public MetricsWALSourceImpl() {
054    this(METRICS_NAME, METRICS_DESCRIPTION, METRICS_CONTEXT, METRICS_JMX_CONTEXT);
055  }
056
057  public MetricsWALSourceImpl(String metricsName,
058                              String metricsDescription,
059                              String metricsContext,
060                              String metricsJmxContext) {
061    super(metricsName, metricsDescription, metricsContext, metricsJmxContext);
062
063    //Create and store the metrics that will be used.
064    appendTimeHisto = this.getMetricsRegistry().newTimeHistogram(APPEND_TIME, APPEND_TIME_DESC);
065    appendSizeHisto = this.getMetricsRegistry().newSizeHistogram(APPEND_SIZE, APPEND_SIZE_DESC);
066    appendCount = this.getMetricsRegistry().newCounter(APPEND_COUNT, APPEND_COUNT_DESC, 0L);
067    slowAppendCount =
068        this.getMetricsRegistry().newCounter(SLOW_APPEND_COUNT, SLOW_APPEND_COUNT_DESC, 0L);
069    syncTimeHisto = this.getMetricsRegistry().newTimeHistogram(SYNC_TIME, SYNC_TIME_DESC);
070    logRollRequested =
071        this.getMetricsRegistry().newCounter(ROLL_REQUESTED, ROLL_REQUESTED_DESC, 0L);
072    errorRollRequested = this.getMetricsRegistry()
073        .newCounter(ERROR_ROLL_REQUESTED, ERROR_ROLL_REQUESTED_DESC, 0L);
074    lowReplicationRollRequested = this.getMetricsRegistry()
075        .newCounter(LOW_REPLICA_ROLL_REQUESTED, LOW_REPLICA_ROLL_REQUESTED_DESC, 0L);
076    slowSyncRollRequested = this.getMetricsRegistry()
077        .newCounter(SLOW_SYNC_ROLL_REQUESTED, SLOW_SYNC_ROLL_REQUESTED_DESC, 0L);
078    sizeRollRequested = this.getMetricsRegistry()
079        .newCounter(SIZE_ROLL_REQUESTED, SIZE_ROLL_REQUESTED_DESC, 0L);
080    writtenBytes = this.getMetricsRegistry().newCounter(WRITTEN_BYTES, WRITTEN_BYTES_DESC, 0L);
081    perTableAppendCount = new ConcurrentHashMap<>();
082    perTableAppendSize = new ConcurrentHashMap<>();
083  }
084
085  @Override
086  public void incrementAppendSize(TableName tableName, long size) {
087    appendSizeHisto.add(size);
088    MutableFastCounter tableAppendSizeCounter = perTableAppendSize.get(tableName);
089    if (tableAppendSizeCounter == null) {
090      // Ideally putIfAbsent is atomic and we don't need a branch check but we still do it to avoid
091      // expensive string construction for every append.
092      String metricsKey = String.format("%s.%s", tableName, APPEND_SIZE);
093      perTableAppendSize.putIfAbsent(
094          tableName, getMetricsRegistry().newCounter(metricsKey, APPEND_SIZE_DESC, 0L));
095      tableAppendSizeCounter = perTableAppendSize.get(tableName);
096    }
097    tableAppendSizeCounter.incr(size);
098  }
099
100  @Override
101  public void incrementAppendTime(long time) {
102    appendTimeHisto.add(time);
103  }
104
105  @Override
106  public void incrementAppendCount(TableName tableName) {
107    appendCount.incr();
108    MutableFastCounter tableAppendCounter = perTableAppendCount.get(tableName);
109    if (tableAppendCounter == null) {
110      String metricsKey = String.format("%s.%s", tableName, APPEND_COUNT);
111      perTableAppendCount.putIfAbsent(
112          tableName, getMetricsRegistry().newCounter(metricsKey, APPEND_COUNT_DESC, 0L));
113      tableAppendCounter = perTableAppendCount.get(tableName);
114    }
115    tableAppendCounter.incr();
116  }
117
118  @Override
119  public void incrementSlowAppendCount() {
120    slowAppendCount.incr();
121  }
122
123  @Override
124  public void incrementSyncTime(long time) {
125    syncTimeHisto.add(time);
126  }
127
128  @Override
129  public void incrementLogRollRequested() {
130    logRollRequested.incr();
131  }
132
133  @Override
134  public void incrementErrorLogRoll() {
135    errorRollRequested.incr();
136  }
137
138  @Override
139  public void incrementLowReplicationLogRoll() {
140    lowReplicationRollRequested.incr();
141  }
142
143  @Override
144  public void incrementSlowSyncLogRoll() {
145    slowSyncRollRequested.incr();
146  }
147
148  @Override
149  public void incrementSizeLogRoll() {
150    sizeRollRequested.incr();
151  }
152
153  @Override
154  public long getSlowAppendCount() {
155    return slowAppendCount.value();
156  }
157
158  @Override
159  public void incrementWrittenBytes(long val) {
160    writtenBytes.incr(val);
161  }
162}