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 java.io.Closeable; 021import java.io.IOException; 022import java.util.HashMap; 023import java.util.Map; 024import java.util.OptionalDouble; 025import java.util.OptionalLong; 026import java.util.concurrent.ScheduledExecutorService; 027import java.util.concurrent.ScheduledFuture; 028import java.util.concurrent.TimeUnit; 029import org.apache.commons.lang3.mutable.MutableLong; 030import org.apache.hadoop.hbase.CompatibilitySingletonFactory; 031import org.apache.hadoop.hbase.client.RegionInfo; 032import org.apache.hadoop.hbase.client.TableDescriptor; 033import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 034import org.apache.hadoop.metrics2.MetricsExecutor; 035import org.apache.yetus.audience.InterfaceAudience; 036import org.slf4j.Logger; 037import org.slf4j.LoggerFactory; 038 039@InterfaceAudience.Private 040public class MetricsRegionWrapperImpl implements MetricsRegionWrapper, Closeable { 041 042 private static final Logger LOG = LoggerFactory.getLogger(MetricsRegionWrapperImpl.class); 043 044 public static final int PERIOD = 45; 045 public static final String UNKNOWN = "unknown"; 046 047 private final HRegion region; 048 private ScheduledExecutorService executor; 049 private Runnable runnable; 050 private long numStoreFiles; 051 private long storeRefCount; 052 private long maxCompactedStoreFileRefCount; 053 private long memstoreSize; 054 private long storeFileSize; 055 private long maxStoreFileAge; 056 private long minStoreFileAge; 057 private long avgStoreFileAge; 058 private long numReferenceFiles; 059 private long maxFlushQueueSize; 060 private long maxCompactionQueueSize; 061 private Map<String, Long> readsOnlyFromMemstore; 062 private Map<String, Long> mixedReadsOnStore; 063 064 private ScheduledFuture<?> regionMetricsUpdateTask; 065 066 private float currentRegionCacheRatio; 067 068 public MetricsRegionWrapperImpl(HRegion region) { 069 this.region = region; 070 this.executor = CompatibilitySingletonFactory.getInstance(MetricsExecutor.class).getExecutor(); 071 this.runnable = new HRegionMetricsWrapperRunnable(); 072 this.regionMetricsUpdateTask = 073 this.executor.scheduleWithFixedDelay(this.runnable, PERIOD, PERIOD, TimeUnit.SECONDS); 074 } 075 076 @Override 077 public String getTableName() { 078 TableDescriptor tableDesc = this.region.getTableDescriptor(); 079 if (tableDesc == null) { 080 return UNKNOWN; 081 } 082 return tableDesc.getTableName().getQualifierAsString(); 083 } 084 085 @Override 086 public String getNamespace() { 087 TableDescriptor tableDesc = this.region.getTableDescriptor(); 088 if (tableDesc == null) { 089 return UNKNOWN; 090 } 091 return tableDesc.getTableName().getNamespaceAsString(); 092 } 093 094 @Override 095 public String getRegionName() { 096 RegionInfo regionInfo = this.region.getRegionInfo(); 097 if (regionInfo == null) { 098 return UNKNOWN; 099 } 100 return regionInfo.getEncodedName(); 101 } 102 103 @Override 104 public long getNumStores() { 105 Map<byte[], HStore> stores = this.region.stores; 106 if (stores == null) { 107 return 0; 108 } 109 return stores.size(); 110 } 111 112 @Override 113 public long getNumStoreFiles() { 114 return numStoreFiles; 115 } 116 117 @Override 118 public long getMemStoreSize() { 119 return memstoreSize; 120 } 121 122 @Override 123 public long getStoreFileSize() { 124 return storeFileSize; 125 } 126 127 public float getCurrentRegionCacheRatio() { 128 return currentRegionCacheRatio; 129 } 130 131 @Override 132 public long getStoreRefCount() { 133 return storeRefCount; 134 } 135 136 @Override 137 public long getMaxCompactedStoreFileRefCount() { 138 return maxCompactedStoreFileRefCount; 139 } 140 141 @Override 142 public long getReadRequestCount() { 143 return this.region.getReadRequestsCount(); 144 } 145 146 @Override 147 public long getCpRequestCount() { 148 return this.region.getCpRequestsCount(); 149 } 150 151 @Override 152 public long getFilteredReadRequestCount() { 153 return this.region.getFilteredReadRequestsCount(); 154 } 155 156 @Override 157 public long getWriteRequestCount() { 158 return this.region.getWriteRequestsCount(); 159 } 160 161 @Override 162 public long getNumFilesCompacted() { 163 return this.region.compactionNumFilesCompacted.sum(); 164 } 165 166 @Override 167 public long getNumBytesCompacted() { 168 return this.region.compactionNumBytesCompacted.sum(); 169 } 170 171 @Override 172 public long getNumCompactionsCompleted() { 173 return this.region.compactionsFinished.sum(); 174 } 175 176 @Override 177 public long getLastMajorCompactionAge() { 178 long lastMajorCompactionTs = 0L; 179 try { 180 lastMajorCompactionTs = this.region.getOldestHfileTs(true); 181 } catch (IOException ioe) { 182 LOG.error("Could not load HFile info ", ioe); 183 } 184 long now = EnvironmentEdgeManager.currentTime(); 185 return now - lastMajorCompactionTs; 186 } 187 188 @Override 189 public long getTotalRequestCount() { 190 return getReadRequestCount() + getWriteRequestCount(); 191 } 192 193 @Override 194 public long getNumCompactionsFailed() { 195 return this.region.compactionsFailed.sum(); 196 } 197 198 @Override 199 public long getNumCompactionsQueued() { 200 return this.region.compactionsQueued.sum(); 201 } 202 203 @Override 204 public long getNumFlushesQueued() { 205 return this.region.flushesQueued.sum(); 206 } 207 208 @Override 209 public long getMaxCompactionQueueSize() { 210 return maxCompactionQueueSize; 211 } 212 213 @Override 214 public long getMaxFlushQueueSize() { 215 return maxFlushQueueSize; 216 } 217 218 @Override 219 public long getMaxStoreFileAge() { 220 return maxStoreFileAge; 221 } 222 223 @Override 224 public long getMinStoreFileAge() { 225 return minStoreFileAge; 226 } 227 228 @Override 229 public long getAvgStoreFileAge() { 230 return avgStoreFileAge; 231 } 232 233 @Override 234 public long getNumReferenceFiles() { 235 return numReferenceFiles; 236 } 237 238 @Override 239 public int getRegionHashCode() { 240 return this.region.hashCode(); 241 } 242 243 @Override 244 public Map<String, Long> getMemstoreOnlyRowReadsCount() { 245 return readsOnlyFromMemstore; 246 } 247 248 @Override 249 public Map<String, Long> getMixedRowReadsCount() { 250 return mixedReadsOnStore; 251 } 252 253 public class HRegionMetricsWrapperRunnable implements Runnable { 254 255 @Override 256 public void run() { 257 long tempNumStoreFiles = 0; 258 int tempStoreRefCount = 0; 259 int tempMaxCompactedStoreFileRefCount = 0; 260 long tempMemstoreSize = 0; 261 long tempStoreFileSize = 0; 262 long tempMaxStoreFileAge = 0; 263 long tempMinStoreFileAge = Long.MAX_VALUE; 264 long tempNumReferenceFiles = 0; 265 long tempMaxCompactionQueueSize = 0; 266 long tempMaxFlushQueueSize = 0; 267 long avgAgeNumerator = 0; 268 long numHFiles = 0; 269 if (region.stores != null) { 270 for (HStore store : region.stores.values()) { 271 tempNumStoreFiles += store.getStorefilesCount(); 272 int currentStoreRefCount = store.getStoreRefCount(); 273 tempStoreRefCount += currentStoreRefCount; 274 int currentMaxCompactedStoreFileRefCount = store.getMaxCompactedStoreFileRefCount(); 275 tempMaxCompactedStoreFileRefCount = 276 Math.max(tempMaxCompactedStoreFileRefCount, currentMaxCompactedStoreFileRefCount); 277 tempMemstoreSize += store.getMemStoreSize().getDataSize(); 278 tempStoreFileSize += store.getStorefilesSize(); 279 OptionalLong storeMaxStoreFileAge = store.getMaxStoreFileAge(); 280 if ( 281 storeMaxStoreFileAge.isPresent() 282 && storeMaxStoreFileAge.getAsLong() > tempMaxStoreFileAge 283 ) { 284 tempMaxStoreFileAge = storeMaxStoreFileAge.getAsLong(); 285 } 286 287 OptionalLong storeMinStoreFileAge = store.getMinStoreFileAge(); 288 if ( 289 storeMinStoreFileAge.isPresent() 290 && storeMinStoreFileAge.getAsLong() < tempMinStoreFileAge 291 ) { 292 tempMinStoreFileAge = storeMinStoreFileAge.getAsLong(); 293 } 294 295 long storeHFiles = store.getNumHFiles(); 296 numHFiles += storeHFiles; 297 tempNumReferenceFiles += store.getNumReferenceFiles(); 298 299 OptionalDouble storeAvgStoreFileAge = store.getAvgStoreFileAge(); 300 if (storeAvgStoreFileAge.isPresent()) { 301 avgAgeNumerator += (long) storeAvgStoreFileAge.getAsDouble() * storeHFiles; 302 } 303 if (mixedReadsOnStore == null) { 304 mixedReadsOnStore = new HashMap<String, Long>(); 305 } 306 Long tempVal = mixedReadsOnStore.get(store.getColumnFamilyName()); 307 if (tempVal == null) { 308 tempVal = 0L; 309 } else { 310 tempVal += store.getMixedRowReadsCount(); 311 } 312 mixedReadsOnStore.put(store.getColumnFamilyName(), tempVal); 313 if (readsOnlyFromMemstore == null) { 314 readsOnlyFromMemstore = new HashMap<String, Long>(); 315 } 316 tempVal = readsOnlyFromMemstore.get(store.getColumnFamilyName()); 317 if (tempVal == null) { 318 tempVal = 0L; 319 } else { 320 tempVal += store.getMemstoreOnlyRowReadsCount(); 321 } 322 readsOnlyFromMemstore.put(store.getColumnFamilyName(), tempVal); 323 } 324 } 325 MutableLong regionCachedAmount = new MutableLong(0); 326 region.getBlockCache().getRegionCachedInfo().ifPresent(regionCacheRatio -> regionCachedAmount 327 .addAndGet(regionCacheRatio.getOrDefault(region.getRegionInfo().getEncodedName(), 0L))); 328 if (tempStoreFileSize > 0) { 329 LOG.debug("Region {}, had cached {} bytes from a total of {}", 330 region.getRegionInfo().getEncodedName(), regionCachedAmount.getValue(), 331 tempStoreFileSize); 332 currentRegionCacheRatio = regionCachedAmount.floatValue() / tempStoreFileSize; 333 } 334 numStoreFiles = tempNumStoreFiles; 335 storeRefCount = tempStoreRefCount; 336 maxCompactedStoreFileRefCount = tempMaxCompactedStoreFileRefCount; 337 memstoreSize = tempMemstoreSize; 338 storeFileSize = tempStoreFileSize; 339 maxStoreFileAge = tempMaxStoreFileAge; 340 if (tempMinStoreFileAge != Long.MAX_VALUE) { 341 minStoreFileAge = tempMinStoreFileAge; 342 } 343 344 if (numHFiles != 0) { 345 avgStoreFileAge = avgAgeNumerator / numHFiles; 346 } 347 348 numReferenceFiles = tempNumReferenceFiles; 349 tempMaxCompactionQueueSize = getNumCompactionsQueued(); 350 tempMaxFlushQueueSize = getNumFlushesQueued(); 351 if (tempMaxCompactionQueueSize > maxCompactionQueueSize) { 352 maxCompactionQueueSize = tempMaxCompactionQueueSize; 353 } 354 if (tempMaxFlushQueueSize > maxFlushQueueSize) { 355 maxFlushQueueSize = tempMaxFlushQueueSize; 356 } 357 } 358 } 359 360 @Override 361 public void close() throws IOException { 362 regionMetricsUpdateTask.cancel(true); 363 } 364 365 /** 366 * Get the replica id of this region. 367 */ 368 @Override 369 public int getReplicaId() { 370 return region.getRegionInfo().getReplicaId(); 371 } 372 373}