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 memstoreSize;
052  private long storeFileSize;
053  private long maxStoreFileAge;
054  private long minStoreFileAge;
055  private long avgStoreFileAge;
056  private long numReferenceFiles;
057  private long maxFlushQueueSize;
058  private long maxCompactionQueueSize;
059
060  private ScheduledFuture<?> regionMetricsUpdateTask;
061
062  public MetricsRegionWrapperImpl(HRegion region) {
063    this.region = region;
064    this.executor = CompatibilitySingletonFactory.getInstance(MetricsExecutor.class).getExecutor();
065    this.runnable = new HRegionMetricsWrapperRunnable();
066    this.regionMetricsUpdateTask = this.executor.scheduleWithFixedDelay(this.runnable, PERIOD,
067      PERIOD, TimeUnit.SECONDS);
068  }
069
070  @Override
071  public String getTableName() {
072    TableDescriptor tableDesc = this.region.getTableDescriptor();
073    if (tableDesc == null) {
074      return UNKNOWN;
075    }
076    return tableDesc.getTableName().getQualifierAsString();
077  }
078
079  @Override
080  public String getNamespace() {
081    TableDescriptor tableDesc = this.region.getTableDescriptor();
082    if (tableDesc == null) {
083      return UNKNOWN;
084    }
085    return tableDesc.getTableName().getNamespaceAsString();
086  }
087
088
089  @Override
090  public String getRegionName() {
091    RegionInfo regionInfo = this.region.getRegionInfo();
092    if (regionInfo == null) {
093      return UNKNOWN;
094    }
095    return regionInfo.getEncodedName();
096  }
097
098  @Override
099  public long getNumStores() {
100    Map<byte[], HStore> stores = this.region.stores;
101    if (stores == null) {
102      return 0;
103    }
104    return stores.size();
105  }
106
107  @Override
108  public long getNumStoreFiles() {
109    return numStoreFiles;
110  }
111
112  @Override
113  public long getMemStoreSize() {
114    return memstoreSize;
115  }
116
117  @Override
118  public long getStoreFileSize() {
119    return storeFileSize;
120  }
121
122  @Override
123  public long getReadRequestCount() {
124    return this.region.getReadRequestsCount();
125  }
126
127  @Override
128  public long getFilteredReadRequestCount() {
129    return this.region.getFilteredReadRequestsCount();
130  }
131
132  @Override
133  public long getWriteRequestCount() {
134    return this.region.getWriteRequestsCount();
135  }
136
137  @Override
138  public long getNumFilesCompacted() {
139    return this.region.compactionNumFilesCompacted.sum();
140  }
141
142  @Override
143  public long getNumBytesCompacted() {
144    return this.region.compactionNumBytesCompacted.sum();
145  }
146
147  @Override
148  public long getNumCompactionsCompleted() {
149    return this.region.compactionsFinished.sum();
150  }
151
152  @Override
153  public long getLastMajorCompactionAge() {
154    long lastMajorCompactionTs = 0L;
155    try {
156      lastMajorCompactionTs = this.region.getOldestHfileTs(true);
157    } catch (IOException ioe) {
158      LOG.error("Could not load HFile info ", ioe);
159    }
160    long now = EnvironmentEdgeManager.currentTime();
161    return now - lastMajorCompactionTs;
162  }
163
164  @Override
165  public long getTotalRequestCount() {
166    return getReadRequestCount() + getWriteRequestCount();
167  }
168
169  @Override
170  public long getNumCompactionsFailed() {
171    return this.region.compactionsFailed.sum();
172  }
173
174  @Override
175  public long getNumCompactionsQueued() {
176    return this.region.compactionsQueued.sum();
177  }
178
179  @Override
180  public long getNumFlushesQueued() {
181    return this.region.flushesQueued.sum();
182  }
183
184  @Override
185  public long getMaxCompactionQueueSize() {
186    return maxCompactionQueueSize;
187  }
188
189  @Override
190  public long getMaxFlushQueueSize() {
191    return maxFlushQueueSize;
192  }
193
194  @Override
195  public long getMaxStoreFileAge() {
196    return maxStoreFileAge;
197  }
198
199  @Override
200  public long getMinStoreFileAge() {
201    return minStoreFileAge;
202  }
203
204  @Override
205  public long getAvgStoreFileAge() {
206    return avgStoreFileAge;
207  }
208
209  @Override
210  public long getNumReferenceFiles() {
211    return numReferenceFiles;
212  }
213
214  @Override
215  public int getRegionHashCode() {
216    return this.region.hashCode();
217  }
218
219  public class HRegionMetricsWrapperRunnable implements Runnable {
220
221    @Override
222    public void run() {
223      long tempNumStoreFiles = 0;
224      long tempMemstoreSize = 0;
225      long tempStoreFileSize = 0;
226      long tempMaxStoreFileAge = 0;
227      long tempMinStoreFileAge = Long.MAX_VALUE;
228      long tempNumReferenceFiles = 0;
229      long tempMaxCompactionQueueSize = 0;
230      long tempMaxFlushQueueSize = 0;
231
232      long avgAgeNumerator = 0;
233      long numHFiles = 0;
234      if (region.stores != null) {
235        for (Store store : region.stores.values()) {
236          tempNumStoreFiles += store.getStorefilesCount();
237          tempMemstoreSize += store.getMemStoreSize().getDataSize();
238          tempStoreFileSize += store.getStorefilesSize();
239          OptionalLong storeMaxStoreFileAge = store.getMaxStoreFileAge();
240          if (storeMaxStoreFileAge.isPresent() &&
241              storeMaxStoreFileAge.getAsLong() > tempMaxStoreFileAge) {
242            tempMaxStoreFileAge = storeMaxStoreFileAge.getAsLong();
243          }
244
245          OptionalLong storeMinStoreFileAge = store.getMinStoreFileAge();
246          if (storeMinStoreFileAge.isPresent() &&
247              storeMinStoreFileAge.getAsLong() < tempMinStoreFileAge) {
248            tempMinStoreFileAge = storeMinStoreFileAge.getAsLong();
249          }
250
251          long storeHFiles = store.getNumHFiles();
252          numHFiles += storeHFiles;
253          tempNumReferenceFiles += store.getNumReferenceFiles();
254
255          OptionalDouble storeAvgStoreFileAge = store.getAvgStoreFileAge();
256          if (storeAvgStoreFileAge.isPresent()) {
257            avgAgeNumerator += (long) storeAvgStoreFileAge.getAsDouble() * storeHFiles;
258          }
259        }
260      }
261
262      numStoreFiles = tempNumStoreFiles;
263      memstoreSize = tempMemstoreSize;
264      storeFileSize = tempStoreFileSize;
265      maxStoreFileAge = tempMaxStoreFileAge;
266      if (tempMinStoreFileAge != Long.MAX_VALUE) {
267        minStoreFileAge = tempMinStoreFileAge;
268      }
269
270      if (numHFiles != 0) {
271        avgStoreFileAge = avgAgeNumerator / numHFiles;
272      }
273
274      numReferenceFiles = tempNumReferenceFiles;
275      tempMaxCompactionQueueSize = getNumCompactionsQueued();
276      tempMaxFlushQueueSize = getNumFlushesQueued();
277      if (tempMaxCompactionQueueSize > maxCompactionQueueSize) {
278        maxCompactionQueueSize = tempMaxCompactionQueueSize;
279      }
280      if (tempMaxFlushQueueSize > maxFlushQueueSize) {
281        maxFlushQueueSize = tempMaxFlushQueueSize;
282      }
283    }
284  }
285
286  @Override
287  public void close() throws IOException {
288    regionMetricsUpdateTask.cancel(true);
289  }
290
291  /**
292   * Get the replica id of this region.
293   */
294  @Override
295  public int getReplicaId() {
296    return region.getRegionInfo().getReplicaId();
297  }
298
299}