001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to you under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
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 */
017package org.apache.hadoop.hbase.regionserver;
018
019import java.util.HashMap;
020import org.apache.hadoop.hbase.TableName;
021import org.apache.hadoop.hbase.metrics.BaseSourceImpl;
022import org.apache.hadoop.metrics2.MetricHistogram;
023import org.apache.hadoop.metrics2.MetricsCollector;
024import org.apache.hadoop.metrics2.MetricsRecordBuilder;
025import org.apache.hadoop.metrics2.lib.DynamicMetricsRegistry;
026import org.apache.yetus.audience.InterfaceAudience;
027
028import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting;
029
030/**
031 * Implementation of {@link MetricsTableLatencies} to track latencies for one table in a
032 * RegionServer.
033 */
034@InterfaceAudience.Private
035public class MetricsTableLatenciesImpl extends BaseSourceImpl implements MetricsTableLatencies {
036
037  private final HashMap<TableName,TableHistograms> histogramsByTable = new HashMap<>();
038
039  @VisibleForTesting
040  public static class TableHistograms {
041    final MetricHistogram getTimeHisto;
042    final MetricHistogram incrementTimeHisto;
043    final MetricHistogram appendTimeHisto;
044    final MetricHistogram putTimeHisto;
045    final MetricHistogram putBatchTimeHisto;
046    final MetricHistogram deleteTimeHisto;
047    final MetricHistogram deleteBatchTimeHisto;
048    final MetricHistogram scanTimeHisto;
049    final MetricHistogram scanSizeHisto;
050
051    TableHistograms(DynamicMetricsRegistry registry, TableName tn) {
052      getTimeHisto = registry.newTimeHistogram(qualifyMetricsName(tn, GET_TIME));
053      incrementTimeHisto = registry.newTimeHistogram(
054          qualifyMetricsName(tn, INCREMENT_TIME));
055      appendTimeHisto = registry.newTimeHistogram(qualifyMetricsName(tn, APPEND_TIME));
056      putTimeHisto = registry.newTimeHistogram(qualifyMetricsName(tn, PUT_TIME));
057      putBatchTimeHisto = registry.newTimeHistogram(qualifyMetricsName(tn, PUT_BATCH_TIME));
058      deleteTimeHisto = registry.newTimeHistogram(qualifyMetricsName(tn, DELETE_TIME));
059      deleteBatchTimeHisto = registry.newTimeHistogram(
060          qualifyMetricsName(tn, DELETE_BATCH_TIME));
061      scanTimeHisto = registry.newTimeHistogram(qualifyMetricsName(tn, SCAN_TIME));
062      scanSizeHisto = registry.newSizeHistogram(qualifyMetricsName(tn, SCAN_SIZE));
063    }
064
065    public void updatePut(long time) {
066      putTimeHisto.add(time);
067    }
068
069    public void updatePutBatch(long time) {
070      putBatchTimeHisto.add(time);
071    }
072
073    public void updateDelete(long t) {
074      deleteTimeHisto.add(t);
075    }
076
077    public void updateDeleteBatch(long t) {
078      deleteBatchTimeHisto.add(t);
079    }
080
081    public void updateGet(long t) {
082      getTimeHisto.add(t);
083    }
084
085    public void updateIncrement(long t) {
086      incrementTimeHisto.add(t);
087    }
088
089    public void updateAppend(long t) {
090      appendTimeHisto.add(t);
091    }
092
093    public void updateScanSize(long scanSize) {
094      scanSizeHisto.add(scanSize);
095    }
096
097    public void updateScanTime(long t) {
098      scanTimeHisto.add(t);
099    }
100  }
101
102  @VisibleForTesting
103  public static String qualifyMetricsName(TableName tableName, String metric) {
104    StringBuilder sb = new StringBuilder();
105    sb.append("Namespace_").append(tableName.getNamespaceAsString());
106    sb.append("_table_").append(tableName.getQualifierAsString());
107    sb.append("_metric_").append(metric);
108    return sb.toString();
109  }
110
111  @VisibleForTesting
112  public TableHistograms getOrCreateTableHistogram(String tableName) {
113    // TODO Java8's ConcurrentHashMap#computeIfAbsent would be stellar instead
114    final TableName tn = TableName.valueOf(tableName);
115    TableHistograms latency = histogramsByTable.get(tn);
116    if (latency == null) {
117      latency = new TableHistograms(getMetricsRegistry(), tn);
118      histogramsByTable.put(tn, latency);
119    }
120    return latency;
121  }
122
123  public MetricsTableLatenciesImpl() {
124    this(METRICS_NAME, METRICS_DESCRIPTION, METRICS_CONTEXT, METRICS_JMX_CONTEXT);
125  }
126
127  public MetricsTableLatenciesImpl(String metricsName, String metricsDescription,
128      String metricsContext, String metricsJmxContext) {
129    super(metricsName, metricsDescription, metricsContext, metricsJmxContext);
130  }
131
132  @Override
133  public void updatePut(String tableName, long t) {
134    getOrCreateTableHistogram(tableName).updatePut(t);
135  }
136
137  @Override
138  public void updatePutBatch(String tableName, long t) {
139    getOrCreateTableHistogram(tableName).updatePutBatch(t);
140  }
141
142  @Override
143  public void updateDelete(String tableName, long t) {
144    getOrCreateTableHistogram(tableName).updateDelete(t);
145  }
146
147  @Override
148  public void updateDeleteBatch(String tableName, long t) {
149    getOrCreateTableHistogram(tableName).updateDeleteBatch(t);
150  }
151
152  @Override
153  public void updateGet(String tableName, long t) {
154    getOrCreateTableHistogram(tableName).updateGet(t);
155  }
156
157  @Override
158  public void updateIncrement(String tableName, long t) {
159    getOrCreateTableHistogram(tableName).updateIncrement(t);
160  }
161
162  @Override
163  public void updateAppend(String tableName, long t) {
164    getOrCreateTableHistogram(tableName).updateAppend(t);
165  }
166
167  @Override
168  public void updateScanSize(String tableName, long scanSize) {
169    getOrCreateTableHistogram(tableName).updateScanSize(scanSize);
170  }
171
172  @Override
173  public void updateScanTime(String tableName, long t) {
174    getOrCreateTableHistogram(tableName).updateScanTime(t);
175  }
176
177  @Override
178  public void getMetrics(MetricsCollector metricsCollector, boolean all) {
179    MetricsRecordBuilder mrb = metricsCollector.addRecord(metricsName);
180    // source is registered in supers constructor, sometimes called before the whole initialization.
181    metricsRegistry.snapshot(mrb, all);
182    if (metricsAdapter != null) {
183      // snapshot MetricRegistry as well
184      metricsAdapter.snapshotAllMetrics(registry, mrb);
185    }
186  }
187}