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; 020 021import java.util.concurrent.atomic.AtomicBoolean; 022 023import org.apache.hadoop.hbase.metrics.Interns; 024import org.apache.hadoop.metrics2.MetricsRecordBuilder; 025import org.apache.hadoop.metrics2.lib.DynamicMetricsRegistry; 026import org.apache.hadoop.metrics2.lib.MutableFastCounter; 027import org.apache.yetus.audience.InterfaceAudience; 028import org.slf4j.Logger; 029import org.slf4j.LoggerFactory; 030 031@InterfaceAudience.Private 032public class MetricsRegionSourceImpl implements MetricsRegionSource { 033 034 private static final Logger LOG = LoggerFactory.getLogger(MetricsRegionSourceImpl.class); 035 036 private AtomicBoolean closed = new AtomicBoolean(false); 037 038 // Non-final so that we can null out the wrapper 039 // This is just paranoia. We really really don't want to 040 // leak a whole region by way of keeping the 041 // regionWrapper around too long. 042 private MetricsRegionWrapper regionWrapper; 043 044 private final MetricsRegionAggregateSourceImpl agg; 045 private final DynamicMetricsRegistry registry; 046 047 private final String regionNamePrefix; 048 private final String regionPutKey; 049 private final String regionDeleteKey; 050 private final String regionGetKey; 051 private final String regionIncrementKey; 052 private final String regionAppendKey; 053 private final String regionScanKey; 054 055 /* 056 * Implementation note: Do not put histograms per region. With hundreds of regions in a server 057 * histograms allocate too many counters. See HBASE-17016. 058 */ 059 private final MutableFastCounter regionPut; 060 private final MutableFastCounter regionDelete; 061 private final MutableFastCounter regionIncrement; 062 private final MutableFastCounter regionAppend; 063 private final MutableFastCounter regionGet; 064 private final MutableFastCounter regionScan; 065 066 private final int hashCode; 067 068 public MetricsRegionSourceImpl(MetricsRegionWrapper regionWrapper, 069 MetricsRegionAggregateSourceImpl aggregate) { 070 this.regionWrapper = regionWrapper; 071 agg = aggregate; 072 hashCode = regionWrapper.getRegionHashCode(); 073 agg.register(this); 074 075 LOG.debug("Creating new MetricsRegionSourceImpl for table " + 076 regionWrapper.getTableName() + " " + regionWrapper.getRegionName()); 077 078 registry = agg.getMetricsRegistry(); 079 080 regionNamePrefix = "Namespace_" + regionWrapper.getNamespace() + 081 "_table_" + regionWrapper.getTableName() + 082 "_region_" + regionWrapper.getRegionName() + 083 "_metric_"; 084 085 String suffix = "Count"; 086 087 regionPutKey = regionNamePrefix + MetricsRegionServerSource.PUT_KEY + suffix; 088 regionPut = registry.getCounter(regionPutKey, 0L); 089 090 regionDeleteKey = regionNamePrefix + MetricsRegionServerSource.DELETE_KEY + suffix; 091 regionDelete = registry.getCounter(regionDeleteKey, 0L); 092 093 regionIncrementKey = regionNamePrefix + MetricsRegionServerSource.INCREMENT_KEY + suffix; 094 regionIncrement = registry.getCounter(regionIncrementKey, 0L); 095 096 regionAppendKey = regionNamePrefix + MetricsRegionServerSource.APPEND_KEY + suffix; 097 regionAppend = registry.getCounter(regionAppendKey, 0L); 098 099 regionGetKey = regionNamePrefix + MetricsRegionServerSource.GET_KEY + suffix; 100 regionGet = registry.getCounter(regionGetKey, 0L); 101 102 regionScanKey = regionNamePrefix + MetricsRegionServerSource.SCAN_KEY + suffix; 103 regionScan = registry.getCounter(regionScanKey, 0L); 104 } 105 106 @Override 107 public void close() { 108 boolean wasClosed = closed.getAndSet(true); 109 110 // Has someone else already closed this for us? 111 if (wasClosed) { 112 return; 113 } 114 115 // Before removing the metrics remove this region from the aggregate region bean. 116 // This should mean that it's unlikely that snapshot and close happen at the same time. 117 agg.deregister(this); 118 119 // While it's un-likely that snapshot and close happen at the same time it's still possible. 120 // So grab the lock to ensure that all calls to snapshot are done before we remove the metrics 121 synchronized (this) { 122 if (LOG.isTraceEnabled()) { 123 LOG.trace("Removing region Metrics: " + regionWrapper.getRegionName()); 124 } 125 126 registry.removeMetric(regionPutKey); 127 registry.removeMetric(regionDeleteKey); 128 registry.removeMetric(regionIncrementKey); 129 registry.removeMetric(regionAppendKey); 130 registry.removeMetric(regionGetKey); 131 registry.removeMetric(regionScanKey); 132 133 regionWrapper = null; 134 } 135 } 136 137 @Override 138 public void updatePut() { 139 regionPut.incr(); 140 } 141 142 @Override 143 public void updateDelete() { 144 regionDelete.incr(); 145 } 146 147 @Override 148 public void updateGet(long mills) { 149 regionGet.incr(); 150 } 151 152 @Override 153 public void updateScanTime(long mills) { 154 regionScan.incr(); 155 } 156 157 @Override 158 public void updateIncrement() { 159 regionIncrement.incr(); 160 } 161 162 @Override 163 public void updateAppend() { 164 regionAppend.incr(); 165 } 166 167 @Override 168 public MetricsRegionAggregateSource getAggregateSource() { 169 return agg; 170 } 171 172 @Override 173 public int compareTo(MetricsRegionSource source) { 174 if (!(source instanceof MetricsRegionSourceImpl)) { 175 return -1; 176 } 177 178 MetricsRegionSourceImpl impl = (MetricsRegionSourceImpl) source; 179 if (impl == null) { 180 return -1; 181 } 182 183 return Long.compare(hashCode, impl.hashCode); 184 } 185 186 void snapshot(MetricsRecordBuilder mrb, boolean ignored) { 187 188 // If there is a close that started be double extra sure 189 // that we're not getting any locks and not putting data 190 // into the metrics that should be removed. So early out 191 // before even getting the lock. 192 if (closed.get()) { 193 return; 194 } 195 196 // Grab the read 197 // This ensures that removes of the metrics 198 // can't happen while we are putting them back in. 199 synchronized (this) { 200 201 // It's possible that a close happened between checking 202 // the closed variable and getting the lock. 203 if (closed.get()) { 204 return; 205 } 206 207 mrb.addGauge( 208 Interns.info( 209 regionNamePrefix + MetricsRegionServerSource.STORE_COUNT, 210 MetricsRegionServerSource.STORE_COUNT_DESC), 211 this.regionWrapper.getNumStores()); 212 mrb.addGauge(Interns.info( 213 regionNamePrefix + MetricsRegionServerSource.STOREFILE_COUNT, 214 MetricsRegionServerSource.STOREFILE_COUNT_DESC), 215 this.regionWrapper.getNumStoreFiles()); 216 mrb.addGauge(Interns.info( 217 regionNamePrefix + MetricsRegionServerSource.MEMSTORE_SIZE, 218 MetricsRegionServerSource.MEMSTORE_SIZE_DESC), 219 this.regionWrapper.getMemStoreSize()); 220 mrb.addGauge(Interns.info( 221 regionNamePrefix + MetricsRegionServerSource.MAX_STORE_FILE_AGE, 222 MetricsRegionServerSource.MAX_STORE_FILE_AGE_DESC), 223 this.regionWrapper.getMaxStoreFileAge()); 224 mrb.addGauge(Interns.info( 225 regionNamePrefix + MetricsRegionServerSource.MIN_STORE_FILE_AGE, 226 MetricsRegionServerSource.MIN_STORE_FILE_AGE_DESC), 227 this.regionWrapper.getMinStoreFileAge()); 228 mrb.addGauge(Interns.info( 229 regionNamePrefix + MetricsRegionServerSource.AVG_STORE_FILE_AGE, 230 MetricsRegionServerSource.AVG_STORE_FILE_AGE_DESC), 231 this.regionWrapper.getAvgStoreFileAge()); 232 mrb.addGauge(Interns.info( 233 regionNamePrefix + MetricsRegionServerSource.NUM_REFERENCE_FILES, 234 MetricsRegionServerSource.NUM_REFERENCE_FILES_DESC), 235 this.regionWrapper.getNumReferenceFiles()); 236 mrb.addGauge(Interns.info( 237 regionNamePrefix + MetricsRegionServerSource.STOREFILE_SIZE, 238 MetricsRegionServerSource.STOREFILE_SIZE_DESC), 239 this.regionWrapper.getStoreFileSize()); 240 mrb.addCounter(Interns.info( 241 regionNamePrefix + MetricsRegionSource.COMPACTIONS_COMPLETED_COUNT, 242 MetricsRegionSource.COMPACTIONS_COMPLETED_DESC), 243 this.regionWrapper.getNumCompactionsCompleted()); 244 mrb.addCounter(Interns.info( 245 regionNamePrefix + MetricsRegionSource.COMPACTIONS_FAILED_COUNT, 246 MetricsRegionSource.COMPACTIONS_FAILED_DESC), 247 this.regionWrapper.getNumCompactionsFailed()); 248 mrb.addCounter(Interns.info( 249 regionNamePrefix + MetricsRegionSource.LAST_MAJOR_COMPACTION_AGE, 250 MetricsRegionSource.LAST_MAJOR_COMPACTION_DESC), 251 this.regionWrapper.getLastMajorCompactionAge()); 252 mrb.addCounter(Interns.info( 253 regionNamePrefix + MetricsRegionSource.NUM_BYTES_COMPACTED_COUNT, 254 MetricsRegionSource.NUM_BYTES_COMPACTED_DESC), 255 this.regionWrapper.getNumBytesCompacted()); 256 mrb.addCounter(Interns.info( 257 regionNamePrefix + MetricsRegionSource.NUM_FILES_COMPACTED_COUNT, 258 MetricsRegionSource.NUM_FILES_COMPACTED_DESC), 259 this.regionWrapper.getNumFilesCompacted()); 260 mrb.addCounter(Interns.info( 261 regionNamePrefix + MetricsRegionServerSource.READ_REQUEST_COUNT, 262 MetricsRegionServerSource.READ_REQUEST_COUNT_DESC), 263 this.regionWrapper.getReadRequestCount()); 264 mrb.addCounter(Interns.info( 265 regionNamePrefix + MetricsRegionServerSource.FILTERED_READ_REQUEST_COUNT, 266 MetricsRegionServerSource.FILTERED_READ_REQUEST_COUNT_DESC), 267 this.regionWrapper.getFilteredReadRequestCount()); 268 mrb.addCounter(Interns.info( 269 regionNamePrefix + MetricsRegionServerSource.WRITE_REQUEST_COUNT, 270 MetricsRegionServerSource.WRITE_REQUEST_COUNT_DESC), 271 this.regionWrapper.getWriteRequestCount()); 272 mrb.addCounter(Interns.info( 273 regionNamePrefix + MetricsRegionSource.REPLICA_ID, 274 MetricsRegionSource.REPLICA_ID_DESC), 275 this.regionWrapper.getReplicaId()); 276 mrb.addCounter(Interns.info( 277 regionNamePrefix + MetricsRegionSource.COMPACTIONS_QUEUED_COUNT, 278 MetricsRegionSource.COMPACTIONS_QUEUED_DESC), 279 this.regionWrapper.getNumCompactionsQueued()); 280 mrb.addCounter(Interns.info( 281 regionNamePrefix + MetricsRegionSource.FLUSHES_QUEUED_COUNT, 282 MetricsRegionSource.FLUSHES_QUEUED_DESC), 283 this.regionWrapper.getNumFlushesQueued()); 284 mrb.addCounter(Interns.info( 285 regionNamePrefix + MetricsRegionSource.MAX_COMPACTION_QUEUE_SIZE, 286 MetricsRegionSource.MAX_COMPACTION_QUEUE_DESC), 287 this.regionWrapper.getMaxCompactionQueueSize()); 288 mrb.addCounter(Interns.info( 289 regionNamePrefix + MetricsRegionSource.MAX_FLUSH_QUEUE_SIZE, 290 MetricsRegionSource.MAX_FLUSH_QUEUE_DESC), 291 this.regionWrapper.getMaxFlushQueueSize()); 292 } 293 } 294 295 @Override 296 public int hashCode() { 297 return hashCode; 298 } 299 300 @Override 301 public boolean equals(Object obj) { 302 return obj == this || 303 (obj instanceof MetricsRegionSourceImpl && compareTo((MetricsRegionSourceImpl) obj) == 0); 304 } 305}