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