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.HashMap;
024import java.util.Map;
025import java.util.Set;
026import java.util.concurrent.ConcurrentHashMap;
027import java.util.concurrent.ScheduledExecutorService;
028import java.util.concurrent.ScheduledFuture;
029import java.util.concurrent.TimeUnit;
030
031import org.apache.hadoop.hbase.CompatibilitySingletonFactory;
032import org.apache.hadoop.hbase.HConstants;
033import org.apache.hadoop.hbase.TableName;
034import org.apache.yetus.audience.InterfaceAudience;
035import org.apache.hadoop.metrics2.MetricsExecutor;
036
037import org.apache.hbase.thirdparty.com.google.common.collect.Sets;
038
039@InterfaceAudience.Private
040public class MetricsTableWrapperAggregateImpl implements MetricsTableWrapperAggregate, Closeable {
041  private final HRegionServer regionServer;
042  private ScheduledExecutorService executor;
043  private Runnable runnable;
044  private long period;
045  private ScheduledFuture<?> tableMetricsUpdateTask;
046  private ConcurrentHashMap<TableName, MetricsTableValues> metricsTableMap
047    = new ConcurrentHashMap<>();
048
049  public MetricsTableWrapperAggregateImpl(final HRegionServer regionServer) {
050    this.regionServer = regionServer;
051    this.period = regionServer.conf.getLong(HConstants.REGIONSERVER_METRICS_PERIOD,
052      HConstants.DEFAULT_REGIONSERVER_METRICS_PERIOD) + 1000;
053    this.executor = CompatibilitySingletonFactory.getInstance(MetricsExecutor.class).getExecutor();
054    this.runnable = new TableMetricsWrapperRunnable();
055    this.tableMetricsUpdateTask = this.executor.scheduleWithFixedDelay(this.runnable, period,
056      this.period, TimeUnit.MILLISECONDS);
057  }
058
059  public class TableMetricsWrapperRunnable implements Runnable {
060
061    @Override
062    public void run() {
063      Map<TableName, MetricsTableValues> localMetricsTableMap = new HashMap<>();
064
065      for (Region r : regionServer.getOnlineRegionsLocalContext()) {
066        TableName tbl = r.getTableDescriptor().getTableName();
067        MetricsTableValues mt = localMetricsTableMap.get(tbl);
068        if (mt == null) {
069          mt = new MetricsTableValues();
070          localMetricsTableMap.put(tbl, mt);
071        }
072        if (r.getStores() != null) {
073          for (Store store : r.getStores()) {
074            mt.storeFileCount += store.getStorefilesCount();
075            mt.memstoreSize += (store.getMemStoreSize().getDataSize() +
076              store.getMemStoreSize().getHeapSize() + store.getMemStoreSize().getOffHeapSize());
077            mt.storeFileSize += store.getStorefilesSize();
078            mt.referenceFileCount += store.getNumReferenceFiles();
079
080            mt.maxStoreFileAge = Math.max(mt.maxStoreFileAge, store.getMaxStoreFileAge().getAsLong());
081            mt.minStoreFileAge = Math.min(mt.minStoreFileAge, store.getMinStoreFileAge().getAsLong());
082            mt.totalStoreFileAge = (long)store.getAvgStoreFileAge().getAsDouble() *
083                store.getStorefilesCount();
084            mt.storeCount += 1;
085          }
086          mt.regionCount += 1;
087
088          mt.readRequestCount += r.getReadRequestsCount();
089          mt.filteredReadRequestCount += getFilteredReadRequestCount(tbl.getNameAsString());
090          mt.writeRequestCount += r.getWriteRequestsCount();
091
092        }
093      }
094
095      for (Map.Entry<TableName, MetricsTableValues> entry : localMetricsTableMap.entrySet()) {
096        TableName tbl = entry.getKey();
097        if (metricsTableMap.get(tbl) == null) {
098          // this will add the Wrapper to the list of TableMetrics
099          CompatibilitySingletonFactory
100              .getInstance(MetricsRegionServerSourceFactory.class)
101              .getTableAggregate()
102              .getOrCreateTableSource(tbl.getNameAsString(), MetricsTableWrapperAggregateImpl.this);
103        }
104        metricsTableMap.put(entry.getKey(), entry.getValue());
105      }
106      Set<TableName> existingTableNames = Sets.newHashSet(metricsTableMap.keySet());
107      existingTableNames.removeAll(localMetricsTableMap.keySet());
108      MetricsTableAggregateSource agg = CompatibilitySingletonFactory
109          .getInstance(MetricsRegionServerSourceFactory.class).getTableAggregate();
110      for (TableName table : existingTableNames) {
111        agg.deleteTableSource(table.getNameAsString());
112        if (metricsTableMap.get(table) != null) {
113          metricsTableMap.remove(table);
114        }
115      }
116    }
117  }
118
119  @Override
120  public long getReadRequestCount(String table) {
121    MetricsTableValues metricsTable = metricsTableMap.get(TableName.valueOf(table));
122    if (metricsTable == null) {
123      return 0;
124    } else {
125      return metricsTable.readRequestCount;
126    }
127  }
128
129  public long getFilteredReadRequestCount(String table) {
130    MetricsTableValues metricsTable = metricsTableMap.get(TableName.valueOf(table));
131    if (metricsTable == null) {
132      return 0;
133    }
134    return metricsTable.filteredReadRequestCount;
135  }
136
137  @Override
138  public long getWriteRequestCount(String table) {
139    MetricsTableValues metricsTable = metricsTableMap.get(TableName.valueOf(table));
140    if (metricsTable == null) {
141      return 0;
142    } else {
143      return metricsTable.writeRequestCount;
144    }
145  }
146
147  @Override
148  public long getTotalRequestsCount(String table) {
149    MetricsTableValues metricsTable = metricsTableMap.get(TableName.valueOf(table));
150    if (metricsTable == null) {
151      return 0;
152    } else {
153      return metricsTable.readRequestCount + metricsTable.writeRequestCount;
154    }
155  }
156
157  @Override
158  public long getMemStoreSize(String table) {
159    MetricsTableValues metricsTable = metricsTableMap.get(TableName.valueOf(table));
160    if (metricsTable == null) {
161      return 0;
162    } else {
163      return metricsTable.memstoreSize;
164    }
165  }
166
167  @Override
168  public long getStoreFileSize(String table) {
169    MetricsTableValues metricsTable = metricsTableMap.get(TableName.valueOf(table));
170    if (metricsTable == null) {
171      return 0;
172    } else {
173      return metricsTable.storeFileSize;
174    }
175  }
176
177  @Override
178  public long getTableSize(String table) {
179    MetricsTableValues metricsTable = metricsTableMap.get(TableName.valueOf(table));
180    if (metricsTable == null) {
181      return 0;
182    } else {
183      return metricsTable.memstoreSize + metricsTable.storeFileSize;
184    }
185  }
186
187  public long getNumRegions(String table) {
188    MetricsTableValues metricsTable = metricsTableMap.get(TableName.valueOf(table));
189    if (metricsTable == null) {
190      return 0;
191    }
192    return metricsTable.regionCount;
193  }
194
195  @Override
196  public long getNumStores(String table) {
197    MetricsTableValues metricsTable = metricsTableMap.get(TableName.valueOf(table));
198    if (metricsTable == null) {
199      return 0;
200    }
201    return metricsTable.storeCount;
202  }
203
204  @Override
205  public long getNumStoreFiles(String table) {
206    MetricsTableValues metricsTable = metricsTableMap.get(TableName.valueOf(table));
207    if (metricsTable == null) {
208      return 0;
209    }
210    return metricsTable.storeFileCount;
211  }
212
213  @Override
214  public long getMaxStoreFileAge(String table) {
215    MetricsTableValues metricsTable = metricsTableMap.get(TableName.valueOf(table));
216    if (metricsTable == null) {
217      return 0;
218    }
219    return metricsTable.maxStoreFileAge;
220  }
221
222  @Override
223  public long getMinStoreFileAge(String table) {
224    MetricsTableValues metricsTable = metricsTableMap.get(TableName.valueOf(table));
225    if (metricsTable == null) {
226      return 0;
227    }
228    return metricsTable.minStoreFileAge == Long.MAX_VALUE ? 0 : metricsTable.minStoreFileAge;
229  }
230
231  @Override
232  public long getAvgStoreFileAge(String table) {
233    MetricsTableValues metricsTable = metricsTableMap.get(TableName.valueOf(table));
234    if (metricsTable == null) {
235      return 0;
236    }
237
238    return metricsTable.storeFileCount == 0
239        ? 0
240        : (metricsTable.totalStoreFileAge / metricsTable.storeFileCount);
241  }
242
243  @Override
244  public long getNumReferenceFiles(String table) {
245    MetricsTableValues metricsTable = metricsTableMap.get(TableName.valueOf(table));
246    if (metricsTable == null) {
247      return 0;
248    }
249    return metricsTable.referenceFileCount;
250  }
251
252  @Override
253  public long getAvgRegionSize(String table) {
254    MetricsTableValues metricsTable = metricsTableMap.get(TableName.valueOf(table));
255    if (metricsTable == null) {
256      return 0;
257    }
258    return metricsTable.regionCount == 0
259        ? 0
260        : (metricsTable.memstoreSize + metricsTable.storeFileSize) / metricsTable.regionCount;
261  }
262
263  public long getCpRequestCount(String table) {
264    MetricsTableValues metricsTable = metricsTableMap.get(TableName.valueOf(table));
265    if (metricsTable == null) {
266      return 0;
267    }
268    return metricsTable.cpRequestCount;
269  }
270
271  @Override
272  public void close() throws IOException {
273    tableMetricsUpdateTask.cancel(true);
274  }
275
276  private static class MetricsTableValues {
277    long readRequestCount;
278    long filteredReadRequestCount;
279    long writeRequestCount;
280    long memstoreSize;
281    long regionCount;
282    long storeCount;
283    long storeFileCount;
284    long storeFileSize;
285    long maxStoreFileAge;
286    long minStoreFileAge = Long.MAX_VALUE;
287    long totalStoreFileAge;
288    long referenceFileCount;
289    long cpRequestCount;
290  }
291
292}