001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.thrift;
019
020import org.apache.hadoop.conf.Configuration;
021import org.apache.hadoop.hbase.CallDroppedException;
022import org.apache.hadoop.hbase.CallQueueTooBigException;
023import org.apache.hadoop.hbase.CompatibilitySingletonFactory;
024import org.apache.hadoop.hbase.MultiActionResultTooLarge;
025import org.apache.hadoop.hbase.NotServingRegionException;
026import org.apache.hadoop.hbase.RegionTooBusyException;
027import org.apache.hadoop.hbase.UnknownScannerException;
028import org.apache.hadoop.hbase.exceptions.ClientExceptionsUtil;
029import org.apache.hadoop.hbase.exceptions.FailedSanityCheckException;
030import org.apache.hadoop.hbase.exceptions.OutOfOrderScannerNextException;
031import org.apache.hadoop.hbase.exceptions.RegionMovedException;
032import org.apache.hadoop.hbase.exceptions.RequestTooBigException;
033import org.apache.hadoop.hbase.exceptions.ScannerResetException;
034import org.apache.hadoop.hbase.quotas.QuotaExceededException;
035import org.apache.hadoop.hbase.quotas.RpcThrottlingException;
036import org.apache.hadoop.hbase.thrift.generated.IOError;
037import org.apache.hadoop.hbase.thrift2.generated.TIOError;
038import org.apache.yetus.audience.InterfaceAudience;
039import org.slf4j.Logger;
040import org.slf4j.LoggerFactory;
041
042/**
043 * This class is for maintaining the various statistics of thrift server and publishing them through
044 * the metrics interfaces.
045 */
046@InterfaceAudience.Private
047public class ThriftMetrics {
048
049  private static final Logger LOG = LoggerFactory.getLogger(ThriftMetrics.class);
050
051  public enum ThriftServerType {
052    ONE,
053    TWO
054  }
055
056  public MetricsThriftServerSource getSource() {
057    return source;
058  }
059
060  public void setSource(MetricsThriftServerSource source) {
061    this.source = source;
062  }
063
064  protected MetricsThriftServerSource source;
065  protected final long slowResponseTime;
066  public static final String SLOW_RESPONSE_NANO_SEC = "hbase.thrift.slow.response.nano.second";
067  public static final long DEFAULT_SLOW_RESPONSE_NANO_SEC = 10 * 1000 * 1000;
068  private final ThriftServerType thriftServerType;
069
070  public ThriftMetrics(Configuration conf, ThriftServerType t) {
071    slowResponseTime = conf.getLong(SLOW_RESPONSE_NANO_SEC, DEFAULT_SLOW_RESPONSE_NANO_SEC);
072    thriftServerType = t;
073    if (t == ThriftServerType.ONE) {
074      source = CompatibilitySingletonFactory.getInstance(MetricsThriftServerSourceFactory.class)
075        .createThriftOneSource();
076    } else if (t == ThriftServerType.TWO) {
077      source = CompatibilitySingletonFactory.getInstance(MetricsThriftServerSourceFactory.class)
078        .createThriftTwoSource();
079    }
080
081  }
082
083  public void incTimeInQueue(long time) {
084    source.incTimeInQueue(time);
085  }
086
087  public void setCallQueueLen(int len) {
088    source.setCallQueueLen(len);
089  }
090
091  public void incNumRowKeysInBatchGet(int diff) {
092    source.incNumRowKeysInBatchGet(diff);
093  }
094
095  public void incNumRowKeysInBatchMutate(int diff) {
096    source.incNumRowKeysInBatchMutate(diff);
097  }
098
099  public void incMethodTime(String name, long time) {
100    source.incMethodTime(name, time);
101    // inc general processTime
102    source.incCall(time);
103    if (time > slowResponseTime) {
104      source.incSlowCall(time);
105    }
106  }
107
108  public void incActiveWorkerCount() {
109    source.incActiveWorkerCount();
110  }
111
112  public void decActiveWorkerCount() {
113    source.decActiveWorkerCount();
114  }
115
116  /**
117   * Increment the count for a specific exception type. This is called for each exception type that
118   * is returned to the thrift handler.
119   * @param rawThrowable type of exception
120   */
121  public void exception(Throwable rawThrowable) {
122    source.exception();
123
124    Throwable throwable = unwrap(rawThrowable);
125    /**
126     * Keep some metrics for commonly seen exceptions Try and put the most common types first. Place
127     * child types before the parent type that they extend. If this gets much larger we might have
128     * to go to a hashmap
129     */
130    if (throwable != null) {
131      if (throwable instanceof OutOfOrderScannerNextException) {
132        source.outOfOrderException();
133      } else if (throwable instanceof RegionTooBusyException) {
134        source.tooBusyException();
135      } else if (throwable instanceof UnknownScannerException) {
136        source.unknownScannerException();
137      } else if (throwable instanceof ScannerResetException) {
138        source.scannerResetException();
139      } else if (throwable instanceof RegionMovedException) {
140        source.movedRegionException();
141      } else if (throwable instanceof NotServingRegionException) {
142        source.notServingRegionException();
143      } else if (throwable instanceof FailedSanityCheckException) {
144        source.failedSanityException();
145      } else if (throwable instanceof MultiActionResultTooLarge) {
146        source.multiActionTooLargeException();
147      } else if (throwable instanceof CallQueueTooBigException) {
148        source.callQueueTooBigException();
149      } else if (throwable instanceof QuotaExceededException) {
150        source.quotaExceededException();
151      } else if (throwable instanceof RpcThrottlingException) {
152        source.rpcThrottlingException();
153      } else if (throwable instanceof CallDroppedException) {
154        source.callDroppedException();
155      } else if (throwable instanceof RequestTooBigException) {
156        source.requestTooBigException();
157      } else {
158        source.otherExceptions();
159        if (LOG.isDebugEnabled()) {
160          LOG.debug("Unknown exception type", throwable);
161        }
162      }
163    }
164  }
165
166  protected static Throwable unwrap(Throwable t) {
167    if (t == null) {
168      return t;
169    }
170    if (t instanceof TIOError || t instanceof IOError) {
171      t = t.getCause();
172    }
173    return ClientExceptionsUtil.findException(t);
174  }
175
176  public ThriftServerType getThriftServerType() {
177    return thriftServerType;
178  }
179}