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