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 java.util.concurrent.atomic.AtomicBoolean;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.hadoop.hbase.classification.InterfaceAudience;
26  import org.apache.hadoop.hbase.metrics.Interns;
27  import org.apache.hadoop.metrics2.MetricHistogram;
28  import org.apache.hadoop.metrics2.MetricsRecordBuilder;
29  import org.apache.hadoop.metrics2.lib.DynamicMetricsRegistry;
30  import org.apache.hadoop.metrics2.lib.MutableFastCounter;
31  
32  @InterfaceAudience.Private
33  public class MetricsRegionSourceImpl implements MetricsRegionSource {
34  
35    private static final Log LOG = LogFactory.getLog(MetricsRegionSourceImpl.class);
36  
37    private AtomicBoolean closed = new AtomicBoolean(false);
38  
39    // Non-final so that we can null out the wrapper
40    // This is just paranoia. We really really don't want to
41    // leak a whole region by way of keeping the
42    // regionWrapper around too long.
43    private MetricsRegionWrapper regionWrapper;
44  
45    private final MetricsRegionAggregateSourceImpl agg;
46    private final DynamicMetricsRegistry registry;
47  
48    private final String regionNamePrefix;
49    private final String regionPutKey;
50    private final String regionDeleteKey;
51    private final String regionGetSizeKey;
52    private final String regionGetKey;
53    private final String regionIncrementKey;
54    private final String regionAppendKey;
55    private final String regionScanSizeKey;
56    private final String regionScanTimeKey;
57  
58    private final MutableFastCounter regionPut;
59    private final MutableFastCounter regionDelete;
60    private final MutableFastCounter regionIncrement;
61    private final MutableFastCounter regionAppend;
62    private final MetricHistogram regionGetSize;
63    private final MetricHistogram regionGet;
64    private final MetricHistogram regionScanSize;
65    private final MetricHistogram regionScanTime;
66    private final int hashCode;
67  
68    public MetricsRegionSourceImpl(MetricsRegionWrapper regionWrapper,
69                                   MetricsRegionAggregateSourceImpl aggregate) {
70      this.regionWrapper = regionWrapper;
71      agg = aggregate;
72      agg.register(this);
73  
74      LOG.debug("Creating new MetricsRegionSourceImpl for table " +
75          regionWrapper.getTableName() + " " + regionWrapper.getRegionName());
76  
77      registry = agg.getMetricsRegistry();
78  
79      regionNamePrefix = "Namespace_" + regionWrapper.getNamespace() +
80          "_table_" + regionWrapper.getTableName() +
81          "_region_" + regionWrapper.getRegionName()  +
82          "_metric_";
83  
84      String suffix = "Count";
85  
86      regionPutKey = regionNamePrefix + MetricsRegionServerSource.MUTATE_KEY + suffix;
87      regionPut = registry.getCounter(regionPutKey, 0L);
88  
89      regionDeleteKey = regionNamePrefix + MetricsRegionServerSource.DELETE_KEY + suffix;
90      regionDelete = registry.getCounter(regionDeleteKey, 0L);
91  
92      regionIncrementKey = regionNamePrefix + MetricsRegionServerSource.INCREMENT_KEY + suffix;
93      regionIncrement = registry.getCounter(regionIncrementKey, 0L);
94  
95      regionAppendKey = regionNamePrefix + MetricsRegionServerSource.APPEND_KEY + suffix;
96      regionAppend = registry.getCounter(regionAppendKey, 0L);
97  
98      regionGetSizeKey = regionNamePrefix + MetricsRegionServerSource.GET_SIZE_KEY;
99      regionGetSize = registry.newSizeHistogram(regionGetSizeKey);
100 
101     regionGetKey = regionNamePrefix + MetricsRegionServerSource.GET_KEY;
102     regionGet = registry.newTimeHistogram(regionGetKey);
103 
104     regionScanSizeKey = regionNamePrefix + MetricsRegionServerSource.SCAN_SIZE_KEY;
105     regionScanSize = registry.newSizeHistogram(regionScanSizeKey);
106 
107     regionScanTimeKey = regionNamePrefix + MetricsRegionServerSource.SCAN_TIME_KEY;
108     regionScanTime = registry.newTimeHistogram(regionScanTimeKey);
109 
110     hashCode = regionWrapper.getRegionHashCode();
111   }
112 
113   @Override
114   public void close() {
115     boolean wasClosed = closed.getAndSet(true);
116 
117     // Has someone else already closed this for us?
118     if (wasClosed) {
119       return;
120     }
121 
122     // Before removing the metrics remove this region from the aggregate region bean.
123     // This should mean that it's unlikely that snapshot and close happen at the same time.
124     agg.deregister(this);
125 
126     // While it's un-likely that snapshot and close happen at the same time it's still possible.
127     // So grab the lock to ensure that all calls to snapshot are done before we remove the metrics
128     synchronized (this) {
129       if (LOG.isTraceEnabled()) {
130         LOG.trace("Removing region Metrics: " + regionWrapper.getRegionName());
131       }
132 
133       registry.removeMetric(regionPutKey);
134       registry.removeMetric(regionDeleteKey);
135       registry.removeMetric(regionIncrementKey);
136       registry.removeMetric(regionAppendKey);
137       registry.removeMetric(regionGetSizeKey);
138       registry.removeMetric(regionGetKey);
139       registry.removeMetric(regionScanSizeKey);
140       registry.removeMetric(regionScanTimeKey);
141       registry.removeHistogramMetrics(regionGetSizeKey);
142       registry.removeHistogramMetrics(regionGetKey);
143       registry.removeHistogramMetrics(regionScanSizeKey);
144       registry.removeHistogramMetrics(regionScanTimeKey);
145 
146       regionWrapper = null;
147     }
148   }
149 
150   @Override
151   public void updatePut() {
152     regionPut.incr();
153   }
154 
155   @Override
156   public void updateDelete() {
157     regionDelete.incr();
158   }
159 
160   @Override
161   public void updateGetSize(long getSize) {
162     regionGetSize.add(getSize);
163   }
164 
165   @Override
166   public void updateGet(long mills) {
167     regionGet.add(mills);
168   }
169 
170   @Override
171   public void updateScanSize(long scanSize) {
172     regionScanSize.add(scanSize);
173   }
174 
175   @Override
176   public void updateScanTime(long mills) {
177     regionScanTime.add(mills);
178   }
179 
180   @Override
181   public void updateIncrement() {
182     regionIncrement.incr();
183   }
184 
185   @Override
186   public void updateAppend() {
187     regionAppend.incr();
188   }
189 
190   @Override
191   public MetricsRegionAggregateSource getAggregateSource() {
192     return agg;
193   }
194 
195   @Override
196   public int compareTo(MetricsRegionSource source) {
197     if (!(source instanceof MetricsRegionSourceImpl)) {
198       return -1;
199     }
200 
201     MetricsRegionSourceImpl impl = (MetricsRegionSourceImpl) 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       mrb.addGauge(
231           Interns.info(
232               regionNamePrefix + MetricsRegionServerSource.STORE_COUNT,
233               MetricsRegionServerSource.STORE_COUNT_DESC),
234           this.regionWrapper.getNumStores());
235       mrb.addGauge(Interns.info(
236               regionNamePrefix + MetricsRegionServerSource.STOREFILE_COUNT,
237               MetricsRegionServerSource.STOREFILE_COUNT_DESC),
238           this.regionWrapper.getNumStoreFiles());
239       mrb.addGauge(Interns.info(
240               regionNamePrefix + MetricsRegionServerSource.MEMSTORE_SIZE,
241               MetricsRegionServerSource.MEMSTORE_SIZE_DESC),
242           this.regionWrapper.getMemstoreSize());
243       mrb.addGauge(Interns.info(
244         regionNamePrefix + MetricsRegionServerSource.MAX_STORE_FILE_AGE,
245         MetricsRegionServerSource.MAX_STORE_FILE_AGE_DESC),
246         this.regionWrapper.getMaxStoreFileAge());
247       mrb.addGauge(Interns.info(
248         regionNamePrefix + MetricsRegionServerSource.MIN_STORE_FILE_AGE,
249         MetricsRegionServerSource.MIN_STORE_FILE_AGE_DESC),
250         this.regionWrapper.getMinStoreFileAge());
251       mrb.addGauge(Interns.info(
252         regionNamePrefix + MetricsRegionServerSource.AVG_STORE_FILE_AGE,
253         MetricsRegionServerSource.AVG_STORE_FILE_AGE_DESC),
254         this.regionWrapper.getAvgStoreFileAge());
255       mrb.addGauge(Interns.info(
256         regionNamePrefix + MetricsRegionServerSource.NUM_REFERENCE_FILES,
257         MetricsRegionServerSource.NUM_REFERENCE_FILES_DESC),
258         this.regionWrapper.getNumReferenceFiles());
259       mrb.addGauge(Interns.info(
260               regionNamePrefix + MetricsRegionServerSource.STOREFILE_SIZE,
261               MetricsRegionServerSource.STOREFILE_SIZE_DESC),
262           this.regionWrapper.getStoreFileSize());
263       mrb.addCounter(Interns.info(
264               regionNamePrefix + MetricsRegionSource.COMPACTIONS_COMPLETED_COUNT,
265               MetricsRegionSource.COMPACTIONS_COMPLETED_DESC),
266           this.regionWrapper.getNumCompactionsCompleted());
267       mrb.addCounter(Interns.info(
268               regionNamePrefix + MetricsRegionSource.NUM_BYTES_COMPACTED_COUNT,
269               MetricsRegionSource.NUM_BYTES_COMPACTED_DESC),
270           this.regionWrapper.getNumBytesCompacted());
271       mrb.addCounter(Interns.info(
272               regionNamePrefix + MetricsRegionSource.NUM_FILES_COMPACTED_COUNT,
273               MetricsRegionSource.NUM_FILES_COMPACTED_DESC),
274           this.regionWrapper.getNumFilesCompacted());
275       mrb.addCounter(Interns.info(
276               regionNamePrefix + MetricsRegionServerSource.READ_REQUEST_COUNT,
277               MetricsRegionServerSource.READ_REQUEST_COUNT_DESC),
278           this.regionWrapper.getReadRequestCount());
279       mrb.addCounter(Interns.info(
280               regionNamePrefix + MetricsRegionServerSource.FILTERED_READ_REQUEST_COUNT,
281               MetricsRegionServerSource.FILTERED_READ_REQUEST_COUNT_DESC),
282           this.regionWrapper.getFilteredReadRequestCount());
283       mrb.addCounter(Interns.info(
284               regionNamePrefix + MetricsRegionServerSource.WRITE_REQUEST_COUNT,
285               MetricsRegionServerSource.WRITE_REQUEST_COUNT_DESC),
286           this.regionWrapper.getWriteRequestCount());
287       mrb.addCounter(Interns.info(regionNamePrefix + MetricsRegionSource.REPLICA_ID,
288               MetricsRegionSource.REPLICA_ID_DESC),
289           this.regionWrapper.getReplicaId());
290     }
291   }
292 
293   @Override
294   public int hashCode() {
295     return hashCode;
296   }
297 
298   @Override
299   public boolean equals(Object obj) {
300     return obj == this ||
301         (obj instanceof MetricsRegionSourceImpl && compareTo((MetricsRegionSourceImpl) obj) == 0);
302   }
303 }