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