/* * 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 "Hours", "Minutes", * "Seconds", "MilliSeconds", "Micro Seconds" * 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