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 */
018
019package org.apache.hadoop.hbase.client.metrics;
020
021import java.io.DataInput;
022import java.io.DataOutput;
023import java.io.IOException;
024import java.util.ArrayList;
025import java.util.Collection;
026
027import org.apache.commons.logging.Log;
028import org.apache.commons.logging.LogFactory;
029import org.apache.hadoop.hbase.HConstants;
030import org.apache.hadoop.io.Writable;
031import org.apache.hadoop.metrics.util.MetricsBase;
032import org.apache.hadoop.metrics.util.MetricsRegistry;
033import org.apache.hadoop.metrics.util.MetricsTimeVaryingLong;
034
035
036/**
037 * Provides client-side metrics related to scan operations
038 * The data can be passed to mapreduce framework or other systems.
039 * Currently metrics framework won't be able to support the scenario
040 * where multiple scan instances run on the same machine trying to
041 * update the same metric. We use metrics objects in the class,
042 * so that it can be easily switched to metrics framework later when it support
043 * this scenario.
044 * Some of these metrics are general for any client operation such as put
045 * However, there is no need for this. So they are defined under scan operation
046 * for now.
047 */
048public class ScanMetrics implements Writable {
049
050  private static final byte SCANMETRICS_VERSION = (byte)1;
051  private static final Log LOG = LogFactory.getLog(ScanMetrics.class);
052  private MetricsRegistry registry = new MetricsRegistry();
053
054  /**
055   * number of RPC calls
056   */
057  public final MetricsTimeVaryingLong countOfRPCcalls =
058    new MetricsTimeVaryingLong("RPC_CALLS", registry);
059
060  /**
061   * number of remote RPC calls
062   */
063  public final MetricsTimeVaryingLong countOfRemoteRPCcalls =
064    new MetricsTimeVaryingLong("REMOTE_RPC_CALLS", registry);
065
066  /**
067   * sum of milliseconds between sequential next calls
068   */
069  public final MetricsTimeVaryingLong sumOfMillisSecBetweenNexts =
070    new MetricsTimeVaryingLong("MILLIS_BETWEEN_NEXTS", registry);
071
072  /**
073   * number of NotServingRegionException caught
074   */
075  public final MetricsTimeVaryingLong countOfNSRE =
076    new MetricsTimeVaryingLong("NOT_SERVING_REGION_EXCEPTION", registry);
077
078  /**
079   * number of bytes in Result objects from region servers
080   */
081  public final MetricsTimeVaryingLong countOfBytesInResults =
082    new MetricsTimeVaryingLong("BYTES_IN_RESULTS", registry);
083
084  /**
085   * number of bytes in Result objects from remote region servers
086   */
087  public final MetricsTimeVaryingLong countOfBytesInRemoteResults =
088    new MetricsTimeVaryingLong("BYTES_IN_REMOTE_RESULTS", registry);
089
090  /**
091   * number of regions
092   */
093  public final MetricsTimeVaryingLong countOfRegions =
094    new MetricsTimeVaryingLong("REGIONS_SCANNED", registry);
095
096  /**
097   * number of RPC retries
098   */
099  public final MetricsTimeVaryingLong countOfRPCRetries =
100    new MetricsTimeVaryingLong("RPC_RETRIES", registry);
101
102  /**
103   * number of remote RPC retries
104   */
105  public final MetricsTimeVaryingLong countOfRemoteRPCRetries =
106    new MetricsTimeVaryingLong("REMOTE_RPC_RETRIES", registry);
107
108  /**
109   * constructor
110   */
111  public ScanMetrics () {
112  }
113
114  /**
115   * serialize all the MetricsTimeVaryingLong
116   */
117  public void write(DataOutput out) throws IOException {
118    out.writeByte(SCANMETRICS_VERSION);
119    Collection<MetricsBase> mbs = registry.getMetricsList();
120
121    // we only handle MetricsTimeVaryingLong for now.
122    int metricsCount = 0;
123    for (MetricsBase mb : mbs) {
124      if ( mb instanceof MetricsTimeVaryingLong) {
125        metricsCount++;
126      } else {
127        throw new IOException("unsupported metrics type. metrics name: "
128          + mb.getName() + ", metrics description: " + mb.getDescription());
129      }
130    }
131
132    out.writeInt(metricsCount);
133    for (MetricsBase mb : mbs) {
134      out.writeUTF(mb.getName());
135      out.writeLong(((MetricsTimeVaryingLong) mb).getCurrentIntervalValue());
136    }
137  }
138
139  public void readFields(DataInput in) throws IOException {
140    int version = in.readByte();
141    if (version > (int)SCANMETRICS_VERSION) {
142      throw new IOException("version " + version + " not supported");
143    }
144
145    int metricsCount = in.readInt();
146    for (int i=0; i<metricsCount; i++) {
147      String metricsName = in.readUTF();
148      long v = in.readLong();
149      MetricsBase mb = registry.get(metricsName);
150      if ( mb instanceof MetricsTimeVaryingLong) {
151        ((MetricsTimeVaryingLong) mb).inc(v);
152      } else {
153        LOG.warn("unsupported metrics type. metrics name: "
154          + mb.getName() + ", metrics description: " + mb.getDescription());
155      }
156    }
157  }
158
159  public MetricsTimeVaryingLong[] getMetricsTimeVaryingLongArray() {
160    Collection<MetricsBase> mbs = registry.getMetricsList();
161    ArrayList<MetricsTimeVaryingLong> mlv =
162      new ArrayList<MetricsTimeVaryingLong>();
163    for (MetricsBase mb : mbs) {
164      if ( mb instanceof MetricsTimeVaryingLong) {
165        mlv.add((MetricsTimeVaryingLong) mb);
166      }
167    }
168    return mlv.toArray(new MetricsTimeVaryingLong[mlv.size()]);
169  }
170
171}