View Javadoc

1   /**
2    * Copyright 2010 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase.regionserver.metrics;
21  
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  import org.apache.hadoop.hbase.io.hfile.HFile;
25  import org.apache.hadoop.hbase.metrics.HBaseInfo;
26  import org.apache.hadoop.hbase.metrics.PersistentMetricsTimeVaryingRate;
27  import org.apache.hadoop.hbase.regionserver.wal.HLog;
28  import org.apache.hadoop.hbase.util.Pair;
29  import org.apache.hadoop.hbase.util.Strings;
30  import org.apache.hadoop.metrics.ContextFactory;
31  import org.apache.hadoop.metrics.MetricsContext;
32  import org.apache.hadoop.metrics.MetricsRecord;
33  import org.apache.hadoop.metrics.MetricsUtil;
34  import org.apache.hadoop.metrics.Updater;
35  import org.apache.hadoop.metrics.jvm.JvmMetrics;
36  import org.apache.hadoop.metrics.util.MetricsIntValue;
37  import org.apache.hadoop.metrics.util.MetricsLongValue;
38  import org.apache.hadoop.metrics.util.MetricsRegistry;
39  import org.apache.hadoop.metrics.util.MetricsTimeVaryingRate;
40  
41  import java.io.IOException;
42  import java.lang.management.ManagementFactory;
43  import java.lang.management.MemoryUsage;
44  import java.util.List;
45  
46  /**
47   * This class is for maintaining the various regionserver statistics
48   * and publishing them through the metrics interfaces.
49   * <p>
50   * This class has a number of metrics variables that are publicly accessible;
51   * these variables (objects) have methods to update their values.
52   */
53  public class RegionServerMetrics implements Updater {
54    @SuppressWarnings({"FieldCanBeLocal"})
55    private final Log LOG = LogFactory.getLog(this.getClass());
56    private final MetricsRecord metricsRecord;
57    private long lastUpdate = System.currentTimeMillis();
58    private long lastExtUpdate = System.currentTimeMillis();
59    private long extendedPeriod = 0;
60    private static final int MB = 1024*1024;
61    private MetricsRegistry registry = new MetricsRegistry();
62    private final RegionServerStatistics statistics;
63  
64    public final MetricsTimeVaryingRate atomicIncrementTime =
65        new MetricsTimeVaryingRate("atomicIncrementTime", registry);
66  
67    /**
68     * Count of regions carried by this regionserver
69     */
70    public final MetricsIntValue regions =
71      new MetricsIntValue("regions", registry);
72  
73    /**
74     * Block cache size.
75     */
76    public final MetricsLongValue blockCacheSize = new MetricsLongValue("blockCacheSize", registry);
77  
78    /**
79     * Block cache free size.
80     */
81    public final MetricsLongValue blockCacheFree = new MetricsLongValue("blockCacheFree", registry);
82  
83    /**
84     * Block cache item count.
85     */
86    public final MetricsLongValue blockCacheCount = new MetricsLongValue("blockCacheCount", registry);
87  
88    /**
89     * Block cache hit count.
90     */
91    public final MetricsLongValue blockCacheHitCount = new MetricsLongValue("blockCacheHitCount", registry);
92  
93    /**
94     * Block cache miss count.
95     */
96    public final MetricsLongValue blockCacheMissCount = new MetricsLongValue("blockCacheMissCount", registry);
97  
98    /**
99     * Block cache evict count.
100    */
101   public final MetricsLongValue blockCacheEvictedCount = new MetricsLongValue("blockCacheEvictedCount", registry);
102 
103   /**
104    * Block hit ratio.
105    */
106   public final MetricsIntValue blockCacheHitRatio = new MetricsIntValue("blockCacheHitRatio", registry);
107 
108   /**
109    * Block hit caching ratio.  This only includes the requests to the block
110    * cache where caching was turned on.  See HBASE-2253.
111    */
112   public final MetricsIntValue blockCacheHitCachingRatio = new MetricsIntValue("blockCacheHitCachingRatio", registry);
113 
114   /**
115    * Count of requests to the regionservers since last call to metrics update
116    */
117   public final MetricsIntValue requests = new MetricsIntValue("requests", registry);
118 
119   /**
120    * Count of stores open on the regionserver.
121    */
122   public final MetricsIntValue stores = new MetricsIntValue("stores", registry);
123 
124   /**
125    * Count of storefiles open on the regionserver.
126    */
127   public final MetricsIntValue storefiles = new MetricsIntValue("storefiles", registry);
128 
129   /**
130    * Sum of all the storefile index sizes in this regionserver in MB
131    */
132   public final MetricsIntValue storefileIndexSizeMB =
133     new MetricsIntValue("storefileIndexSizeMB", registry);
134 
135   /**
136    * Sum of all the memstore sizes in this regionserver in MB
137    */
138   public final MetricsIntValue memstoreSizeMB =
139     new MetricsIntValue("memstoreSizeMB", registry);
140 
141   /**
142    * Size of the compaction queue.
143    */
144   public final MetricsIntValue compactionQueueSize =
145     new MetricsIntValue("compactionQueueSize", registry);
146   
147   /**
148    * Size of the flush queue.
149    */
150   public final MetricsIntValue flushQueueSize =
151     new MetricsIntValue("flushQueueSize", registry);
152 
153   /**
154    * filesystem read latency
155    */
156   public final MetricsTimeVaryingRate fsReadLatency =
157     new MetricsTimeVaryingRate("fsReadLatency", registry);
158 
159   /**
160    * filesystem write latency
161    */
162   public final MetricsTimeVaryingRate fsWriteLatency =
163     new MetricsTimeVaryingRate("fsWriteLatency", registry);
164 
165   /**
166    * filesystem sync latency
167    */
168   public final MetricsTimeVaryingRate fsSyncLatency =
169     new MetricsTimeVaryingRate("fsSyncLatency", registry);
170 
171   /**
172    * time each scheduled compaction takes
173    */
174   protected final PersistentMetricsTimeVaryingRate compactionTime =
175     new PersistentMetricsTimeVaryingRate("compactionTime", registry);
176 
177   protected final PersistentMetricsTimeVaryingRate compactionSize =
178     new PersistentMetricsTimeVaryingRate("compactionSize", registry);
179 
180   /**
181    * time each scheduled flush takes
182    */
183   protected final PersistentMetricsTimeVaryingRate flushTime =
184     new PersistentMetricsTimeVaryingRate("flushTime", registry);
185 
186   protected final PersistentMetricsTimeVaryingRate flushSize =
187     new PersistentMetricsTimeVaryingRate("flushSize", registry);
188 
189   public RegionServerMetrics() {
190     MetricsContext context = MetricsUtil.getContext("hbase");
191     metricsRecord = MetricsUtil.createRecord(context, "regionserver");
192     String name = Thread.currentThread().getName();
193     metricsRecord.setTag("RegionServer", name);
194     context.registerUpdater(this);
195     // Add jvmmetrics.
196     JvmMetrics.init("RegionServer", name);
197     // Add Hbase Info metrics
198     HBaseInfo.init();
199 
200     // export for JMX
201     statistics = new RegionServerStatistics(this.registry, name);
202 
203     // get custom attributes
204     try {
205       Object m = ContextFactory.getFactory().getAttribute("hbase.extendedperiod");
206       if (m instanceof String) {
207         this.extendedPeriod = Long.parseLong((String) m)*1000;
208       }
209     } catch (IOException ioe) {
210       LOG.info("Couldn't load ContextFactory for Metrics config info");
211     }
212 
213     LOG.info("Initialized");
214   }
215 
216   public void shutdown() {
217     if (statistics != null)
218       statistics.shutdown();
219   }
220 
221   /**
222    * Since this object is a registered updater, this method will be called
223    * periodically, e.g. every 5 seconds.
224    * @param caller the metrics context that this responsible for calling us
225    */
226   public void doUpdates(MetricsContext caller) {
227     synchronized (this) {
228       this.lastUpdate = System.currentTimeMillis();
229 
230       // has the extended period for long-living stats elapsed?
231       if (this.extendedPeriod > 0 &&
232           this.lastUpdate - this.lastExtUpdate >= this.extendedPeriod) {
233         this.lastExtUpdate = this.lastUpdate;
234         this.compactionTime.resetMinMaxAvg();
235         this.compactionSize.resetMinMaxAvg();
236         this.flushTime.resetMinMaxAvg();
237         this.flushSize.resetMinMaxAvg();
238         this.resetAllMinMax();
239       }
240 
241       this.stores.pushMetric(this.metricsRecord);
242       this.storefiles.pushMetric(this.metricsRecord);
243       this.storefileIndexSizeMB.pushMetric(this.metricsRecord);
244       this.memstoreSizeMB.pushMetric(this.metricsRecord);
245       this.regions.pushMetric(this.metricsRecord);
246       this.requests.pushMetric(this.metricsRecord);
247       this.compactionQueueSize.pushMetric(this.metricsRecord);
248       this.flushQueueSize.pushMetric(this.metricsRecord);
249       this.blockCacheSize.pushMetric(this.metricsRecord);
250       this.blockCacheFree.pushMetric(this.metricsRecord);
251       this.blockCacheCount.pushMetric(this.metricsRecord);
252       this.blockCacheHitCount.pushMetric(this.metricsRecord);
253       this.blockCacheMissCount.pushMetric(this.metricsRecord);
254       this.blockCacheEvictedCount.pushMetric(this.metricsRecord);
255       this.blockCacheHitRatio.pushMetric(this.metricsRecord);
256       this.blockCacheHitCachingRatio.pushMetric(this.metricsRecord);
257 
258       // Mix in HFile and HLog metrics
259       // Be careful. Here is code for MTVR from up in hadoop:
260       // public synchronized void inc(final int numOps, final long time) {
261       //   currentData.numOperations += numOps;
262       //   currentData.time += time;
263       //   long timePerOps = time/numOps;
264       //    minMax.update(timePerOps);
265       // }
266       // Means you can't pass a numOps of zero or get a ArithmeticException / by zero.
267       int ops = (int)HFile.getReadOps();
268       if (ops != 0) this.fsReadLatency.inc(ops, HFile.getReadTime());
269       ops = (int)HFile.getWriteOps();
270       if (ops != 0) this.fsWriteLatency.inc(ops, HFile.getWriteTime());
271       // mix in HLog metrics
272       ops = (int)HLog.getWriteOps();
273       if (ops != 0) this.fsWriteLatency.inc(ops, HLog.getWriteTime());
274       ops = (int)HLog.getSyncOps();
275       if (ops != 0) this.fsSyncLatency.inc(ops, HLog.getSyncTime());
276 
277       // push the result
278       this.fsReadLatency.pushMetric(this.metricsRecord);
279       this.fsWriteLatency.pushMetric(this.metricsRecord);
280       this.fsSyncLatency.pushMetric(this.metricsRecord);
281       this.compactionTime.pushMetric(this.metricsRecord);
282       this.compactionSize.pushMetric(this.metricsRecord);
283       this.flushTime.pushMetric(this.metricsRecord);
284       this.flushSize.pushMetric(this.metricsRecord);
285     }
286     this.metricsRecord.update();
287   }
288 
289   public void resetAllMinMax() {
290     this.atomicIncrementTime.resetMinMax();
291     this.fsReadLatency.resetMinMax();
292     this.fsWriteLatency.resetMinMax();
293     this.fsSyncLatency.resetMinMax();
294   }
295 
296   /**
297    * @param compact history in <time, size>
298    */
299   public synchronized void addCompaction(final Pair<Long,Long> compact) {
300      this.compactionTime.inc(compact.getFirst());
301      this.compactionSize.inc(compact.getSecond());
302   }
303 
304   /**
305    * @param flushes history in <time, size>
306    */
307   public synchronized void addFlush(final List<Pair<Long,Long>> flushes) {
308     for (Pair<Long,Long> f : flushes) {
309       this.flushTime.inc(f.getFirst());
310       this.flushSize.inc(f.getSecond());
311     }
312   }
313 
314 
315   @Override
316   public String toString() {
317     StringBuilder sb = new StringBuilder();
318     int seconds = (int)((System.currentTimeMillis() - this.lastUpdate)/1000);
319     if (seconds == 0) {
320       seconds = 1;
321     }
322     sb = Strings.appendKeyValue(sb, "requests",
323         Integer.valueOf(this.requests.get()));
324     sb = Strings.appendKeyValue(sb, "regions",
325       Integer.valueOf(this.regions.get()));
326     sb = Strings.appendKeyValue(sb, "stores",
327       Integer.valueOf(this.stores.get()));
328     sb = Strings.appendKeyValue(sb, "storefiles",
329       Integer.valueOf(this.storefiles.get()));
330     sb = Strings.appendKeyValue(sb, "storefileIndexSize",
331       Integer.valueOf(this.storefileIndexSizeMB.get()));
332     sb = Strings.appendKeyValue(sb, "memstoreSize",
333       Integer.valueOf(this.memstoreSizeMB.get()));
334     sb = Strings.appendKeyValue(sb, "compactionQueueSize",
335       Integer.valueOf(this.compactionQueueSize.get()));
336     sb = Strings.appendKeyValue(sb, "flushQueueSize",
337       Integer.valueOf(this.flushQueueSize.get()));
338     // Duplicate from jvmmetrics because metrics are private there so
339     // inaccessible.
340     MemoryUsage memory =
341       ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
342     sb = Strings.appendKeyValue(sb, "usedHeap",
343       Long.valueOf(memory.getUsed()/MB));
344     sb = Strings.appendKeyValue(sb, "maxHeap",
345       Long.valueOf(memory.getMax()/MB));
346     sb = Strings.appendKeyValue(sb, this.blockCacheSize.getName(),
347         Long.valueOf(this.blockCacheSize.get()));
348     sb = Strings.appendKeyValue(sb, this.blockCacheFree.getName(),
349         Long.valueOf(this.blockCacheFree.get()));
350     sb = Strings.appendKeyValue(sb, this.blockCacheCount.getName(),
351         Long.valueOf(this.blockCacheCount.get()));
352     sb = Strings.appendKeyValue(sb, this.blockCacheHitCount.getName(),
353         Long.valueOf(this.blockCacheHitCount.get()));
354     sb = Strings.appendKeyValue(sb, this.blockCacheMissCount.getName(),
355         Long.valueOf(this.blockCacheMissCount.get()));
356     sb = Strings.appendKeyValue(sb, this.blockCacheEvictedCount.getName(),
357         Long.valueOf(this.blockCacheEvictedCount.get()));
358     sb = Strings.appendKeyValue(sb, this.blockCacheHitRatio.getName(),
359         Long.valueOf(this.blockCacheHitRatio.get()));
360     sb = Strings.appendKeyValue(sb, this.blockCacheHitCachingRatio.getName(),
361         Long.valueOf(this.blockCacheHitCachingRatio.get()));
362     return sb.toString();
363   }
364 }