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  
21  package org.apache.hadoop.hbase.ipc;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.hadoop.metrics.MetricsContext;
26  import org.apache.hadoop.metrics.MetricsRecord;
27  import org.apache.hadoop.metrics.MetricsUtil;
28  import org.apache.hadoop.metrics.Updater;
29  import org.apache.hadoop.metrics.util.MetricsRegistry;
30  import org.apache.hadoop.metrics.util.MetricsTimeVaryingRate;
31  
32  import java.lang.reflect.Method;
33  
34  /**
35   *
36   * This class is for maintaining  the various RPC statistics
37   * and publishing them through the metrics interfaces.
38   * This also registers the JMX MBean for RPC.
39   * <p>
40   * This class has a number of metrics variables that are publicly accessible;
41   * these variables (objects) have methods to update their values;
42   * for example:
43   *  <p> {@link #rpcQueueTime}.inc(time)
44   *
45   */
46  public class HBaseRpcMetrics implements Updater {
47    public static final String NAME_DELIM = "$";
48    private MetricsRecord metricsRecord;
49    private static Log LOG = LogFactory.getLog(HBaseRpcMetrics.class);
50    private final HBaseRPCStatistics rpcStatistics;
51  
52    public HBaseRpcMetrics(String hostName, String port) {
53      MetricsContext context = MetricsUtil.getContext("rpc");
54      metricsRecord = MetricsUtil.createRecord(context, "metrics");
55  
56      metricsRecord.setTag("port", port);
57  
58      LOG.info("Initializing RPC Metrics with hostName="
59          + hostName + ", port=" + port);
60  
61      context.registerUpdater(this);
62  
63      initMethods(HMasterInterface.class);
64      initMethods(HMasterRegionInterface.class);
65      initMethods(HRegionInterface.class);
66      rpcStatistics = new HBaseRPCStatistics(this.registry, hostName, port);
67    }
68  
69  
70    /**
71     * The metrics variables are public:
72     *  - they can be set directly by calling their set/inc methods
73     *  -they can also be read directly - e.g. JMX does this.
74     */
75    public final MetricsRegistry registry = new MetricsRegistry();
76  
77    public MetricsTimeVaryingRate rpcQueueTime = new MetricsTimeVaryingRate("RpcQueueTime", registry);
78    public MetricsTimeVaryingRate rpcProcessingTime = new MetricsTimeVaryingRate("RpcProcessingTime", registry);
79  
80    //public Map <String, MetricsTimeVaryingRate> metricsList = Collections.synchronizedMap(new HashMap<String, MetricsTimeVaryingRate>());
81  
82    private void initMethods(Class<? extends HBaseRPCProtocolVersion> protocol) {
83      for (Method m : protocol.getDeclaredMethods()) {
84        if (get(m.getName()) == null)
85          create(m.getName());
86      }
87    }
88  
89    private MetricsTimeVaryingRate get(String key) {
90      return (MetricsTimeVaryingRate) registry.get(key);
91    }
92    private MetricsTimeVaryingRate create(String key) {
93      return new MetricsTimeVaryingRate(key, this.registry);
94    }
95  
96    public void inc(String name, int amt) {
97      MetricsTimeVaryingRate m = get(name);
98      if (m == null) {
99        LOG.warn("Got inc() request for method that doesnt exist: " +
100       name);
101       return; // ignore methods that dont exist.
102     }
103     m.inc(amt);
104   }
105 
106   /**
107    * Generate metrics entries for all the methods defined in the list of
108    * interfaces.  A {@link MetricsTimeVaryingRate} counter will be created for
109    * each {@code Class.getMethods().getName()} entry.
110    * @param ifaces Define metrics for all methods in the given classes
111    */
112   public void createMetrics(Class<?>[] ifaces) {
113     createMetrics(ifaces, false);
114   }
115 
116   /**
117    * Generate metrics entries for all the methods defined in the list of
118    * interfaces.  A {@link MetricsTimeVaryingRate} counter will be created for
119    * each {@code Class.getMethods().getName()} entry.
120    *
121    * <p>
122    * If {@code prefixWithClass} is {@code true}, each metric will be named as
123    * {@code [Class.getSimpleName()].[Method.getName()]}.  Otherwise each metric
124    * will just be named according to the method -- {@code Method.getName()}.
125    * </p>
126    * @param ifaces Define metrics for all methods in the given classes
127    * @param prefixWithClass If {@code true}, each metric will be named as
128    *     "classname.method"
129    */
130   public void createMetrics(Class<?>[] ifaces, boolean prefixWithClass) {
131     for (Class<?> iface : ifaces) {
132       Method[] methods = iface.getMethods();
133       for (Method method : methods) {
134         String attrName = prefixWithClass ?
135             getMetricName(iface, method.getName()) : method.getName();
136         if (get(attrName) == null)
137           create(attrName);
138       }
139     }
140   }
141 
142   public static String getMetricName(Class<?> c, String method) {
143     return c.getSimpleName() + NAME_DELIM + method;
144   }
145 
146   /**
147    * Push the metrics to the monitoring subsystem on doUpdate() call.
148    * @param context ctx
149    */
150   public void doUpdates(MetricsContext context) {
151     rpcQueueTime.pushMetric(metricsRecord);
152     rpcProcessingTime.pushMetric(metricsRecord);
153 
154     synchronized (registry) {
155       // Iterate through the registry to propagate the different rpc metrics.
156 
157       for (String metricName : registry.getKeyList() ) {
158         MetricsTimeVaryingRate value = (MetricsTimeVaryingRate) registry.get(metricName);
159 
160         value.pushMetric(metricsRecord);
161       }
162     }
163     metricsRecord.update();
164   }
165 
166   public void shutdown() {
167     if (rpcStatistics != null)
168       rpcStatistics.shutdown();
169   }
170 }