StatisticsAccumulator.java revision 608:7e06bf1dcb09
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 * <p>
31 *
32 * @author Hemanth Puttaswamy
33 * </p>
34 * <p>
35 * StatisticsAccumulator accumulates the samples provided by the user and
36 * computes the value of minimum, maximum, sum and sample square sum. When
37 * the StatisticMonitoredAttribute calls getValue(), it will compute all
38 * the statistics for the collected samples (Which are Minimum, Maximum,
39 * Average, StandardDeviation) and provides a nice printable record as a
40 * String.
41 *
42 * Users can easily extend this class and provide the implementation of
43 * toString() method to format the stats as desired. By default all the stats
44 * are printed in a single line.
45 * </p>
46 */
47public class StatisticsAccumulator {
48
49  ///////////////////////////////////////
50  // attributes
51
52
53    // Users can extend this class to get access to current Max value
54    protected double max = Double.MIN_VALUE;
55
56    // Users can extend this class to get access to current Min value
57    protected double min = Double.MAX_VALUE;
58
59    private double sampleSum;
60
61    private double sampleSquareSum;
62
63    private long sampleCount;
64
65    protected String unit;
66
67
68
69  ///////////////////////////////////////
70  // operations
71
72
73
74/**
75 * <p>
76 * User will use this method to just register a sample with the
77 * StatisticsAccumulator. This is the only method that User will use to
78 * expose the statistics, internally the StatisticMonitoredAttribute will
79 * collect the information when requested from the ASAdmin.
80 * </p>
81 * <p>
82 *
83 * </p>
84 * <p>
85 *
86 * @param value a double value to make it more precise
87 * </p>
88 */
89    public void sample(double value) {
90        sampleCount++;
91        if( value < min )  min = value;
92        if( value > max) max = value;
93        sampleSum += value;
94        sampleSquareSum += (value * value);
95    } // end sample
96
97
98
99    /**
100     *  Computes the Standard Statistic Results based on the samples collected
101     *  so far and provides the complete value as a formatted String
102     */
103    public String getValue( ) {
104        return toString();
105    }
106
107    /**
108     *  Users can extend StatisticsAccumulator to provide the complete
109     *  Stats in the format they prefer, if the default format doesn't suffice.
110     */
111    public String toString( ) {
112        return "Minimum Value = " + min + " " + unit + " " +
113            "Maximum Value = " + max + " " + unit + " " +
114            "Average Value = " + computeAverage() + " " +  unit + " " +
115            "Standard Deviation = " + computeStandardDeviation() + " " + unit +
116            " " + "Samples Collected = " + sampleCount;
117    }
118
119    /**
120     *  If users choose to custom format the stats.
121     */
122    protected double computeAverage( ) {
123        return (sampleSum / sampleCount);
124    }
125
126
127    /**
128     * We use a derived Standard Deviation formula to compute SD. This way
129     * there is no need to hold on to all the samples provided.
130     *
131     * The method is protected to let users extend and format the results.
132     */
133    protected double computeStandardDeviation( ) {
134        double sampleSumSquare = sampleSum * sampleSum;
135        return Math.sqrt(
136            (sampleSquareSum-((sampleSumSquare)/sampleCount))/(sampleCount-1));
137    }
138
139/**
140 * <p>
141 * Construct the Statistics Accumulator by providing the unit as a String.
142 * The examples of units are &quot;Hours&quot;, &quot;Minutes&quot;,
143 * &quot;Seconds&quot;, &quot;MilliSeconds&quot;, &quot;Micro Seconds&quot;
144 * etc.,
145 * </p>
146 * <p>
147 *
148 * @return a StatisticsAccumulator with ...
149 * </p>
150 * <p>
151 * @param unit a String representing the units for the samples collected
152 * </p>
153 */
154    public StatisticsAccumulator( String unit ) {
155        this.unit = unit;
156        sampleCount = 0;
157        sampleSum = 0;
158        sampleSquareSum = 0;
159    }
160
161
162    /**
163     *  Clears the samples and starts fresh on new samples.
164     */
165    void clearState( ) {
166        min = Double.MAX_VALUE;
167        max = Double.MIN_VALUE;
168        sampleCount = 0;
169        sampleSum = 0;
170        sampleSquareSum = 0;
171    }
172
173    /**
174     *  This is an internal API to test StatisticsAccumulator...
175     */
176    public void unitTestValidate( String expectedUnit, double expectedMin,
177        double expectedMax, long expectedSampleCount, double expectedAverage,
178        double expectedStandardDeviation )
179    {
180        if( !expectedUnit.equals( unit ) ){
181            throw new RuntimeException(
182                "Unit is not same as expected Unit" +
183                "\nUnit = " + unit + "ExpectedUnit = " + expectedUnit );
184        }
185        if( min != expectedMin ) {
186            throw new RuntimeException(
187                "Minimum value is not same as expected minimum value" +
188                "\nMin Value = " + min + "Expected Min Value = " + expectedMin);
189        }
190        if( max != expectedMax ) {
191            throw new RuntimeException(
192                "Maximum value is not same as expected maximum value" +
193                "\nMax Value = " + max + "Expected Max Value = " + expectedMax);
194        }
195        if( sampleCount != expectedSampleCount ) {
196            throw new RuntimeException(
197                "Sample count is not same as expected Sample Count" +
198                "\nSampleCount = " + sampleCount + "Expected Sample Count = " +
199                expectedSampleCount);
200        }
201        if( computeAverage() != expectedAverage ) {
202            throw new RuntimeException(
203                "Average is not same as expected Average" +
204                "\nAverage = " + computeAverage() + "Expected Average = " +
205                expectedAverage);
206        }
207        // We are computing Standard Deviation from two different methods
208        // for comparison. So, the values will not be the exact same to the last
209        // few digits. So, we are taking the difference and making sure that
210        // the difference is not greater than 1.
211        double difference = Math.abs(
212            computeStandardDeviation() - expectedStandardDeviation);
213        if( difference > 1 ) {
214            throw new RuntimeException(
215                "Standard Deviation is not same as expected Std Deviation" +
216                "\nStandard Dev = " + computeStandardDeviation() +
217                "Expected Standard Dev = " + expectedStandardDeviation);
218        }
219    }
220
221
222} // end StatisticsAccumulator
223