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