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