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    
019    package org.apache.hadoop.metrics2.lib;
020    
021    import org.apache.commons.lang.StringUtils;
022    import org.apache.hadoop.classification.InterfaceAudience;
023    import org.apache.hadoop.classification.InterfaceStability;
024    import org.apache.hadoop.metrics2.MetricsInfo;
025    import org.apache.hadoop.metrics2.MetricsRecordBuilder;
026    import org.apache.hadoop.metrics2.util.SampleStat;
027    import static org.apache.hadoop.metrics2.lib.Interns.*;
028    
029    /**
030     * A mutable metric with stats.
031     *
032     * Useful for keeping throughput/latency stats.
033     */
034    @InterfaceAudience.Public
035    @InterfaceStability.Evolving
036    public class MutableStat extends MutableMetric {
037      private final MetricsInfo numInfo;
038      private final MetricsInfo avgInfo;
039      private final MetricsInfo stdevInfo;
040      private final MetricsInfo iMinInfo;
041      private final MetricsInfo iMaxInfo;
042      private final MetricsInfo minInfo;
043      private final MetricsInfo maxInfo;
044    
045      private final SampleStat intervalStat = new SampleStat();
046      private final SampleStat prevStat = new SampleStat();
047      private final SampleStat.MinMax minMax = new SampleStat.MinMax();
048      private long numSamples = 0;
049      private boolean extended = false;
050    
051      /**
052       * Construct a sample statistics metric
053       * @param name        of the metric
054       * @param description of the metric
055       * @param sampleName  of the metric (e.g. "Ops")
056       * @param valueName   of the metric (e.g. "Time", "Latency")
057       * @param extended    create extended stats (stdev, min/max etc.) by default.
058       */
059      public MutableStat(String name, String description,
060                         String sampleName, String valueName, boolean extended) {
061        String ucName = StringUtils.capitalize(name);
062        String usName = StringUtils.capitalize(sampleName);
063        String uvName = StringUtils.capitalize(valueName);
064        String desc = StringUtils.uncapitalize(description);
065        String lsName = StringUtils.uncapitalize(sampleName);
066        String lvName = StringUtils.uncapitalize(valueName);
067        numInfo = info(ucName +"Num"+ usName, "Number of "+ lsName +" for "+ desc);
068        avgInfo = info(ucName +"Avg"+ uvName, "Average "+ lvName +" for "+ desc);
069        stdevInfo = info(ucName +"Stdev"+ uvName,
070                         "Standard deviation of "+ lvName +" for "+ desc);
071        iMinInfo = info(ucName +"IMin"+ uvName,
072                        "Interval min "+ lvName +" for "+ desc);
073        iMaxInfo = info(ucName + "IMax"+ uvName,
074                        "Interval max "+ lvName +" for "+ desc);
075        minInfo = info(ucName +"Min"+ uvName, "Min "+ lvName +" for "+ desc);
076        maxInfo = info(ucName +"Max"+ uvName, "Max "+ lvName +" for "+ desc);
077        this.extended = extended;
078      }
079    
080      /**
081       * Construct a snapshot stat metric with extended stat off by default
082       * @param name        of the metric
083       * @param description of the metric
084       * @param sampleName  of the metric (e.g. "Ops")
085       * @param valueName   of the metric (e.g. "Time", "Latency")
086       */
087      public MutableStat(String name, String description,
088                         String sampleName, String valueName) {
089        this(name, description, sampleName, valueName, false);
090      }
091    
092      /**
093       * Set whether to display the extended stats (stdev, min/max etc.) or not
094       * @param extended enable/disable displaying extended stats
095       */
096      public synchronized void setExtended(boolean extended) {
097        this.extended = extended;
098      }
099    
100      /**
101       * Add a number of samples and their sum to the running stat
102       * @param numSamples  number of samples
103       * @param sum of the samples
104       */
105      public synchronized void add(long numSamples, long sum) {
106        intervalStat.add(numSamples, sum);
107        setChanged();
108      }
109    
110      /**
111       * Add a snapshot to the metric
112       * @param value of the metric
113       */
114      public synchronized void add(long value) {
115        intervalStat.add(value);
116        minMax.add(value);
117        setChanged();
118      }
119    
120      public synchronized void snapshot(MetricsRecordBuilder builder, boolean all) {
121        if (all || changed()) {
122          numSamples += intervalStat.numSamples();
123          builder.addCounter(numInfo, numSamples)
124                 .addGauge(avgInfo, lastStat().mean());
125          if (extended) {
126            builder.addGauge(stdevInfo, lastStat().stddev())
127                   .addGauge(iMinInfo, lastStat().min())
128                   .addGauge(iMaxInfo, lastStat().max())
129                   .addGauge(minInfo, minMax.min())
130                   .addGauge(maxInfo, minMax.max());
131          }
132          if (changed()) {
133            if (numSamples > 0) {
134              intervalStat.copyTo(prevStat);
135              intervalStat.reset();
136            }
137            clearChanged();
138          }
139        }
140      }
141    
142      private SampleStat lastStat() {
143        return changed() ? intervalStat : prevStat;
144      }
145    
146      /**
147       * Reset the all time min max of the metric
148       */
149      public void resetMinMax() {
150        minMax.reset();
151      }
152    
153    }