1. /*
  2. * @(#)StatisticsAccumulator.java 1.3 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.corba.se.spi.monitoring;
  8. import java.util.*;
  9. /**
  10. * <p>
  11. *
  12. * @author Hemanth Puttaswamy
  13. * </p>
  14. * <p>
  15. * StatisticsAccumulator accumulates the samples provided by the user and
  16. * computes the value of minimum, maximum, sum and sample square sum. When
  17. * the StatisticMonitoredAttribute calls getValue(), it will compute all
  18. * the statistics for the collected samples (Which are Minimum, Maximum,
  19. * Average, StandardDeviation) and provides a nice printable record as a
  20. * String.
  21. *
  22. * Users can easily extend this class and provide the implementation of
  23. * toString() method to format the stats as desired. By default all the stats
  24. * are printed in a single line.
  25. * </p>
  26. */
  27. public class StatisticsAccumulator {
  28. ///////////////////////////////////////
  29. // attributes
  30. // Users can extend this class to get access to current Max value
  31. protected double max = Double.MIN_VALUE;
  32. // Users can extend this class to get access to current Min value
  33. protected double min = Double.MAX_VALUE;
  34. private double sampleSum;
  35. private double sampleSquareSum;
  36. private long sampleCount;
  37. protected String unit;
  38. ///////////////////////////////////////
  39. // operations
  40. /**
  41. * <p>
  42. * User will use this method to just register a sample with the
  43. * StatisticsAccumulator. This is the only method that User will use to
  44. * expose the statistics, internally the StatisticMonitoredAttribute will
  45. * collect the information when requested from the ASAdmin.
  46. * </p>
  47. * <p>
  48. *
  49. * </p>
  50. * <p>
  51. *
  52. * @param value a double value to make it more precise
  53. * </p>
  54. */
  55. public void sample(double value) {
  56. sampleCount++;
  57. if( value < min ) min = value;
  58. if( value > max) max = value;
  59. sampleSum += value;
  60. sampleSquareSum += (value * value);
  61. } // end sample
  62. /**
  63. * Computes the Standard Statistic Results based on the samples collected
  64. * so far and provides the complete value as a formatted String
  65. */
  66. public String getValue( ) {
  67. return toString();
  68. }
  69. /**
  70. * Users can extend StatisticsAccumulator to provide the complete
  71. * Stats in the format they prefer, if the default format doesn't suffice.
  72. */
  73. public String toString( ) {
  74. return "Minimum Value = " + min + " " + unit + " " +
  75. "Maximum Value = " + max + " " + unit + " " +
  76. "Average Value = " + computeAverage() + " " + unit + " " +
  77. "Standard Deviation = " + computeStandardDeviation() + " " + unit +
  78. " " + "Samples Collected = " + sampleCount;
  79. }
  80. /**
  81. * If users choose to custom format the stats.
  82. */
  83. protected double computeAverage( ) {
  84. return (sampleSum / sampleCount);
  85. }
  86. /**
  87. * We use a derived Standard Deviation formula to compute SD. This way
  88. * there is no need to hold on to all the samples provided.
  89. *
  90. * The method is protected to let users extend and format the results.
  91. */
  92. protected double computeStandardDeviation( ) {
  93. double sampleSumSquare = sampleSum * sampleSum;
  94. return Math.sqrt(
  95. (sampleSquareSum-((sampleSumSquare)/sampleCount))/(sampleCount-1));
  96. }
  97. /**
  98. * <p>
  99. * Construct the Statistics Accumulator by providing the unit as a String.
  100. * The examples of units are "Hours", "Minutes",
  101. * "Seconds", "MilliSeconds", "Micro Seconds"
  102. * etc.,
  103. * </p>
  104. * <p>
  105. *
  106. * @return a StatisticsAccumulator with ...
  107. * </p>
  108. * <p>
  109. * @param unit a String representing the units for the samples collected
  110. * </p>
  111. */
  112. public StatisticsAccumulator( String unit ) {
  113. this.unit = unit;
  114. sampleCount = 0;
  115. sampleSum = 0;
  116. sampleSquareSum = 0;
  117. }
  118. /**
  119. * Clears the samples and starts fresh on new samples.
  120. */
  121. void clearState( ) {
  122. min = Double.MAX_VALUE;
  123. max = Double.MIN_VALUE;
  124. sampleCount = 0;
  125. sampleSum = 0;
  126. sampleSquareSum = 0;
  127. }
  128. /**
  129. * This is an internal API to test StatisticsAccumulator...
  130. */
  131. public void unitTestValidate( String expectedUnit, double expectedMin,
  132. double expectedMax, long expectedSampleCount, double expectedAverage,
  133. double expectedStandardDeviation )
  134. {
  135. if( !expectedUnit.equals( unit ) ){
  136. throw new RuntimeException(
  137. "Unit is not same as expected Unit" +
  138. "\nUnit = " + unit + "ExpectedUnit = " + expectedUnit );
  139. }
  140. if( min != expectedMin ) {
  141. throw new RuntimeException(
  142. "Minimum value is not same as expected minimum value" +
  143. "\nMin Value = " + min + "Expected Min Value = " + expectedMin);
  144. }
  145. if( max != expectedMax ) {
  146. throw new RuntimeException(
  147. "Maximum value is not same as expected maximum value" +
  148. "\nMax Value = " + max + "Expected Max Value = " + expectedMax);
  149. }
  150. if( sampleCount != expectedSampleCount ) {
  151. throw new RuntimeException(
  152. "Sample count is not same as expected Sample Count" +
  153. "\nSampleCount = " + sampleCount + "Expected Sample Count = " +
  154. expectedSampleCount);
  155. }
  156. if( computeAverage() != expectedAverage ) {
  157. throw new RuntimeException(
  158. "Average is not same as expected Average" +
  159. "\nAverage = " + computeAverage() + "Expected Average = " +
  160. expectedAverage);
  161. }
  162. // We are computing Standard Deviation from two different methods
  163. // for comparison. So, the values will not be the exact same to the last
  164. // few digits. So, we are taking the difference and making sure that
  165. // the difference is not greater than 1.
  166. double difference = Math.abs(
  167. computeStandardDeviation() - expectedStandardDeviation);
  168. if( difference > 1 ) {
  169. throw new RuntimeException(
  170. "Standard Deviation is not same as expected Std Deviation" +
  171. "\nStandard Dev = " + computeStandardDeviation() +
  172. "Expected Standard Dev = " + expectedStandardDeviation);
  173. }
  174. }
  175. } // end StatisticsAccumulator