StatisticsAccumulator.java revision 672:2bb058ce572e
1/*
2 * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25package com.sun.corba.se.spi.monitoring;
26
27import java.util.*;
28
29/**
30 * @author Hemanth Puttaswamy
31 *
32 * StatisticsAccumulator accumulates the samples provided by the user and
33 * computes the value of minimum, maximum, sum and sample square sum. When
34 * the StatisticMonitoredAttribute calls getValue(), it will compute all
35 * the statistics for the collected samples (Which are Minimum, Maximum,
36 * Average, StandardDeviation) and provides a nice printable record as a
37 * String.
38 *
39 * Users can easily extend this class and provide the implementation of
40 * toString() method to format the stats as desired. By default all the stats
41 * are printed in a single line.
42 */
43public class StatisticsAccumulator {
44
45  ///////////////////////////////////////
46  // attributes
47
48
49    // Users can extend this class to get access to current Max value
50    protected double max = Double.MIN_VALUE;
51
52    // Users can extend this class to get access to current Min value
53    protected double min = Double.MAX_VALUE;
54
55    private double sampleSum;
56
57    private double sampleSquareSum;
58
59    private long sampleCount;
60
61    protected String unit;
62
63
64
65  ///////////////////////////////////////
66  // operations
67
68
69
70/**
71 * User will use this method to just register a sample with the
72 * StatisticsAccumulator. This is the only method that User will use to
73 * expose the statistics, internally the StatisticMonitoredAttribute will
74 * collect the information when requested from the ASAdmin.
75 *
76 * @param value a double value to make it more precise
77 */
78    public void sample(double value) {
79        sampleCount++;
80        if( value < min )  min = value;
81        if( value > max) max = value;
82        sampleSum += value;
83        sampleSquareSum += (value * value);
84    } // end sample
85
86
87
88    /**
89     *  Computes the Standard Statistic Results based on the samples collected
90     *  so far and provides the complete value as a formatted String
91     */
92    public String getValue( ) {
93        return toString();
94    }
95
96    /**
97     *  Users can extend StatisticsAccumulator to provide the complete
98     *  Stats in the format they prefer, if the default format doesn't suffice.
99     */
100    public String toString( ) {
101        return "Minimum Value = " + min + " " + unit + " " +
102            "Maximum Value = " + max + " " + unit + " " +
103            "Average Value = " + computeAverage() + " " +  unit + " " +
104            "Standard Deviation = " + computeStandardDeviation() + " " + unit +
105            " " + "Samples Collected = " + sampleCount;
106    }
107
108    /**
109     *  If users choose to custom format the stats.
110     */
111    protected double computeAverage( ) {
112        return (sampleSum / sampleCount);
113    }
114
115
116    /**
117     * We use a derived Standard Deviation formula to compute SD. This way
118     * there is no need to hold on to all the samples provided.
119     *
120     * The method is protected to let users extend and format the results.
121     */
122    protected double computeStandardDeviation( ) {
123        double sampleSumSquare = sampleSum * sampleSum;
124        return Math.sqrt(
125            (sampleSquareSum-((sampleSumSquare)/sampleCount))/(sampleCount-1));
126    }
127
128/**
129 * Construct the Statistics Accumulator by providing the unit as a String.
130 * The examples of units are "Hours", "Minutes",
131 * "Seconds", "MilliSeconds", "Micro Seconds" etc.
132 *
133 * @param unit a String representing the units for the samples collected
134 */
135    public StatisticsAccumulator( String unit ) {
136        this.unit = unit;
137        sampleCount = 0;
138        sampleSum = 0;
139        sampleSquareSum = 0;
140    }
141
142
143    /**
144     *  Clears the samples and starts fresh on new samples.
145     */
146    void clearState( ) {
147        min = Double.MAX_VALUE;
148        max = Double.MIN_VALUE;
149        sampleCount = 0;
150        sampleSum = 0;
151        sampleSquareSum = 0;
152    }
153
154    /**
155     *  This is an internal API to test StatisticsAccumulator...
156     */
157    public void unitTestValidate( String expectedUnit, double expectedMin,
158        double expectedMax, long expectedSampleCount, double expectedAverage,
159        double expectedStandardDeviation )
160    {
161        if( !expectedUnit.equals( unit ) ){
162            throw new RuntimeException(
163                "Unit is not same as expected Unit" +
164                "\nUnit = " + unit + "ExpectedUnit = " + expectedUnit );
165        }
166        if( min != expectedMin ) {
167            throw new RuntimeException(
168                "Minimum value is not same as expected minimum value" +
169                "\nMin Value = " + min + "Expected Min Value = " + expectedMin);
170        }
171        if( max != expectedMax ) {
172            throw new RuntimeException(
173                "Maximum value is not same as expected maximum value" +
174                "\nMax Value = " + max + "Expected Max Value = " + expectedMax);
175        }
176        if( sampleCount != expectedSampleCount ) {
177            throw new RuntimeException(
178                "Sample count is not same as expected Sample Count" +
179                "\nSampleCount = " + sampleCount + "Expected Sample Count = " +
180                expectedSampleCount);
181        }
182        if( computeAverage() != expectedAverage ) {
183            throw new RuntimeException(
184                "Average is not same as expected Average" +
185                "\nAverage = " + computeAverage() + "Expected Average = " +
186                expectedAverage);
187        }
188        // We are computing Standard Deviation from two different methods
189        // for comparison. So, the values will not be the exact same to the last
190        // few digits. So, we are taking the difference and making sure that
191        // the difference is not greater than 1.
192        double difference = Math.abs(
193            computeStandardDeviation() - expectedStandardDeviation);
194        if( difference > 1 ) {
195            throw new RuntimeException(
196                "Standard Deviation is not same as expected Std Deviation" +
197                "\nStandard Dev = " + computeStandardDeviation() +
198                "Expected Standard Dev = " + expectedStandardDeviation);
199        }
200    }
201
202
203} // end StatisticsAccumulator
204