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