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.MetricsRate;
27  import org.apache.hadoop.hbase.metrics.PersistentMetricsTimeVaryingRate;
28  import org.apache.hadoop.hbase.regionserver.wal.HLog;
29  import org.apache.hadoop.hbase.util.Pair;
30  import org.apache.hadoop.hbase.util.Strings;
31  import org.apache.hadoop.metrics.ContextFactory;
32  import org.apache.hadoop.metrics.MetricsContext;
33  import org.apache.hadoop.metrics.MetricsRecord;
34  import org.apache.hadoop.metrics.MetricsUtil;
35  import org.apache.hadoop.metrics.Updater;
36  import org.apache.hadoop.metrics.jvm.JvmMetrics;
37  import org.apache.hadoop.metrics.util.MetricsIntValue;
38  import org.apache.hadoop.metrics.util.MetricsLongValue;
39  import org.apache.hadoop.metrics.util.MetricsRegistry;
40  import org.apache.hadoop.metrics.util.MetricsTimeVaryingRate;
41  import org.apache.hadoop.util.StringUtils;
42  
43  import java.io.IOException;
44  import java.lang.management.ManagementFactory;
45  import java.lang.management.MemoryUsage;
46  import java.util.List;
47  
48  /**
49   * This class is for maintaining the various regionserver statistics
50   * and publishing them through the metrics interfaces.
51   * <p>
52   * This class has a number of metrics variables that are publicly accessible;
53   * these variables (objects) have methods to update their values.
54   */
55  public class RegionServerMetrics implements Updater {
56    @SuppressWarnings({"FieldCanBeLocal"})
57    private final Log LOG = LogFactory.getLog(this.getClass());
58    private final MetricsRecord metricsRecord;
59    private long lastUpdate = System.currentTimeMillis();
60    private long lastExtUpdate = System.currentTimeMillis();
61    private long extendedPeriod = 0;
62    private static final int MB = 1024*1024;
63    private MetricsRegistry registry = new MetricsRegistry();
64    private final RegionServerStatistics statistics;
65  
66    public final MetricsTimeVaryingRate atomicIncrementTime =
67        new MetricsTimeVaryingRate("atomicIncrementTime", registry);
68  
69    /**
70     * Count of regions carried by this regionserver
71     */
72    public final MetricsIntValue regions =
73      new MetricsIntValue("regions", registry);
74  
75    /**
76     * Block cache size.
77     */
78    public final MetricsLongValue blockCacheSize = new MetricsLongValue("blockCacheSize", registry);
79  
80    /**
81     * Block cache free size.
82     */
83    public final MetricsLongValue blockCacheFree = new MetricsLongValue("blockCacheFree", registry);
84  
85    /**
86     * Block cache item count.
87     */
88    public final MetricsLongValue blockCacheCount = new MetricsLongValue("blockCacheCount", registry);
89  
90    /**
91     * Block cache hit count.
92     */
93    public final MetricsLongValue blockCacheHitCount = new MetricsLongValue("blockCacheHitCount", registry);
94  
95    /**
96     * Block cache miss count.
97     */
98    public final MetricsLongValue blockCacheMissCount = new MetricsLongValue("blockCacheMissCount", registry);
99  
100   /**
101    * Block cache evict count.
102    */
103   public final MetricsLongValue blockCacheEvictedCount = new MetricsLongValue("blockCacheEvictedCount", registry);
104 
105   /**
106    * Block hit ratio.
107    */
108   public final MetricsIntValue blockCacheHitRatio = new MetricsIntValue("blockCacheHitRatio", registry);
109 
110   /**
111    * Block hit caching ratio.  This only includes the requests to the block
112    * cache where caching was turned on.  See HBASE-2253.
113    */
114   public final MetricsIntValue blockCacheHitCachingRatio = new MetricsIntValue("blockCacheHitCachingRatio", registry);
115 
116   /*
117    * Count of requests to the regionservers since last call to metrics update
118    */
119   public final MetricsRate requests = new MetricsRate("requests", registry);
120 
121   /**
122    * Count of stores open on the regionserver.
123    */
124   public final MetricsIntValue stores = new MetricsIntValue("stores", registry);
125 
126   /**
127    * Count of storefiles open on the regionserver.
128    */
129   public final MetricsIntValue storefiles = new MetricsIntValue("storefiles", registry);
130 
131   /**
132    * Count of read requests
133    */
134   public final MetricsLongValue readRequestsCount = new MetricsLongValue("readRequestsCount", registry);
135 
136   /**
137    * Count of write requests
138    */
139   public final MetricsLongValue writeRequestsCount = new MetricsLongValue("writeRequestsCount", registry);
140 
141   /**
142    */
143   public final MetricsIntValue storefileIndexSizeMB =
144     new MetricsIntValue("storefileIndexSizeMB", registry);
145 
146   /** The total size of block index root levels in this regionserver in KB. */
147   public final MetricsIntValue rootIndexSizeKB =
148     new MetricsIntValue("rootIndexSizeKB", registry);
149 
150   /** Total size of all block indexes (not necessarily loaded in memory) */
151   public final MetricsIntValue totalStaticIndexSizeKB =
152     new MetricsIntValue("totalStaticIndexSizeKB", registry);
153 
154   /** Total size of all Bloom filters (not necessarily loaded in memory) */
155   public final MetricsIntValue totalStaticBloomSizeKB =
156     new MetricsIntValue("totalStaticBloomSizeKB", registry);
157 
158   /**
159    * HDFS blocks locality index
160    */
161   public final MetricsIntValue hdfsBlocksLocalityIndex =
162     new MetricsIntValue("hdfsBlocksLocalityIndex", registry);
163   
164   /**
165    * Sum of all the memstore sizes in this regionserver in MB
166    */
167   public final MetricsIntValue memstoreSizeMB =
168     new MetricsIntValue("memstoreSizeMB", registry);
169 
170   /**
171    * Size of the compaction queue.
172    */
173   public final MetricsIntValue compactionQueueSize =
174     new MetricsIntValue("compactionQueueSize", registry);
175   
176   /**
177    * Size of the flush queue.
178    */
179   public final MetricsIntValue flushQueueSize =
180     new MetricsIntValue("flushQueueSize", registry);
181 
182   /**
183    * filesystem read latency
184    */
185   public final MetricsTimeVaryingRate fsReadLatency =
186     new MetricsTimeVaryingRate("fsReadLatency", registry);
187 
188   /**
189    * filesystem write latency
190    */
191   public final MetricsTimeVaryingRate fsWriteLatency =
192     new MetricsTimeVaryingRate("fsWriteLatency", registry);
193 
194   /**
195    * filesystem sync latency
196    */
197   public final MetricsTimeVaryingRate fsSyncLatency =
198     new MetricsTimeVaryingRate("fsSyncLatency", registry);
199 
200   /**
201    * time each scheduled compaction takes
202    */
203   protected final PersistentMetricsTimeVaryingRate compactionTime =
204     new PersistentMetricsTimeVaryingRate("compactionTime", registry);
205 
206   protected final PersistentMetricsTimeVaryingRate compactionSize =
207     new PersistentMetricsTimeVaryingRate("compactionSize", registry);
208 
209   /**
210    * time each scheduled flush takes
211    */
212   protected final PersistentMetricsTimeVaryingRate flushTime =
213     new PersistentMetricsTimeVaryingRate("flushTime", registry);
214 
215   protected final PersistentMetricsTimeVaryingRate flushSize =
216     new PersistentMetricsTimeVaryingRate("flushSize", registry);
217 
218   public RegionServerMetrics() {
219     MetricsContext context = MetricsUtil.getContext("hbase");
220     metricsRecord = MetricsUtil.createRecord(context, "regionserver");
221     String name = Thread.currentThread().getName();
222     metricsRecord.setTag("RegionServer", name);
223     context.registerUpdater(this);
224     // Add jvmmetrics.
225     JvmMetrics.init("RegionServer", name);
226     // Add Hbase Info metrics
227     HBaseInfo.init();
228 
229     // export for JMX
230     statistics = new RegionServerStatistics(this.registry, name);
231 
232     // get custom attributes
233     try {
234       Object m = ContextFactory.getFactory().getAttribute("hbase.extendedperiod");
235       if (m instanceof String) {
236         this.extendedPeriod = Long.parseLong((String) m)*1000;
237       }
238     } catch (IOException ioe) {
239       LOG.info("Couldn't load ContextFactory for Metrics config info");
240     }
241 
242     LOG.info("Initialized");
243   }
244 
245   public void shutdown() {
246     if (statistics != null)
247       statistics.shutdown();
248   }
249 
250   /**
251    * Since this object is a registered updater, this method will be called
252    * periodically, e.g. every 5 seconds.
253    * @param caller the metrics context that this responsible for calling us
254    */
255   public void doUpdates(MetricsContext caller) {
256     synchronized (this) {
257       this.lastUpdate = System.currentTimeMillis();
258 
259       // has the extended period for long-living stats elapsed?
260       if (this.extendedPeriod > 0 &&
261           this.lastUpdate - this.lastExtUpdate >= this.extendedPeriod) {
262         this.lastExtUpdate = this.lastUpdate;
263         this.compactionTime.resetMinMaxAvg();
264         this.compactionSize.resetMinMaxAvg();
265         this.flushTime.resetMinMaxAvg();
266         this.flushSize.resetMinMaxAvg();
267         this.resetAllMinMax();
268       }
269 
270       this.stores.pushMetric(this.metricsRecord);
271       this.storefiles.pushMetric(this.metricsRecord);
272       this.storefileIndexSizeMB.pushMetric(this.metricsRecord);
273       this.rootIndexSizeKB.pushMetric(this.metricsRecord);
274       this.totalStaticIndexSizeKB.pushMetric(this.metricsRecord);
275       this.totalStaticBloomSizeKB.pushMetric(this.metricsRecord);
276       this.memstoreSizeMB.pushMetric(this.metricsRecord);
277       this.readRequestsCount.pushMetric(this.metricsRecord);
278       this.writeRequestsCount.pushMetric(this.metricsRecord);
279       this.regions.pushMetric(this.metricsRecord);
280       this.requests.pushMetric(this.metricsRecord);
281       this.compactionQueueSize.pushMetric(this.metricsRecord);
282       this.flushQueueSize.pushMetric(this.metricsRecord);
283       this.blockCacheSize.pushMetric(this.metricsRecord);
284       this.blockCacheFree.pushMetric(this.metricsRecord);
285       this.blockCacheCount.pushMetric(this.metricsRecord);
286       this.blockCacheHitCount.pushMetric(this.metricsRecord);
287       this.blockCacheMissCount.pushMetric(this.metricsRecord);
288       this.blockCacheEvictedCount.pushMetric(this.metricsRecord);
289       this.blockCacheHitRatio.pushMetric(this.metricsRecord);
290       this.blockCacheHitCachingRatio.pushMetric(this.metricsRecord);
291       this.hdfsBlocksLocalityIndex.pushMetric(this.metricsRecord);
292 
293       // Mix in HFile and HLog metrics
294       // Be careful. Here is code for MTVR from up in hadoop:
295       // public synchronized void inc(final int numOps, final long time) {
296       //   currentData.numOperations += numOps;
297       //   currentData.time += time;
298       //   long timePerOps = time/numOps;
299       //    minMax.update(timePerOps);
300       // }
301       // Means you can't pass a numOps of zero or get a ArithmeticException / by zero.
302       int ops = (int)HFile.getReadOps();
303       if (ops != 0) this.fsReadLatency.inc(ops, HFile.getReadTimeMs());
304       ops = (int)HFile.getWriteOps();
305       if (ops != 0) this.fsWriteLatency.inc(ops, HFile.getWriteTimeMs());
306       // mix in HLog metrics
307       ops = (int)HLog.getWriteOps();
308       if (ops != 0) this.fsWriteLatency.inc(ops, HLog.getWriteTime());
309       ops = (int)HLog.getSyncOps();
310       if (ops != 0) this.fsSyncLatency.inc(ops, HLog.getSyncTime());
311 
312       // push the result
313       this.fsReadLatency.pushMetric(this.metricsRecord);
314       this.fsWriteLatency.pushMetric(this.metricsRecord);
315       this.fsSyncLatency.pushMetric(this.metricsRecord);
316       this.compactionTime.pushMetric(this.metricsRecord);
317       this.compactionSize.pushMetric(this.metricsRecord);
318       this.flushTime.pushMetric(this.metricsRecord);
319       this.flushSize.pushMetric(this.metricsRecord);
320     }
321     this.metricsRecord.update();
322   }
323 
324   public void resetAllMinMax() {
325     this.atomicIncrementTime.resetMinMax();
326     this.fsReadLatency.resetMinMax();
327     this.fsWriteLatency.resetMinMax();
328     this.fsSyncLatency.resetMinMax();
329   }
330 
331   /**
332    * @return Count of requests.
333    */
334   public float getRequests() {
335     return this.requests.getPreviousIntervalValue();
336   }
337 
338   /**
339    * @param time time that compaction took
340    * @param size bytesize of storefiles in the compaction
341    */
342   public synchronized void addCompaction(long time, long size) {
343     this.compactionTime.inc(time);
344     this.compactionSize.inc(size);
345   }
346 
347   /**
348    * @param flushes history in <time, size>
349    */
350   public synchronized void addFlush(final List<Pair<Long,Long>> flushes) {
351     for (Pair<Long,Long> f : flushes) {
352       this.flushTime.inc(f.getFirst());
353       this.flushSize.inc(f.getSecond());
354     }
355   }
356 
357   /**
358    * @param inc How much to add to requests.
359    */
360   public void incrementRequests(final int inc) {
361     this.requests.inc(inc);
362   }
363 
364   @Override
365   public String toString() {
366     StringBuilder sb = new StringBuilder();
367     sb = Strings.appendKeyValue(sb, "requestsPerSecond", Integer
368         .valueOf((int) this.requests.getPreviousIntervalValue()));
369     sb = Strings.appendKeyValue(sb, "numberOfOnlineRegions",
370       Integer.valueOf(this.regions.get()));
371     sb = Strings.appendKeyValue(sb, "numberOfStores",
372       Integer.valueOf(this.stores.get()));
373     sb = Strings.appendKeyValue(sb, "numberOfStorefiles",
374       Integer.valueOf(this.storefiles.get()));
375     sb = Strings.appendKeyValue(sb, this.storefileIndexSizeMB.getName(),
376       Integer.valueOf(this.storefileIndexSizeMB.get()));
377     sb = Strings.appendKeyValue(sb, "rootIndexSizeKB",
378         Integer.valueOf(this.rootIndexSizeKB.get()));
379     sb = Strings.appendKeyValue(sb, "totalStaticIndexSizeKB",
380         Integer.valueOf(this.totalStaticIndexSizeKB.get()));
381     sb = Strings.appendKeyValue(sb, "totalStaticBloomSizeKB",
382         Integer.valueOf(this.totalStaticBloomSizeKB.get()));
383     sb = Strings.appendKeyValue(sb, this.memstoreSizeMB.getName(),
384       Integer.valueOf(this.memstoreSizeMB.get()));
385     sb = Strings.appendKeyValue(sb, "readRequestsCount",
386         Long.valueOf(this.readRequestsCount.get()));
387     sb = Strings.appendKeyValue(sb, "writeRequestsCount",
388         Long.valueOf(this.writeRequestsCount.get()));
389     sb = Strings.appendKeyValue(sb, "compactionQueueSize",
390       Integer.valueOf(this.compactionQueueSize.get()));
391     sb = Strings.appendKeyValue(sb, "flushQueueSize",
392       Integer.valueOf(this.flushQueueSize.get()));
393     // Duplicate from jvmmetrics because metrics are private there so
394     // inaccessible.
395     MemoryUsage memory =
396       ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
397     sb = Strings.appendKeyValue(sb, "usedHeapMB",
398       Long.valueOf(memory.getUsed()/MB));
399     sb = Strings.appendKeyValue(sb, "maxHeapMB",
400       Long.valueOf(memory.getMax()/MB));
401     sb = Strings.appendKeyValue(sb, this.blockCacheSize.getName()+"MB",
402     	StringUtils.limitDecimalTo2((float)this.blockCacheSize.get()/MB));
403     sb = Strings.appendKeyValue(sb, this.blockCacheFree.getName()+"MB",
404     	StringUtils.limitDecimalTo2((float)this.blockCacheFree.get()/MB));
405     sb = Strings.appendKeyValue(sb, this.blockCacheCount.getName(),
406         Long.valueOf(this.blockCacheCount.get()));
407     sb = Strings.appendKeyValue(sb, this.blockCacheHitCount.getName(),
408         Long.valueOf(this.blockCacheHitCount.get()));
409     sb = Strings.appendKeyValue(sb, this.blockCacheMissCount.getName(),
410         Long.valueOf(this.blockCacheMissCount.get()));
411     sb = Strings.appendKeyValue(sb, this.blockCacheEvictedCount.getName(),
412         Long.valueOf(this.blockCacheEvictedCount.get()));
413     sb = Strings.appendKeyValue(sb, this.blockCacheHitRatio.getName(),
414         Long.valueOf(this.blockCacheHitRatio.get())+"%");
415     sb = Strings.appendKeyValue(sb, this.blockCacheHitCachingRatio.getName(),
416         Long.valueOf(this.blockCacheHitCachingRatio.get())+"%");
417     sb = Strings.appendKeyValue(sb, this.hdfsBlocksLocalityIndex.getName(),
418         Long.valueOf(this.hdfsBlocksLocalityIndex.get()));
419     return sb.toString();
420   }
421 }