View Javadoc

1   /*
2    * Copyright The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one or more
5    * contributor license agreements. See the NOTICE file distributed with this
6    * work for additional information regarding copyright ownership. The ASF
7    * licenses this file to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   *
11   * http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16   * License for the specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.hadoop.hbase.thrift;
21  
22  import java.lang.reflect.Method;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.apache.hadoop.conf.Configuration;
27  import org.apache.hadoop.hbase.thrift.generated.Hbase;
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.util.MetricsBase;
33  import org.apache.hadoop.metrics.util.MetricsIntValue;
34  import org.apache.hadoop.metrics.util.MetricsRegistry;
35  import org.apache.hadoop.metrics.util.MetricsTimeVaryingInt;
36  import org.apache.hadoop.metrics.util.MetricsTimeVaryingLong;
37  import org.apache.hadoop.metrics.util.MetricsTimeVaryingRate;
38  
39  /**
40   * This class is for maintaining the various statistics of thrift server
41   * and publishing them through the metrics interfaces.
42   */
43  public class ThriftMetrics implements Updater {
44    public final static Log LOG = LogFactory.getLog(ThriftMetrics.class);
45    public final static String CONTEXT_NAME = "thriftserver";
46  
47    private final MetricsContext context;
48    private final MetricsRecord metricsRecord;
49    private final MetricsRegistry registry = new MetricsRegistry();
50    private final long slowResponseTime;
51    public static final String SLOW_RESPONSE_NANO_SEC =
52      "hbase.thrift.slow.response.nano.second";
53    public static final long DEFAULT_SLOW_RESPONSE_NANO_SEC = 10 * 1000 * 1000;
54  
55    private final MetricsIntValue callQueueLen =
56        new MetricsIntValue("callQueueLen", registry);
57    private final MetricsTimeVaryingRate numRowKeysInBatchGet =
58        new MetricsTimeVaryingRate("numRowKeysInBatchGet", registry);
59    private final MetricsTimeVaryingRate numRowKeysInBatchMutate =
60        new MetricsTimeVaryingRate("numRowKeysInBatchMutate", registry);
61    private final MetricsTimeVaryingRate timeInQueue =
62        new MetricsTimeVaryingRate("timeInQueue", registry);
63    private MetricsTimeVaryingRate thriftCall =
64        new MetricsTimeVaryingRate("thriftCall", registry);
65    private MetricsTimeVaryingRate slowThriftCall =
66        new MetricsTimeVaryingRate("slowThriftCall", registry);
67  
68    public ThriftMetrics(int port, Configuration conf, Class<?> iface) {
69      slowResponseTime = conf.getLong(
70          SLOW_RESPONSE_NANO_SEC, DEFAULT_SLOW_RESPONSE_NANO_SEC);
71      context = MetricsUtil.getContext(CONTEXT_NAME);
72      metricsRecord = MetricsUtil.createRecord(context, CONTEXT_NAME);
73  
74      metricsRecord.setTag("port", port + "");
75  
76      LOG.info("Initializing RPC Metrics with port=" + port);
77  
78      context.registerUpdater(this);
79  
80      createMetricsForMethods(iface);
81    }
82  
83    public void incTimeInQueue(long time) {
84      timeInQueue.inc(time);
85    }
86  
87    public void setCallQueueLen(int len) {
88      callQueueLen.set(len);
89    }
90  
91    public void incNumRowKeysInBatchGet(int diff) {
92      numRowKeysInBatchGet.inc(diff);
93    }
94  
95    public void incNumRowKeysInBatchMutate(int diff) {
96      numRowKeysInBatchMutate.inc(diff);
97    }
98  
99    public void incMethodTime(String name, int time) {
100     MetricsTimeVaryingRate methodTimeMetrc = getMethodTimeMetrics(name);
101     if (methodTimeMetrc == null) {
102       LOG.warn(
103           "Got incMethodTime() request for method that doesnt exist: " + name);
104       return; // ignore methods that dont exist.
105     }
106 
107     // inc method specific processTime
108     methodTimeMetrc.inc(time);
109 
110     // inc general processTime
111     thriftCall.inc(time);
112     if (time > slowResponseTime) {
113       slowThriftCall.inc(time);
114     }
115   }
116 
117   private void createMetricsForMethods(Class<?> iface) {
118     LOG.debug("Creating metrics for interface " + iface.toString());
119     for (Method m : iface.getDeclaredMethods()) {
120       if (getMethodTimeMetrics(m.getName()) == null)
121         LOG.debug("Creating metrics for method:" + m.getName());
122         createMethodTimeMetrics(m.getName());
123     }
124   }
125 
126   private MetricsTimeVaryingRate getMethodTimeMetrics(String key) {
127     return (MetricsTimeVaryingRate) registry.get(key);
128   }
129 
130   private MetricsTimeVaryingRate createMethodTimeMetrics(String key) {
131     return new MetricsTimeVaryingRate(key, this.registry);
132   }
133 
134   /**
135    * Push the metrics to the monitoring subsystem on doUpdate() call.
136    */
137   public void doUpdates(final MetricsContext context) {
138     // getMetricsList() and pushMetric() are thread safe methods
139     for (MetricsBase m : registry.getMetricsList()) {
140       m.pushMetric(metricsRecord);
141     }
142     metricsRecord.update();
143   }
144 }