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