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.MetricsRate;
26  import org.apache.hadoop.hbase.regionserver.wal.HLog;
27  import org.apache.hadoop.hbase.util.Strings;
28  import org.apache.hadoop.metrics.MetricsContext;
29  import org.apache.hadoop.metrics.MetricsRecord;
30  import org.apache.hadoop.metrics.MetricsUtil;
31  import org.apache.hadoop.metrics.Updater;
32  import org.apache.hadoop.metrics.jvm.JvmMetrics;
33  import org.apache.hadoop.metrics.util.MetricsIntValue;
34  import org.apache.hadoop.metrics.util.MetricsLongValue;
35  import org.apache.hadoop.metrics.util.MetricsRegistry;
36  import org.apache.hadoop.metrics.util.MetricsTimeVaryingRate;
37  
38  import java.lang.management.ManagementFactory;
39  import java.lang.management.MemoryUsage;
40  
41  /**
42   * This class is for maintaining the various regionserver statistics
43   * and publishing them through the metrics interfaces.
44   * <p>
45   * This class has a number of metrics variables that are publicly accessible;
46   * these variables (objects) have methods to update their values.
47   */
48  public class RegionServerMetrics implements Updater {
49    @SuppressWarnings({"FieldCanBeLocal"})
50    private final Log LOG = LogFactory.getLog(this.getClass());
51    private final MetricsRecord metricsRecord;
52    private long lastUpdate = System.currentTimeMillis();
53    private static final int MB = 1024*1024;
54    private MetricsRegistry registry = new MetricsRegistry();
55    private final RegionServerStatistics statistics;
56  
57    public final MetricsTimeVaryingRate atomicIncrementTime =
58        new MetricsTimeVaryingRate("atomicIncrementTime", registry);
59  
60    /**
61     * Count of regions carried by this regionserver
62     */
63    public final MetricsIntValue regions =
64      new MetricsIntValue("regions", registry);
65  
66    /**
67     * Block cache size.
68     */
69    public final MetricsLongValue blockCacheSize = new MetricsLongValue("blockCacheSize", registry);
70  
71    /**
72     * Block cache free size.
73     */
74    public final MetricsLongValue blockCacheFree = new MetricsLongValue("blockCacheFree", registry);
75  
76    /**
77     * Block cache item count.
78     */
79    public final MetricsLongValue blockCacheCount = new MetricsLongValue("blockCacheCount", registry);
80  
81    /**
82     * Block hit ratio.
83     */
84    public final MetricsIntValue blockCacheHitRatio = new MetricsIntValue("blockCacheHitRatio", registry);
85  
86    /*
87     * Count of requests to the regionservers since last call to metrics update
88     */
89    private final MetricsRate requests = new MetricsRate("requests", registry);
90  
91    /**
92     * Count of stores open on the regionserver.
93     */
94    public final MetricsIntValue stores = new MetricsIntValue("stores", registry);
95  
96    /**
97     * Count of storefiles open on the regionserver.
98     */
99    public final MetricsIntValue storefiles = new MetricsIntValue("storefiles", registry);
100 
101   /**
102    * Sum of all the storefile index sizes in this regionserver in MB
103    */
104   public final MetricsIntValue storefileIndexSizeMB =
105     new MetricsIntValue("storefileIndexSizeMB", registry);
106 
107   /**
108    * Sum of all the memstore sizes in this regionserver in MB
109    */
110   public final MetricsIntValue memstoreSizeMB =
111     new MetricsIntValue("memstoreSizeMB", registry);
112 
113   /**
114    * Size of the compaction queue.
115    */
116   public final MetricsIntValue compactionQueueSize =
117     new MetricsIntValue("compactionQueueSize", registry);
118 
119   /**
120    * filesystem read latency
121    */
122   public final MetricsTimeVaryingRate fsReadLatency =
123     new MetricsTimeVaryingRate("fsReadLatency", registry);
124 
125   /**
126    * filesystem write latency
127    */
128   public final MetricsTimeVaryingRate fsWriteLatency =
129     new MetricsTimeVaryingRate("fsWriteLatency", registry);
130 
131   /**
132    * filesystem sync latency
133    */
134   public final MetricsTimeVaryingRate fsSyncLatency =
135     new MetricsTimeVaryingRate("fsSyncLatency", registry);
136 
137   public RegionServerMetrics() {
138     MetricsContext context = MetricsUtil.getContext("hbase");
139     metricsRecord = MetricsUtil.createRecord(context, "regionserver");
140     String name = Thread.currentThread().getName();
141     metricsRecord.setTag("RegionServer", name);
142     context.registerUpdater(this);
143     // Add jvmmetrics.
144     JvmMetrics.init("RegionServer", name);
145 
146     // export for JMX
147     statistics = new RegionServerStatistics(this.registry, name);
148 
149     LOG.info("Initialized");
150   }
151 
152   public void shutdown() {
153     if (statistics != null)
154       statistics.shutdown();
155   }
156 
157   /**
158    * Since this object is a registered updater, this method will be called
159    * periodically, e.g. every 5 seconds.
160    * @param unused unused argument
161    */
162   public void doUpdates(MetricsContext unused) {
163     synchronized (this) {
164       this.stores.pushMetric(this.metricsRecord);
165       this.storefiles.pushMetric(this.metricsRecord);
166       this.storefileIndexSizeMB.pushMetric(this.metricsRecord);
167       this.memstoreSizeMB.pushMetric(this.metricsRecord);
168       this.regions.pushMetric(this.metricsRecord);
169       this.requests.pushMetric(this.metricsRecord);
170       this.compactionQueueSize.pushMetric(this.metricsRecord);
171       this.blockCacheSize.pushMetric(this.metricsRecord);
172       this.blockCacheFree.pushMetric(this.metricsRecord);
173       this.blockCacheCount.pushMetric(this.metricsRecord);
174       this.blockCacheHitRatio.pushMetric(this.metricsRecord);
175 
176       // Mix in HFile and HLog metrics
177       // Be careful. Here is code for MTVR from up in hadoop:
178       // public synchronized void inc(final int numOps, final long time) {
179       //   currentData.numOperations += numOps;
180       //   currentData.time += time;
181       //   long timePerOps = time/numOps;
182       //    minMax.update(timePerOps);
183       // }
184       // Means you can't pass a numOps of zero or get a ArithmeticException / by zero.
185       int ops = (int)HFile.getReadOps();
186       if (ops != 0) this.fsReadLatency.inc(ops, HFile.getReadTime());
187       ops = (int)HFile.getWriteOps();
188       if (ops != 0) this.fsWriteLatency.inc(ops, HFile.getWriteTime());
189       // mix in HLog metrics
190       ops = (int)HLog.getWriteOps();
191       if (ops != 0) this.fsWriteLatency.inc(ops, HLog.getWriteTime());
192       ops = (int)HLog.getSyncOps();
193       if (ops != 0) this.fsSyncLatency.inc(ops, HLog.getSyncTime());
194 
195       // push the result
196       this.fsReadLatency.pushMetric(this.metricsRecord);
197       this.fsWriteLatency.pushMetric(this.metricsRecord);
198       this.fsSyncLatency.pushMetric(this.metricsRecord);
199     }
200     this.metricsRecord.update();
201     this.lastUpdate = System.currentTimeMillis();
202   }
203 
204   public void resetAllMinMax() {
205     this.atomicIncrementTime.resetMinMax();
206     this.fsReadLatency.resetMinMax();
207     this.fsWriteLatency.resetMinMax();
208   }
209 
210   /**
211    * @return Count of requests.
212    */
213   public float getRequests() {
214     return this.requests.getPreviousIntervalValue();
215   }
216 
217   /**
218    * @param inc How much to add to requests.
219    */
220   public void incrementRequests(final int inc) {
221     this.requests.inc(inc);
222   }
223 
224   @Override
225   public String toString() {
226     StringBuilder sb = new StringBuilder();
227     int seconds = (int)((System.currentTimeMillis() - this.lastUpdate)/1000);
228     if (seconds == 0) {
229       seconds = 1;
230     }
231     sb = Strings.appendKeyValue(sb, "request",
232       Float.valueOf(this.requests.getPreviousIntervalValue()));
233     sb = Strings.appendKeyValue(sb, "regions",
234       Integer.valueOf(this.regions.get()));
235     sb = Strings.appendKeyValue(sb, "stores",
236       Integer.valueOf(this.stores.get()));
237     sb = Strings.appendKeyValue(sb, "storefiles",
238       Integer.valueOf(this.storefiles.get()));
239     sb = Strings.appendKeyValue(sb, "storefileIndexSize",
240       Integer.valueOf(this.storefileIndexSizeMB.get()));
241     sb = Strings.appendKeyValue(sb, "memstoreSize",
242       Integer.valueOf(this.memstoreSizeMB.get()));
243     sb = Strings.appendKeyValue(sb, "compactionQueueSize",
244       Integer.valueOf(this.compactionQueueSize.get()));
245     // Duplicate from jvmmetrics because metrics are private there so
246     // inaccessible.
247     MemoryUsage memory =
248       ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
249     sb = Strings.appendKeyValue(sb, "usedHeap",
250       Long.valueOf(memory.getUsed()/MB));
251     sb = Strings.appendKeyValue(sb, "maxHeap",
252       Long.valueOf(memory.getMax()/MB));
253     sb = Strings.appendKeyValue(sb, this.blockCacheSize.getName(),
254         Long.valueOf(this.blockCacheSize.get()));
255     sb = Strings.appendKeyValue(sb, this.blockCacheFree.getName(),
256         Long.valueOf(this.blockCacheFree.get()));
257     sb = Strings.appendKeyValue(sb, this.blockCacheCount.getName(),
258         Long.valueOf(this.blockCacheCount.get()));
259     sb = Strings.appendKeyValue(sb, this.blockCacheHitRatio.getName(),
260         Long.valueOf(this.blockCacheHitRatio.get()));
261     return sb.toString();
262   }
263 }