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 incrSplitRequest(String table) { 213 serverSource.incrSplitRequest(); 214 if (table != null) { 215 metricsTable.incrSplitRequest(table); 216 } 217 } 218 219 public void updateFlush(String table, long t, long memstoreSize, long fileSize) { 220 serverSource.updateFlushTime(t); 221 serverSource.updateFlushMemStoreSize(memstoreSize); 222 serverSource.updateFlushOutputSize(fileSize); 223 224 if (table != null) { 225 metricsTable.updateFlushTime(table, t); 226 metricsTable.updateFlushMemstoreSize(table, memstoreSize); 227 metricsTable.updateFlushOutputSize(table, fileSize); 228 } 229 230 } 231 232 public void updateCompaction(String table, boolean isMajor, long t, int inputFileCount, 233 int outputFileCount, long inputBytes, long outputBytes) { 234 serverSource.updateCompactionTime(isMajor, t); 235 serverSource.updateCompactionInputFileCount(isMajor, inputFileCount); 236 serverSource.updateCompactionOutputFileCount(isMajor, outputFileCount); 237 serverSource.updateCompactionInputSize(isMajor, inputBytes); 238 serverSource.updateCompactionOutputSize(isMajor, outputBytes); 239 240 if (table != null) { 241 metricsTable.updateCompactionTime(table, isMajor, t); 242 metricsTable.updateCompactionInputFileCount(table, isMajor, inputFileCount); 243 metricsTable.updateCompactionOutputFileCount(table, isMajor, outputFileCount); 244 metricsTable.updateCompactionInputSize(table, isMajor, inputBytes); 245 metricsTable.updateCompactionOutputSize(table, isMajor, outputBytes); 246 } 247 } 248 249 public void updateBulkLoad(long millis) { 250 this.bulkLoadTimer.updateMillis(millis); 251 } 252 253 /** 254 * @see MetricsRegionServerQuotaSource#incrementNumRegionSizeReportsSent(long) 255 */ 256 public void incrementNumRegionSizeReportsSent(long numReportsSent) { 257 quotaSource.incrementNumRegionSizeReportsSent(numReportsSent); 258 } 259 260 /** 261 * @see MetricsRegionServerQuotaSource#incrementRegionSizeReportingChoreTime(long) 262 */ 263 public void incrementRegionSizeReportingChoreTime(long time) { 264 quotaSource.incrementRegionSizeReportingChoreTime(time); 265 } 266 267 public void updateReadQueryMeter(HRegion region, long count) { 268 if (region.getMetricsTableRequests() != null) { 269 region.getMetricsTableRequests().updateTableReadQueryMeter(count); 270 } 271 if (serverReadQueryMeter != null) { 272 serverReadQueryMeter.mark(count); 273 } 274 } 275 276 public void updateWriteQueryMeter(HRegion region, long count) { 277 if (region.getMetricsTableRequests() != null) { 278 region.getMetricsTableRequests().updateTableWriteQueryMeter(count); 279 } 280 if (serverWriteQueryMeter != null) { 281 serverWriteQueryMeter.mark(count); 282 } 283 } 284 285 public void updateWriteQueryMeter(HRegion region) { 286 if (region.getMetricsTableRequests() != null) { 287 region.getMetricsTableRequests().updateTableWriteQueryMeter(); 288 } 289 if (serverWriteQueryMeter != null) { 290 serverWriteQueryMeter.mark(); 291 } 292 } 293 294 public void incrScannerLeaseExpired() { 295 serverSource.incrScannerLeaseExpired(); 296 } 297 298 /** 299 * Record a throttle exception with contextual information. 300 * @param throttleType the type of throttle exception from RpcThrottlingException.Type enum 301 * @param user the user who triggered the throttle 302 * @param table the table that was being accessed 303 */ 304 public void recordThrottleException(RpcThrottlingException.Type throttleType, String user, 305 String table) { 306 throttleMetrics.recordThrottleException(throttleType, user, table); 307 } 308 309}