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.metrics2.MetricsRecordBuilder;
27  import org.apache.hadoop.metrics2.lib.DynamicMetricsRegistry;
28  import org.apache.hadoop.metrics2.lib.Interns;
29  import org.apache.hadoop.metrics2.lib.MutableCounterLong;
30  import org.apache.hadoop.metrics2.lib.MutableHistogram;
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 regionGetKey;
52    private final String regionIncrementKey;
53    private final String regionAppendKey;
54    private final String regionScanNextKey;
55  
56    private final MutableCounterLong regionPut;
57    private final MutableCounterLong regionDelete;
58    private final MutableCounterLong regionIncrement;
59    private final MutableCounterLong regionAppend;
60    private final MutableHistogram regionGet;
61    private final MutableHistogram regionScanNext;
62    private final int hashCode;
63  
64    public MetricsRegionSourceImpl(MetricsRegionWrapper regionWrapper,
65                                   MetricsRegionAggregateSourceImpl aggregate) {
66      this.regionWrapper = regionWrapper;
67      agg = aggregate;
68      agg.register(this);
69  
70      LOG.debug("Creating new MetricsRegionSourceImpl for table " +
71          regionWrapper.getTableName() + " " + regionWrapper.getRegionName());
72  
73      registry = agg.getMetricsRegistry();
74  
75      regionNamePrefix = "Namespace_" + regionWrapper.getNamespace() +
76          "_table_" + regionWrapper.getTableName() +
77          "_region_" + regionWrapper.getRegionName()  +
78          "_metric_";
79  
80      String suffix = "Count";
81  
82      regionPutKey = regionNamePrefix + MetricsRegionServerSource.MUTATE_KEY + suffix;
83      regionPut = registry.getLongCounter(regionPutKey, 0L);
84  
85      regionDeleteKey = regionNamePrefix + MetricsRegionServerSource.DELETE_KEY + suffix;
86      regionDelete = registry.getLongCounter(regionDeleteKey, 0L);
87  
88      regionIncrementKey = regionNamePrefix + MetricsRegionServerSource.INCREMENT_KEY + suffix;
89      regionIncrement = registry.getLongCounter(regionIncrementKey, 0L);
90  
91      regionAppendKey = regionNamePrefix + MetricsRegionServerSource.APPEND_KEY + suffix;
92      regionAppend = registry.getLongCounter(regionAppendKey, 0L);
93  
94      regionGetKey = regionNamePrefix + MetricsRegionServerSource.GET_KEY;
95      regionGet = registry.newTimeHistogram(regionGetKey);
96  
97      regionScanNextKey = regionNamePrefix + MetricsRegionServerSource.SCAN_NEXT_KEY;
98      regionScanNext = registry.newTimeHistogram(regionScanNextKey);
99  
100     hashCode = regionWrapper.getRegionHashCode();
101   }
102 
103   @Override
104   public void close() {
105     boolean wasClosed = closed.getAndSet(true);
106 
107     // Has someone else already closed this for us?
108     if (wasClosed) {
109       return;
110     }
111 
112     // Before removing the metrics remove this region from the aggregate region bean.
113     // This should mean that it's unlikely that snapshot and close happen at the same time.
114     agg.deregister(this);
115 
116     // While it's un-likely that snapshot and close happen at the same time it's still possible.
117     // So grab the lock to ensure that all calls to snapshot are done before we remove the metrics
118     synchronized (this) {
119       if (LOG.isTraceEnabled()) {
120         LOG.trace("Removing region Metrics: " + regionWrapper.getRegionName());
121       }
122 
123       registry.removeMetric(regionPutKey);
124       registry.removeMetric(regionDeleteKey);
125       registry.removeMetric(regionIncrementKey);
126       registry.removeMetric(regionAppendKey);
127       registry.removeMetric(regionGetKey);
128       registry.removeMetric(regionScanNextKey);
129       registry.removeHistogramMetrics(regionGetKey);
130       registry.removeHistogramMetrics(regionScanNextKey);
131 
132       regionWrapper = null;
133     }
134   }
135 
136   @Override
137   public void updatePut() {
138     regionPut.incr();
139   }
140 
141   @Override
142   public void updateDelete() {
143     regionDelete.incr();
144   }
145 
146   @Override
147   public void updateGet(long getSize) {
148     regionGet.add(getSize);
149   }
150 
151   @Override
152   public void updateScan(long scanSize) {
153     regionScanNext.add(scanSize);
154   }
155 
156   @Override
157   public void updateIncrement() {
158     regionIncrement.incr();
159   }
160 
161   @Override
162   public void updateAppend() {
163     regionAppend.incr();
164   }
165 
166   @Override
167   public MetricsRegionAggregateSource getAggregateSource() {
168     return agg;
169   }
170 
171   @Override
172   public int compareTo(MetricsRegionSource source) {
173     if (!(source instanceof MetricsRegionSourceImpl)) {
174       return -1;
175     }
176 
177     MetricsRegionSourceImpl impl = (MetricsRegionSourceImpl) source;
178     if (impl == null) {
179       return -1;
180     }
181 
182     return Long.compare(hashCode, impl.hashCode);
183   }
184 
185   void snapshot(MetricsRecordBuilder mrb, boolean ignored) {
186 
187     // If there is a close that started be double extra sure
188     // that we're not getting any locks and not putting data
189     // into the metrics that should be removed. So early out
190     // before even getting the lock.
191     if (closed.get()) {
192       return;
193     }
194 
195     // Grab the read
196     // This ensures that removes of the metrics
197     // can't happen while we are putting them back in.
198     synchronized (this) {
199 
200       // It's possible that a close happened between checking
201       // the closed variable and getting the lock.
202       if (closed.get()) {
203         return;
204       }
205 
206       mrb.addGauge(
207           Interns.info(
208               regionNamePrefix + MetricsRegionServerSource.STORE_COUNT,
209               MetricsRegionServerSource.STORE_COUNT_DESC),
210           this.regionWrapper.getNumStores());
211       mrb.addGauge(Interns.info(
212               regionNamePrefix + MetricsRegionServerSource.STOREFILE_COUNT,
213               MetricsRegionServerSource.STOREFILE_COUNT_DESC),
214           this.regionWrapper.getNumStoreFiles());
215       mrb.addGauge(Interns.info(
216               regionNamePrefix + MetricsRegionServerSource.MEMSTORE_SIZE,
217               MetricsRegionServerSource.MEMSTORE_SIZE_DESC),
218           this.regionWrapper.getMemstoreSize());
219       mrb.addGauge(Interns.info(
220               regionNamePrefix + MetricsRegionServerSource.STOREFILE_SIZE,
221               MetricsRegionServerSource.STOREFILE_SIZE_DESC),
222           this.regionWrapper.getStoreFileSize());
223       mrb.addCounter(Interns.info(
224               regionNamePrefix + MetricsRegionSource.COMPACTIONS_COMPLETED_COUNT,
225               MetricsRegionSource.COMPACTIONS_COMPLETED_DESC),
226           this.regionWrapper.getNumCompactionsCompleted());
227       mrb.addCounter(Interns.info(
228               regionNamePrefix + MetricsRegionSource.NUM_BYTES_COMPACTED_COUNT,
229               MetricsRegionSource.NUM_BYTES_COMPACTED_DESC),
230           this.regionWrapper.getNumBytesCompacted());
231       mrb.addCounter(Interns.info(
232               regionNamePrefix + MetricsRegionSource.NUM_FILES_COMPACTED_COUNT,
233               MetricsRegionSource.NUM_FILES_COMPACTED_DESC),
234           this.regionWrapper.getNumFilesCompacted());
235       mrb.addCounter(Interns.info(
236               regionNamePrefix + MetricsRegionServerSource.READ_REQUEST_COUNT,
237               MetricsRegionServerSource.READ_REQUEST_COUNT_DESC),
238           this.regionWrapper.getReadRequestCount());
239       mrb.addCounter(Interns.info(
240               regionNamePrefix + MetricsRegionServerSource.FILTERED_READ_REQUEST_COUNT,
241               MetricsRegionServerSource.FILTERED_READ_REQUEST_COUNT_DESC),
242           this.regionWrapper.getFilteredReadRequestCount());
243       mrb.addCounter(Interns.info(
244               regionNamePrefix + MetricsRegionServerSource.WRITE_REQUEST_COUNT,
245               MetricsRegionServerSource.WRITE_REQUEST_COUNT_DESC),
246           this.regionWrapper.getWriteRequestCount());
247       mrb.addCounter(Interns.info(regionNamePrefix + MetricsRegionSource.REPLICA_ID,
248               MetricsRegionSource.REPLICA_ID_DESC),
249           this.regionWrapper.getReplicaId());
250     }
251   }
252 
253   @Override
254   public int hashCode() {
255     return hashCode;
256   }
257 
258   @Override
259   public boolean equals(Object obj) {
260     return obj == this ||
261         (obj instanceof MetricsRegionSourceImpl && compareTo((MetricsRegionSourceImpl) obj) == 0);
262   }
263 }