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 */
018
019package org.apache.hadoop.hbase.regionserver;
020
021import java.io.Closeable;
022import java.io.IOException;
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;
029
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 maxStoreFileRefCount;
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
062  private ScheduledFuture<?> regionMetricsUpdateTask;
063
064  public MetricsRegionWrapperImpl(HRegion region) {
065    this.region = region;
066    this.executor = CompatibilitySingletonFactory.getInstance(MetricsExecutor.class).getExecutor();
067    this.runnable = new HRegionMetricsWrapperRunnable();
068    this.regionMetricsUpdateTask = this.executor.scheduleWithFixedDelay(this.runnable, PERIOD,
069      PERIOD, TimeUnit.SECONDS);
070  }
071
072  @Override
073  public String getTableName() {
074    TableDescriptor tableDesc = this.region.getTableDescriptor();
075    if (tableDesc == null) {
076      return UNKNOWN;
077    }
078    return tableDesc.getTableName().getQualifierAsString();
079  }
080
081  @Override
082  public String getNamespace() {
083    TableDescriptor tableDesc = this.region.getTableDescriptor();
084    if (tableDesc == null) {
085      return UNKNOWN;
086    }
087    return tableDesc.getTableName().getNamespaceAsString();
088  }
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 getMaxStoreFileRefCount() {
131    return maxStoreFileRefCount;
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  public class HRegionMetricsWrapperRunnable implements Runnable {
237
238    @Override
239    public void run() {
240      long tempNumStoreFiles = 0;
241      int tempStoreRefCount = 0;
242      int tempMaxStoreFileRefCount = 0;
243      long tempMemstoreSize = 0;
244      long tempStoreFileSize = 0;
245      long tempMaxStoreFileAge = 0;
246      long tempMinStoreFileAge = Long.MAX_VALUE;
247      long tempNumReferenceFiles = 0;
248      long tempMaxCompactionQueueSize = 0;
249      long tempMaxFlushQueueSize = 0;
250      long avgAgeNumerator = 0;
251      long numHFiles = 0;
252      if (region.stores != null) {
253        for (HStore store : region.stores.values()) {
254          tempNumStoreFiles += store.getStorefilesCount();
255          int currentStoreRefCount = store.getStoreRefCount();
256          tempStoreRefCount += currentStoreRefCount;
257          int currentMaxStoreFileRefCount = store.getMaxStoreFileRefCount();
258          tempMaxStoreFileRefCount = Math.max(tempMaxStoreFileRefCount,
259            currentMaxStoreFileRefCount);
260          tempMemstoreSize += store.getMemStoreSize().getDataSize();
261          tempStoreFileSize += store.getStorefilesSize();
262          OptionalLong storeMaxStoreFileAge = store.getMaxStoreFileAge();
263          if (storeMaxStoreFileAge.isPresent() &&
264              storeMaxStoreFileAge.getAsLong() > tempMaxStoreFileAge) {
265            tempMaxStoreFileAge = storeMaxStoreFileAge.getAsLong();
266          }
267
268          OptionalLong storeMinStoreFileAge = store.getMinStoreFileAge();
269          if (storeMinStoreFileAge.isPresent() &&
270              storeMinStoreFileAge.getAsLong() < tempMinStoreFileAge) {
271            tempMinStoreFileAge = storeMinStoreFileAge.getAsLong();
272          }
273
274          long storeHFiles = store.getNumHFiles();
275          numHFiles += storeHFiles;
276          tempNumReferenceFiles += store.getNumReferenceFiles();
277
278          OptionalDouble storeAvgStoreFileAge = store.getAvgStoreFileAge();
279          if (storeAvgStoreFileAge.isPresent()) {
280            avgAgeNumerator += (long) storeAvgStoreFileAge.getAsDouble() * storeHFiles;
281          }
282        }
283      }
284
285      numStoreFiles = tempNumStoreFiles;
286      storeRefCount = tempStoreRefCount;
287      maxStoreFileRefCount = tempMaxStoreFileRefCount;
288      memstoreSize = tempMemstoreSize;
289      storeFileSize = tempStoreFileSize;
290      maxStoreFileAge = tempMaxStoreFileAge;
291      if (tempMinStoreFileAge != Long.MAX_VALUE) {
292        minStoreFileAge = tempMinStoreFileAge;
293      }
294
295      if (numHFiles != 0) {
296        avgStoreFileAge = avgAgeNumerator / numHFiles;
297      }
298
299      numReferenceFiles = tempNumReferenceFiles;
300      tempMaxCompactionQueueSize = getNumCompactionsQueued();
301      tempMaxFlushQueueSize = getNumFlushesQueued();
302      if (tempMaxCompactionQueueSize > maxCompactionQueueSize) {
303        maxCompactionQueueSize = tempMaxCompactionQueueSize;
304      }
305      if (tempMaxFlushQueueSize > maxFlushQueueSize) {
306        maxFlushQueueSize = tempMaxFlushQueueSize;
307      }
308    }
309  }
310
311  @Override
312  public void close() throws IOException {
313    regionMetricsUpdateTask.cancel(true);
314  }
315
316  /**
317   * Get the replica id of this region.
318   */
319  @Override
320  public int getReplicaId() {
321    return region.getRegionInfo().getReplicaId();
322  }
323
324}