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 */
018package org.apache.hadoop.hbase.regionserver;
019
020import org.apache.hadoop.conf.Configuration;
021import org.apache.hadoop.hbase.CompatibilitySingletonFactory;
022import org.apache.hadoop.hbase.TableName;
023import org.apache.hadoop.hbase.metrics.Meter;
024import org.apache.hadoop.hbase.metrics.MetricRegistries;
025import org.apache.hadoop.hbase.metrics.MetricRegistry;
026import org.apache.hadoop.hbase.metrics.Timer;
027import org.apache.yetus.audience.InterfaceAudience;
028import org.apache.yetus.audience.InterfaceStability;
029
030/**
031 * Maintains regionserver statistics and publishes them through the metrics interfaces. This class
032 * has a number of metrics variables that are publicly accessible; these variables (objects) have
033 * methods to update their values. Batch your updates rather than call on each instance else all
034 * threads will do nothing but contend trying to maintain metric counters!
035 */
036@InterfaceStability.Evolving
037@InterfaceAudience.Private
038public class MetricsRegionServer {
039  public static final String RS_ENABLE_TABLE_METRICS_KEY =
040    "hbase.regionserver.enable.table.latencies";
041  public static final boolean RS_ENABLE_TABLE_METRICS_DEFAULT = true;
042  public static final String RS_ENABLE_SERVER_QUERY_METER_METRICS_KEY =
043    "hbase.regionserver.enable.server.query.meter";
044  public static final boolean RS_ENABLE_SERVER_QUERY_METER_METRICS_KEY_DEFAULT = false;
045  public static final String RS_ENABLE_TABLE_QUERY_METER_METRICS_KEY =
046    "hbase.regionserver.enable.table.query.meter";
047  public static final boolean RS_ENABLE_TABLE_QUERY_METER_METRICS_KEY_DEFAULT = false;
048
049  public static final String SLOW_METRIC_TIME = "hbase.ipc.slow.metric.time";
050  private final MetricsRegionServerSource serverSource;
051  private final MetricsRegionServerWrapper regionServerWrapper;
052  private RegionServerTableMetrics tableMetrics;
053  private final MetricsTable metricsTable;
054  private MetricsRegionServerQuotaSource quotaSource;
055  private final MetricsUserAggregate userAggregate;
056
057  private MetricRegistry metricRegistry;
058  private Timer bulkLoadTimer;
059  // Incremented once for each call to Scan#nextRaw
060  private Meter serverReadQueryMeter;
061  // Incremented per write.
062  private Meter serverWriteQueryMeter;
063  protected long slowMetricTime;
064  protected static final int DEFAULT_SLOW_METRIC_TIME = 1000; // milliseconds
065
066  public MetricsRegionServer(MetricsRegionServerWrapper regionServerWrapper, Configuration conf,
067    MetricsTable metricsTable) {
068    this(regionServerWrapper,
069      CompatibilitySingletonFactory.getInstance(MetricsRegionServerSourceFactory.class)
070        .createServer(regionServerWrapper),
071      createTableMetrics(conf), metricsTable,
072      MetricsUserAggregateFactory.getMetricsUserAggregate(conf));
073
074    // Create hbase-metrics module based metrics. The registry should already be registered by the
075    // MetricsRegionServerSource
076    metricRegistry = MetricRegistries.global().get(serverSource.getMetricRegistryInfo()).get();
077
078    // create and use metrics from the new hbase-metrics based registry.
079    bulkLoadTimer = metricRegistry.timer("Bulkload");
080
081    slowMetricTime = conf.getLong(SLOW_METRIC_TIME, DEFAULT_SLOW_METRIC_TIME);
082    quotaSource = CompatibilitySingletonFactory.getInstance(MetricsRegionServerQuotaSource.class);
083    if (
084      conf.getBoolean(RS_ENABLE_SERVER_QUERY_METER_METRICS_KEY,
085        RS_ENABLE_SERVER_QUERY_METER_METRICS_KEY_DEFAULT)
086    ) {
087      serverReadQueryMeter = metricRegistry.meter("ServerReadQueryPerSecond");
088      serverWriteQueryMeter = metricRegistry.meter("ServerWriteQueryPerSecond");
089    }
090  }
091
092  MetricsRegionServer(MetricsRegionServerWrapper regionServerWrapper,
093    MetricsRegionServerSource serverSource, RegionServerTableMetrics tableMetrics,
094    MetricsTable metricsTable, MetricsUserAggregate userAggregate) {
095    this.regionServerWrapper = regionServerWrapper;
096    this.serverSource = serverSource;
097    this.tableMetrics = tableMetrics;
098    this.metricsTable = metricsTable;
099    this.userAggregate = userAggregate;
100  }
101
102  /**
103   * Creates an instance of {@link RegionServerTableMetrics} only if the feature is enabled.
104   */
105  static RegionServerTableMetrics createTableMetrics(Configuration conf) {
106    if (conf.getBoolean(RS_ENABLE_TABLE_METRICS_KEY, RS_ENABLE_TABLE_METRICS_DEFAULT)) {
107      return new RegionServerTableMetrics(conf.getBoolean(RS_ENABLE_TABLE_QUERY_METER_METRICS_KEY,
108        RS_ENABLE_TABLE_QUERY_METER_METRICS_KEY_DEFAULT));
109    }
110    return null;
111  }
112
113  public MetricsRegionServerSource getMetricsSource() {
114    return serverSource;
115  }
116
117  public MetricsUserAggregate getMetricsUserAggregate() {
118    return userAggregate;
119  }
120
121  public MetricsRegionServerWrapper getRegionServerWrapper() {
122    return regionServerWrapper;
123  }
124
125  public void updatePutBatch(TableName tn, long t) {
126    if (tableMetrics != null && tn != null) {
127      tableMetrics.updatePutBatch(tn, t);
128    }
129    serverSource.updatePutBatch(t);
130  }
131
132  public void updatePut(TableName tn, long t) {
133    if (tableMetrics != null && tn != null) {
134      tableMetrics.updatePut(tn, t);
135    }
136    if (t > slowMetricTime) {
137      serverSource.incrSlowPut();
138    }
139    serverSource.updatePut(t);
140    userAggregate.updatePut(t);
141  }
142
143  public void updateDelete(TableName tn, long t) {
144    if (tableMetrics != null && tn != null) {
145      tableMetrics.updateDelete(tn, t);
146    }
147    if (t > slowMetricTime) {
148      serverSource.incrSlowDelete();
149    }
150    serverSource.updateDelete(t);
151    userAggregate.updateDelete(t);
152  }
153
154  public void updateDeleteBatch(TableName tn, long t) {
155    if (tableMetrics != null && tn != null) {
156      tableMetrics.updateDeleteBatch(tn, t);
157    }
158    serverSource.updateDeleteBatch(t);
159  }
160
161  public void updateCheckAndDelete(TableName tn, long t) {
162    if (tableMetrics != null && tn != null) {
163      tableMetrics.updateCheckAndDelete(tn, t);
164    }
165    serverSource.updateCheckAndDelete(t);
166  }
167
168  public void updateCheckAndPut(TableName tn, long t) {
169    if (tableMetrics != null && tn != null) {
170      tableMetrics.updateCheckAndPut(tn, t);
171    }
172    serverSource.updateCheckAndPut(t);
173  }
174
175  public void updateCheckAndMutate(TableName tn, long t) {
176    if (tableMetrics != null && tn != null) {
177      tableMetrics.updateCheckAndMutate(tn, t);
178    }
179    serverSource.updateCheckAndMutate(t);
180  }
181
182  public void updateGet(TableName tn, long t) {
183    if (tableMetrics != null && tn != null) {
184      tableMetrics.updateGet(tn, t);
185    }
186    if (t > slowMetricTime) {
187      serverSource.incrSlowGet();
188    }
189    serverSource.updateGet(t);
190    userAggregate.updateGet(t);
191  }
192
193  public void updateIncrement(TableName tn, long t) {
194    if (tableMetrics != null && tn != null) {
195      tableMetrics.updateIncrement(tn, t);
196    }
197    if (t > slowMetricTime) {
198      serverSource.incrSlowIncrement();
199    }
200    serverSource.updateIncrement(t);
201    userAggregate.updateIncrement(t);
202  }
203
204  public void updateAppend(TableName tn, long t) {
205    if (tableMetrics != null && tn != null) {
206      tableMetrics.updateAppend(tn, t);
207    }
208    if (t > slowMetricTime) {
209      serverSource.incrSlowAppend();
210    }
211    serverSource.updateAppend(t);
212    userAggregate.updateAppend(t);
213  }
214
215  public void updateReplay(long t) {
216    serverSource.updateReplay(t);
217    userAggregate.updateReplay(t);
218  }
219
220  public void updateScanSize(TableName tn, long scanSize) {
221    if (tableMetrics != null && tn != null) {
222      tableMetrics.updateScanSize(tn, scanSize);
223    }
224    serverSource.updateScanSize(scanSize);
225  }
226
227  public void updateScanTime(TableName tn, long t) {
228    if (tableMetrics != null && tn != null) {
229      tableMetrics.updateScanTime(tn, t);
230    }
231    serverSource.updateScanTime(t);
232    userAggregate.updateScanTime(t);
233  }
234
235  public void updateSplitTime(long t) {
236    serverSource.updateSplitTime(t);
237  }
238
239  public void incrSplitRequest() {
240    serverSource.incrSplitRequest();
241  }
242
243  public void incrSplitSuccess() {
244    serverSource.incrSplitSuccess();
245  }
246
247  public void updateFlush(String table, long t, long memstoreSize, long fileSize) {
248    serverSource.updateFlushTime(t);
249    serverSource.updateFlushMemStoreSize(memstoreSize);
250    serverSource.updateFlushOutputSize(fileSize);
251
252    if (table != null) {
253      metricsTable.updateFlushTime(table, t);
254      metricsTable.updateFlushMemstoreSize(table, memstoreSize);
255      metricsTable.updateFlushOutputSize(table, fileSize);
256    }
257
258  }
259
260  public void updateCompaction(String table, boolean isMajor, long t, int inputFileCount,
261    int outputFileCount, long inputBytes, long outputBytes) {
262    serverSource.updateCompactionTime(isMajor, t);
263    serverSource.updateCompactionInputFileCount(isMajor, inputFileCount);
264    serverSource.updateCompactionOutputFileCount(isMajor, outputFileCount);
265    serverSource.updateCompactionInputSize(isMajor, inputBytes);
266    serverSource.updateCompactionOutputSize(isMajor, outputBytes);
267
268    if (table != null) {
269      metricsTable.updateCompactionTime(table, isMajor, t);
270      metricsTable.updateCompactionInputFileCount(table, isMajor, inputFileCount);
271      metricsTable.updateCompactionOutputFileCount(table, isMajor, outputFileCount);
272      metricsTable.updateCompactionInputSize(table, isMajor, inputBytes);
273      metricsTable.updateCompactionOutputSize(table, isMajor, outputBytes);
274    }
275  }
276
277  public void updateBulkLoad(long millis) {
278    this.bulkLoadTimer.updateMillis(millis);
279  }
280
281  /**
282   * @see MetricsRegionServerQuotaSource#incrementNumRegionSizeReportsSent(long)
283   */
284  public void incrementNumRegionSizeReportsSent(long numReportsSent) {
285    quotaSource.incrementNumRegionSizeReportsSent(numReportsSent);
286  }
287
288  /**
289   * @see MetricsRegionServerQuotaSource#incrementRegionSizeReportingChoreTime(long)
290   */
291  public void incrementRegionSizeReportingChoreTime(long time) {
292    quotaSource.incrementRegionSizeReportingChoreTime(time);
293  }
294
295  public void updateReadQueryMeter(TableName tn, long count) {
296    if (tableMetrics != null && tn != null) {
297      tableMetrics.updateTableReadQueryMeter(tn, count);
298    }
299    if (serverReadQueryMeter != null) {
300      serverReadQueryMeter.mark(count);
301    }
302  }
303
304  public void updateWriteQueryMeter(TableName tn, long count) {
305    if (tableMetrics != null && tn != null) {
306      tableMetrics.updateTableWriteQueryMeter(tn, count);
307    }
308    if (serverWriteQueryMeter != null) {
309      serverWriteQueryMeter.mark(count);
310    }
311  }
312
313  public void updateWriteQueryMeter(TableName tn) {
314    if (tableMetrics != null && tn != null) {
315      tableMetrics.updateTableWriteQueryMeter(tn);
316    }
317    if (serverWriteQueryMeter != null) {
318      serverWriteQueryMeter.mark();
319    }
320  }
321
322  public void incrScannerLeaseExpired() {
323    serverSource.incrScannerLeaseExpired();
324  }
325}