blob: 255196e809b4ce65d63d1ab438390349fe328678 [file] [log] [blame]
/*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.corba.se.spi.monitoring;
import java.util.*;
/**
* <p>
*
* @author Hemanth Puttaswamy
* </p>
* <p>
* StatisticsAccumulator accumulates the samples provided by the user and
* computes the value of minimum, maximum, sum and sample square sum. When
* the StatisticMonitoredAttribute calls getValue(), it will compute all
* the statistics for the collected samples (Which are Minimum, Maximum,
* Average, StandardDeviation) and provides a nice printable record as a
* String.
*
* Users can easily extend this class and provide the implementation of
* toString() method to format the stats as desired. By default all the stats
* are printed in a single line.
* </p>
*/
public class StatisticsAccumulator {
///////////////////////////////////////
// attributes
// Users can extend this class to get access to current Max value
protected double max = Double.MIN_VALUE;
// Users can extend this class to get access to current Min value
protected double min = Double.MAX_VALUE;
private double sampleSum;
private double sampleSquareSum;
private long sampleCount;
protected String unit;
///////////////////////////////////////
// operations
/**
* <p>
* User will use this method to just register a sample with the
* StatisticsAccumulator. This is the only method that User will use to
* expose the statistics, internally the StatisticMonitoredAttribute will
* collect the information when requested from the ASAdmin.
* </p>
* <p>
*
* </p>
* <p>
*
* @param value a double value to make it more precise
* </p>
*/
public void sample(double value) {
sampleCount++;
if( value < min ) min = value;
if( value > max) max = value;
sampleSum += value;
sampleSquareSum += (value * value);
} // end sample
/**
* Computes the Standard Statistic Results based on the samples collected
* so far and provides the complete value as a formatted String
*/
public String getValue( ) {
return toString();
}
/**
* Users can extend StatisticsAccumulator to provide the complete
* Stats in the format they prefer, if the default format doesn't suffice.
*/
public String toString( ) {
return "Minimum Value = " + min + " " + unit + " " +
"Maximum Value = " + max + " " + unit + " " +
"Average Value = " + computeAverage() + " " + unit + " " +
"Standard Deviation = " + computeStandardDeviation() + " " + unit +
" " + "Samples Collected = " + sampleCount;
}
/**
* If users choose to custom format the stats.
*/
protected double computeAverage( ) {
return (sampleSum / sampleCount);
}
/**
* We use a derived Standard Deviation formula to compute SD. This way
* there is no need to hold on to all the samples provided.
*
* The method is protected to let users extend and format the results.
*/
protected double computeStandardDeviation( ) {
double sampleSumSquare = sampleSum * sampleSum;
return Math.sqrt(
(sampleSquareSum-((sampleSumSquare)/sampleCount))/(sampleCount-1));
}
/**
* <p>
* Construct the Statistics Accumulator by providing the unit as a String.
* The examples of units are &quot;Hours&quot;, &quot;Minutes&quot;,
* &quot;Seconds&quot;, &quot;MilliSeconds&quot;, &quot;Micro Seconds&quot;
* etc.,
* </p>
* <p>
*
* @return a StatisticsAccumulator with ...
* </p>
* <p>
* @param unit a String representing the units for the samples collected
* </p>
*/
public StatisticsAccumulator( String unit ) {
this.unit = unit;
sampleCount = 0;
sampleSum = 0;
sampleSquareSum = 0;
}
/**
* Clears the samples and starts fresh on new samples.
*/
void clearState( ) {
min = Double.MAX_VALUE;
max = Double.MIN_VALUE;
sampleCount = 0;
sampleSum = 0;
sampleSquareSum = 0;
}
/**
* This is an internal API to test StatisticsAccumulator...
*/
public void unitTestValidate( String expectedUnit, double expectedMin,
double expectedMax, long expectedSampleCount, double expectedAverage,
double expectedStandardDeviation )
{
if( !expectedUnit.equals( unit ) ){
throw new RuntimeException(
"Unit is not same as expected Unit" +
"\nUnit = " + unit + "ExpectedUnit = " + expectedUnit );
}
if( min != expectedMin ) {
throw new RuntimeException(
"Minimum value is not same as expected minimum value" +
"\nMin Value = " + min + "Expected Min Value = " + expectedMin);
}
if( max != expectedMax ) {
throw new RuntimeException(
"Maximum value is not same as expected maximum value" +
"\nMax Value = " + max + "Expected Max Value = " + expectedMax);
}
if( sampleCount != expectedSampleCount ) {
throw new RuntimeException(
"Sample count is not same as expected Sample Count" +
"\nSampleCount = " + sampleCount + "Expected Sample Count = " +
expectedSampleCount);
}
if( computeAverage() != expectedAverage ) {
throw new RuntimeException(
"Average is not same as expected Average" +
"\nAverage = " + computeAverage() + "Expected Average = " +
expectedAverage);
}
// We are computing Standard Deviation from two different methods
// for comparison. So, the values will not be the exact same to the last
// few digits. So, we are taking the difference and making sure that
// the difference is not greater than 1.
double difference = Math.abs(
computeStandardDeviation() - expectedStandardDeviation);
if( difference > 1 ) {
throw new RuntimeException(
"Standard Deviation is not same as expected Std Deviation" +
"\nStandard Dev = " + computeStandardDeviation() +
"Expected Standard Dev = " + expectedStandardDeviation);
}
}
} // end StatisticsAccumulator