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.metrics2.lib; 020 021import org.apache.commons.lang.StringUtils; 022import org.apache.hadoop.classification.InterfaceAudience; 023import org.apache.hadoop.classification.InterfaceStability; 024import org.apache.hadoop.metrics2.MetricsInfo; 025import org.apache.hadoop.metrics2.MetricsRecordBuilder; 026import org.apache.hadoop.metrics2.util.SampleStat; 027import 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 036public 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 * 103 * Note that although use of this method will preserve accurate mean values, 104 * large values for numSamples may result in inaccurate variance values due 105 * to the use of a single step of the Welford method for variance calculation. 106 * @param numSamples number of samples 107 * @param sum of the samples 108 */ 109 public synchronized void add(long numSamples, long sum) { 110 intervalStat.add(numSamples, sum); 111 setChanged(); 112 } 113 114 /** 115 * Add a snapshot to the metric 116 * @param value of the metric 117 */ 118 public synchronized void add(long value) { 119 intervalStat.add(value); 120 minMax.add(value); 121 setChanged(); 122 } 123 124 public synchronized void snapshot(MetricsRecordBuilder builder, boolean all) { 125 if (all || changed()) { 126 numSamples += intervalStat.numSamples(); 127 builder.addCounter(numInfo, numSamples) 128 .addGauge(avgInfo, lastStat().mean()); 129 if (extended) { 130 builder.addGauge(stdevInfo, lastStat().stddev()) 131 .addGauge(iMinInfo, lastStat().min()) 132 .addGauge(iMaxInfo, lastStat().max()) 133 .addGauge(minInfo, minMax.min()) 134 .addGauge(maxInfo, minMax.max()); 135 } 136 if (changed()) { 137 if (numSamples > 0) { 138 intervalStat.copyTo(prevStat); 139 intervalStat.reset(); 140 } 141 clearChanged(); 142 } 143 } 144 } 145 146 /** 147 * Return a SampleStat object that supports 148 * calls like StdDev and Mean. 149 * @return SampleStat 150 */ 151 public SampleStat lastStat() { 152 return changed() ? intervalStat : prevStat; 153 } 154 155 /** 156 * Reset the all time min max of the metric 157 */ 158 public void resetMinMax() { 159 minMax.reset(); 160 } 161 162 @Override 163 public String toString() { 164 return lastStat().toString(); 165 } 166}