View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase.regionserver;
20  
21  import static org.apache.hadoop.hbase.regionserver.MetricsRegionServerSource.*;
22  import java.util.concurrent.atomic.AtomicBoolean;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.apache.hadoop.hbase.TableName;
27  import org.apache.hadoop.hbase.classification.InterfaceAudience;
28  import org.apache.hadoop.metrics2.MetricHistogram;
29  import org.apache.hadoop.metrics2.MetricsRecordBuilder;
30  import org.apache.hadoop.metrics2.lib.DynamicMetricsRegistry;
31  import org.apache.hadoop.metrics2.lib.Interns;
32  import org.apache.hadoop.metrics2.lib.MutableFastCounter;
33  
34  @InterfaceAudience.Private
35  public class MetricsTableSourceImpl implements MetricsTableSource {
36  
37    private static final Log LOG = LogFactory.getLog(MetricsTableSourceImpl.class);
38  
39    private AtomicBoolean closed = new AtomicBoolean(false);
40  
41    // Non-final so that we can null out the wrapper
42    // This is just paranoia. We really really don't want to
43    // leak a whole table by way of keeping the
44    // tableWrapper around too long.
45    private MetricsTableWrapperAggregate tableWrapperAgg;
46    private final MetricsTableAggregateSourceImpl agg;
47    private final DynamicMetricsRegistry registry;
48    private final String tableNamePrefix;
49    private final TableName tableName;
50    private final int hashCode;
51  
52    // split related metrics
53    private MutableFastCounter splitRequest;
54    private MutableFastCounter splitSuccess;
55    private MetricHistogram splitTimeHisto;
56  
57    // flush related metrics
58    private MetricHistogram flushTimeHisto;
59    private MetricHistogram flushMemstoreSizeHisto;
60    private MetricHistogram flushOutputSizeHisto;
61    private MutableFastCounter flushedMemstoreBytes;
62    private MutableFastCounter flushedOutputBytes;
63  
64    // compaction related metrics
65    private MetricHistogram compactionTimeHisto;
66    private MetricHistogram compactionInputFileCountHisto;
67    private MetricHistogram compactionInputSizeHisto;
68    private MetricHistogram compactionOutputFileCountHisto;
69    private MetricHistogram compactionOutputSizeHisto;
70    private MutableFastCounter compactedInputBytes;
71    private MutableFastCounter compactedOutputBytes;
72  
73    private MetricHistogram majorCompactionTimeHisto;
74    private MetricHistogram majorCompactionInputFileCountHisto;
75    private MetricHistogram majorCompactionInputSizeHisto;
76    private MetricHistogram majorCompactionOutputFileCountHisto;
77    private MetricHistogram majorCompactionOutputSizeHisto;
78    private MutableFastCounter majorCompactedInputBytes;
79    private MutableFastCounter majorCompactedOutputBytes;
80  
81    public MetricsTableSourceImpl(String tblName,
82        MetricsTableAggregateSourceImpl aggregate, MetricsTableWrapperAggregate tblWrapperAgg) {
83      LOG.debug("Creating new MetricsTableSourceImpl for table ");
84      this.tableName = TableName.valueOf(tblName);
85      this.agg = aggregate;
86  
87      this.tableWrapperAgg = tblWrapperAgg;
88      this.registry = agg.getMetricsRegistry();
89      this.tableNamePrefix = "Namespace_" + this.tableName.getNamespaceAsString() +
90          "_table_" + this.tableName.getQualifierAsString() + "_metric_";
91      this.hashCode = this.tableName.hashCode();
92    }
93  
94    @Override
95    public synchronized void registerMetrics() {
96      flushTimeHisto = registry.newTimeHistogram(tableNamePrefix + FLUSH_TIME, FLUSH_TIME_DESC);
97      flushMemstoreSizeHisto =
98          registry.newSizeHistogram(tableNamePrefix + FLUSH_MEMSTORE_SIZE, FLUSH_MEMSTORE_SIZE_DESC);
99      flushOutputSizeHisto =
100         registry.newSizeHistogram(tableNamePrefix + FLUSH_OUTPUT_SIZE, FLUSH_OUTPUT_SIZE_DESC);
101     flushedOutputBytes =
102         registry.newCounter(tableNamePrefix + FLUSHED_OUTPUT_BYTES, FLUSHED_OUTPUT_BYTES_DESC, 0L);
103     flushedMemstoreBytes = registry.newCounter(tableNamePrefix + FLUSHED_MEMSTORE_BYTES,
104       FLUSHED_MEMSTORE_BYTES_DESC, 0L);
105 
106     compactionTimeHisto =
107         registry.newTimeHistogram(tableNamePrefix + COMPACTION_TIME, COMPACTION_TIME_DESC);
108     compactionInputFileCountHisto = registry.newHistogram(
109       tableNamePrefix + COMPACTION_INPUT_FILE_COUNT, COMPACTION_INPUT_FILE_COUNT_DESC);
110     compactionInputSizeHisto = registry.newSizeHistogram(tableNamePrefix + COMPACTION_INPUT_SIZE,
111       COMPACTION_INPUT_SIZE_DESC);
112     compactionOutputFileCountHisto = registry.newHistogram(
113       tableNamePrefix + COMPACTION_OUTPUT_FILE_COUNT, COMPACTION_OUTPUT_FILE_COUNT_DESC);
114     compactionOutputSizeHisto = registry.newSizeHistogram(tableNamePrefix + COMPACTION_OUTPUT_SIZE,
115       COMPACTION_OUTPUT_SIZE_DESC);
116     compactedInputBytes = registry.newCounter(tableNamePrefix + COMPACTED_INPUT_BYTES,
117       COMPACTED_INPUT_BYTES_DESC, 0L);
118     compactedOutputBytes = registry.newCounter(tableNamePrefix + COMPACTED_OUTPUT_BYTES,
119       COMPACTED_OUTPUT_BYTES_DESC, 0L);
120 
121     majorCompactionTimeHisto = registry.newTimeHistogram(tableNamePrefix + MAJOR_COMPACTION_TIME,
122       MAJOR_COMPACTION_TIME_DESC);
123     majorCompactionInputFileCountHisto = registry.newHistogram(
124       tableNamePrefix + MAJOR_COMPACTION_INPUT_FILE_COUNT, MAJOR_COMPACTION_INPUT_FILE_COUNT_DESC);
125     majorCompactionInputSizeHisto = registry.newSizeHistogram(
126       tableNamePrefix + MAJOR_COMPACTION_INPUT_SIZE, MAJOR_COMPACTION_INPUT_SIZE_DESC);
127     majorCompactionOutputFileCountHisto =
128         registry.newHistogram(tableNamePrefix + MAJOR_COMPACTION_OUTPUT_FILE_COUNT,
129           MAJOR_COMPACTION_OUTPUT_FILE_COUNT_DESC);
130     majorCompactionOutputSizeHisto = registry.newSizeHistogram(
131       tableNamePrefix + MAJOR_COMPACTION_OUTPUT_SIZE, MAJOR_COMPACTION_OUTPUT_SIZE_DESC);
132     majorCompactedInputBytes = registry.newCounter(tableNamePrefix + MAJOR_COMPACTED_INPUT_BYTES,
133       MAJOR_COMPACTED_INPUT_BYTES_DESC, 0L);
134     majorCompactedOutputBytes = registry.newCounter(tableNamePrefix + MAJOR_COMPACTED_OUTPUT_BYTES,
135       MAJOR_COMPACTED_OUTPUT_BYTES_DESC, 0L);
136 
137     splitTimeHisto = registry.newTimeHistogram(tableNamePrefix + SPLIT_KEY);
138     splitRequest = registry.newCounter(tableNamePrefix + SPLIT_REQUEST_KEY, SPLIT_REQUEST_DESC, 0L);
139     splitSuccess = registry.newCounter(tableNamePrefix + SPLIT_SUCCESS_KEY, SPLIT_SUCCESS_DESC, 0L);
140   }
141 
142   private void deregisterMetrics() {
143     registry.removeHistogramMetrics(tableNamePrefix + FLUSH_TIME);
144     registry.removeHistogramMetrics(tableNamePrefix + FLUSH_MEMSTORE_SIZE);
145     registry.removeHistogramMetrics(tableNamePrefix + FLUSH_OUTPUT_SIZE);
146     registry.removeMetric(tableNamePrefix + FLUSHED_OUTPUT_BYTES);
147     registry.removeMetric(tableNamePrefix + FLUSHED_MEMSTORE_BYTES);
148     registry.removeHistogramMetrics(tableNamePrefix + COMPACTION_TIME);
149     registry.removeHistogramMetrics(tableNamePrefix + COMPACTION_INPUT_FILE_COUNT);
150     registry.removeHistogramMetrics(tableNamePrefix + COMPACTION_INPUT_SIZE);
151     registry.removeHistogramMetrics(tableNamePrefix + COMPACTION_OUTPUT_FILE_COUNT);
152     registry.removeHistogramMetrics(tableNamePrefix + COMPACTION_OUTPUT_SIZE);
153     registry.removeMetric(tableNamePrefix + COMPACTED_INPUT_BYTES);
154     registry.removeMetric(tableNamePrefix + COMPACTED_OUTPUT_BYTES);
155     registry.removeHistogramMetrics(tableNamePrefix + MAJOR_COMPACTION_TIME);
156     registry.removeHistogramMetrics(tableNamePrefix + MAJOR_COMPACTION_INPUT_FILE_COUNT);
157     registry.removeHistogramMetrics(tableNamePrefix + MAJOR_COMPACTION_INPUT_SIZE);
158     registry.removeHistogramMetrics(tableNamePrefix + MAJOR_COMPACTION_OUTPUT_FILE_COUNT);
159     registry.removeHistogramMetrics(tableNamePrefix + MAJOR_COMPACTION_OUTPUT_SIZE);
160     registry.removeMetric(tableNamePrefix + MAJOR_COMPACTED_INPUT_BYTES);
161     registry.removeMetric(tableNamePrefix + MAJOR_COMPACTED_OUTPUT_BYTES);
162     registry.removeHistogramMetrics(tableNamePrefix + SPLIT_KEY);
163     registry.removeMetric(tableNamePrefix + SPLIT_REQUEST_KEY);
164     registry.removeMetric(tableNamePrefix + SPLIT_SUCCESS_KEY);
165   }
166 
167   @Override
168   public void close() {
169     boolean wasClosed = closed.getAndSet(true);
170 
171     // Has someone else already closed this for us?
172     if (wasClosed) {
173       return;
174     }
175 
176     // Before removing the metrics remove this table from the aggregate table bean.
177     // This should mean that it's unlikely that snapshot and close happen at the same time.
178     agg.deleteTableSource(tableName.getNameAsString());
179 
180     // While it's un-likely that snapshot and close happen at the same time it's still possible.
181     // So grab the lock to ensure that all calls to snapshot are done before we remove the metrics
182     synchronized (this) {
183       if (LOG.isTraceEnabled()) {
184         LOG.trace("Removing table Metrics for table ");
185       }
186       deregisterMetrics();
187       tableWrapperAgg = null;
188     }
189   }
190   @Override
191   public MetricsTableAggregateSource getAggregateSource() {
192     return agg;
193   }
194 
195   @Override
196   public int compareTo(MetricsTableSource source) {
197     if (!(source instanceof MetricsTableSourceImpl)) {
198       return -1;
199     }
200 
201     MetricsTableSourceImpl impl = (MetricsTableSourceImpl) source;
202     if (impl == null) {
203       return -1;
204     }
205 
206     return Long.compare(hashCode, impl.hashCode);
207   }
208 
209   void snapshot(MetricsRecordBuilder mrb, boolean ignored) {
210 
211     // If there is a close that started be double extra sure
212     // that we're not getting any locks and not putting data
213     // into the metrics that should be removed. So early out
214     // before even getting the lock.
215     if (closed.get()) {
216       return;
217     }
218 
219     // Grab the read
220     // This ensures that removes of the metrics
221     // can't happen while we are putting them back in.
222     synchronized (this) {
223 
224       // It's possible that a close happened between checking
225       // the closed variable and getting the lock.
226       if (closed.get()) {
227         return;
228       }
229 
230       if (this.tableWrapperAgg != null) {
231         mrb.addCounter(Interns.info(tableNamePrefix + MetricsRegionServerSource.READ_REQUEST_COUNT,
232           MetricsRegionServerSource.READ_REQUEST_COUNT_DESC),
233           tableWrapperAgg.getReadRequestCount(tableName.getNameAsString()));
234         mrb.addCounter(Interns.info(tableNamePrefix + MetricsRegionServerSource.WRITE_REQUEST_COUNT,
235           MetricsRegionServerSource.WRITE_REQUEST_COUNT_DESC),
236           tableWrapperAgg.getWriteRequestCount(tableName.getNameAsString()));
237         mrb.addCounter(Interns.info(tableNamePrefix + MetricsRegionServerSource.TOTAL_REQUEST_COUNT,
238           MetricsRegionServerSource.TOTAL_REQUEST_COUNT_DESC),
239           tableWrapperAgg.getTotalRequestsCount(tableName.getNameAsString()));
240         mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.MEMSTORE_SIZE,
241           MetricsRegionServerSource.MEMSTORE_SIZE_DESC),
242           tableWrapperAgg.getMemstoreSize(tableName.getNameAsString()));
243         mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.STOREFILE_COUNT,
244           MetricsRegionServerSource.STOREFILE_COUNT_DESC),
245           tableWrapperAgg.getNumStoreFiles(tableName.getNameAsString()));
246         mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.STOREFILE_SIZE,
247           MetricsRegionServerSource.STOREFILE_SIZE_DESC),
248           tableWrapperAgg.getStoreFileSize(tableName.getNameAsString()));
249         mrb.addGauge(Interns.info(tableNamePrefix + MetricsTableSource.TABLE_SIZE,
250           MetricsTableSource.TABLE_SIZE_DESC),
251           tableWrapperAgg.getTableSize(tableName.getNameAsString()));
252         mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.AVERAGE_REGION_SIZE,
253           MetricsRegionServerSource.AVERAGE_REGION_SIZE_DESC),
254           tableWrapperAgg.getAvgRegionSize(tableName.getNameAsString()));
255         mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.REGION_COUNT,
256           MetricsRegionServerSource.REGION_COUNT_DESC),
257           tableWrapperAgg.getNumRegions(tableName.getNameAsString()));
258         mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.STORE_COUNT,
259           MetricsRegionServerSource.STORE_COUNT_DESC),
260           tableWrapperAgg.getNumStores(tableName.getNameAsString()));
261         mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.MAX_STORE_FILE_AGE,
262           MetricsRegionServerSource.MAX_STORE_FILE_AGE_DESC),
263           tableWrapperAgg.getMaxStoreFileAge(tableName.getNameAsString()));
264         mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.MIN_STORE_FILE_AGE,
265           MetricsRegionServerSource.MIN_STORE_FILE_AGE_DESC),
266           tableWrapperAgg.getMinStoreFileAge(tableName.getNameAsString()));
267         mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.AVG_STORE_FILE_AGE,
268           MetricsRegionServerSource.AVG_STORE_FILE_AGE_DESC),
269           tableWrapperAgg.getAvgStoreFileAge(tableName.getNameAsString()));
270         mrb.addGauge(Interns.info(tableNamePrefix + MetricsRegionServerSource.NUM_REFERENCE_FILES,
271           MetricsRegionServerSource.NUM_REFERENCE_FILES_DESC),
272           tableWrapperAgg.getNumReferenceFiles(tableName.getNameAsString()));
273       }
274     }
275   }
276 
277   @Override
278   public String getTableName() {
279     return tableName.getNameAsString();
280   }
281 
282   @Override
283   public int hashCode() {
284     return hashCode;
285   }
286 
287   @Override
288   public boolean equals(Object o) {
289     if (this == o) return true;
290     if (o == null || getClass() != o.getClass()) return false;
291     return (o instanceof MetricsTableSourceImpl && compareTo((MetricsTableSourceImpl) o) == 0);
292   }
293 
294   public MetricsTableWrapperAggregate getTableWrapper() {
295     return tableWrapperAgg;
296   }
297 
298   public String getTableNamePrefix() {
299     return tableNamePrefix;
300   }
301 
302   @Override
303   public void incrSplitRequest() {
304     if (splitRequest == null) {
305       return;
306     }
307     splitRequest.incr();
308   }
309 
310   @Override
311   public void incrSplitSuccess() {
312     if (splitSuccess == null) {
313       return;
314     }
315     splitSuccess.incr();
316   }
317 
318   @Override
319   public void updateSplitTime(long t) {
320     if (splitTimeHisto == null) {
321       return;
322     }
323     splitTimeHisto.add(t);
324   }
325 
326   @Override
327   public void updateFlushTime(long t) {
328     if (flushTimeHisto == null) {
329       return;
330     }
331     flushTimeHisto.add(t);
332   }
333 
334   @Override
335   public void updateFlushMemstoreSize(long bytes) {
336     if (flushMemstoreSizeHisto == null || flushedMemstoreBytes == null) {
337       return;
338     }
339     flushMemstoreSizeHisto.add(bytes);
340     flushedMemstoreBytes.incr(bytes);
341   }
342 
343   @Override
344   public void updateFlushOutputSize(long bytes) {
345     if (flushOutputSizeHisto == null || flushedOutputBytes == null) {
346       return;
347     }
348     flushOutputSizeHisto.add(bytes);
349     flushedOutputBytes.incr(bytes);
350   }
351 
352   @Override
353   public void updateCompactionTime(boolean isMajor, long t) {
354     if (compactionTimeHisto == null || majorCompactionTimeHisto == null) {
355       return;
356     }
357     compactionTimeHisto.add(t);
358     if (isMajor) {
359       majorCompactionTimeHisto.add(t);
360     }
361   }
362 
363   @Override
364   public void updateCompactionInputFileCount(boolean isMajor, long c) {
365     if (compactionInputFileCountHisto == null || majorCompactionInputFileCountHisto == null) {
366       return;
367     }
368     compactionInputFileCountHisto.add(c);
369     if (isMajor) {
370       majorCompactionInputFileCountHisto.add(c);
371     }
372   }
373 
374   @Override
375   public void updateCompactionInputSize(boolean isMajor, long bytes) {
376     if (compactionInputSizeHisto == null || compactedInputBytes == null ||
377         majorCompactionInputSizeHisto == null || majorCompactedInputBytes == null) {
378       return;
379     }
380     compactionInputSizeHisto.add(bytes);
381     compactedInputBytes.incr(bytes);
382     if (isMajor) {
383       majorCompactionInputSizeHisto.add(bytes);
384       majorCompactedInputBytes.incr(bytes);
385     }
386   }
387 
388   @Override
389   public void updateCompactionOutputFileCount(boolean isMajor, long c) {
390     if (compactionOutputFileCountHisto == null || majorCompactionOutputFileCountHisto == null) {
391       return;
392     }
393     compactionOutputFileCountHisto.add(c);
394     if (isMajor) {
395       majorCompactionOutputFileCountHisto.add(c);
396     }
397   }
398 
399   @Override
400   public void updateCompactionOutputSize(boolean isMajor, long bytes) {
401     if (compactionOutputSizeHisto == null || compactedOutputBytes == null
402         || majorCompactionOutputSizeHisto == null || majorCompactedOutputBytes == null) {
403       return;
404     }
405     compactionOutputSizeHisto.add(bytes);
406     compactedOutputBytes.incr(bytes);
407     if (isMajor) {
408       majorCompactionOutputSizeHisto.add(bytes);
409       majorCompactedOutputBytes.incr(bytes);
410     }
411   }
412 }