2 * ============LICENSE_START===================================================
3 * SPARKY (AAI UI service)
4 * ============================================================================
5 * Copyright © 2017 AT&T Intellectual Property.
6 * Copyright © 2017 Amdocs
8 * ============================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 * ============LICENSE_END=====================================================
22 * ECOMP and OpenECOMP are trademarks
23 * and service marks of AT&T Intellectual Property.
26 package org.openecomp.sparky.analytics;
29 * A class that models a histogram for reporting and tracking long values with variable steps, bins,
30 * and floating point accuracy.
34 public final class HistogramSampler {
38 private long binMaxValue;
42 private double stepSize;
44 private long sampleValueTotal;
46 private long minValue = -1;
48 private long maxValue = 0;
50 private long numSamples = 0;
52 private long decimalPointAccuracy = 0;
54 private static String FORMAT_FLOAT_TEMPLATE = "%%.%df";
56 private String floatFormatStr;
58 private long[] histogramBins;
61 * Instantiates a new histogram sampler.
63 * @param label the label
64 * @param maxValue the max value
65 * @param numBins the num bins
66 * @param decimalPointAccuracy the decimal point accuracy
68 public HistogramSampler(String label, long maxValue, int numBins, int decimalPointAccuracy) {
70 this.binMaxValue = maxValue;
71 this.numBins = numBins;
72 this.stepSize = ((double) binMaxValue / (double) numBins);
73 this.decimalPointAccuracy = decimalPointAccuracy;
74 this.floatFormatStr = String.format(FORMAT_FLOAT_TEMPLATE, this.decimalPointAccuracy);
77 * [numBins + 1] => last bin is catch-all for outliers
80 initializeHistogramBins(numBins + 1);
85 * Initialize histogram bins.
87 * @param numBins the num bins
89 private void initializeHistogramBins(int numBins) {
91 histogramBins = new long[numBins];
93 while (counter < numBins) {
94 histogramBins[counter] = 0;
101 * Is it really necessary to synchronize the collection, or should we simply switch the underlying
102 * data type to an AtomicLong
108 * @param value the value
110 public synchronized void track(long value) {
116 sampleValueTotal += value;
119 if (minValue == -1) {
123 if (value < minValue) {
127 if (value > maxValue) {
132 * One step bin determination
135 if (value < (numBins * stepSize)) {
137 int index = (int) (value / stepSize);
138 histogramBins[index]++;
141 // peg the metric in the outlier bin
142 histogramBins[numBins - 1]++;
150 public void clear() {
153 while (counter < numBins) {
154 histogramBins[counter] = 0;
161 sampleValueTotal = 0;
166 * Re initialize bins.
168 * @param label the label
169 * @param numBins the num bins
170 * @param maxValue the max value
171 * @param decimalPointAccuracy the decimal point accuracy
173 public void reInitializeBins(String label, int numBins, long maxValue, int decimalPointAccuracy) {
175 this.decimalPointAccuracy = decimalPointAccuracy;
176 this.floatFormatStr = String.format(FORMAT_FLOAT_TEMPLATE, this.decimalPointAccuracy);
177 this.numBins = numBins;
180 initializeHistogramBins(numBins);
181 this.stepSize = (maxValue / numBins);
185 public long getNumberOfSamples() {
189 public long getTotalValueSum() {
190 return sampleValueTotal;
196 * @param formatted the formatted
197 * @param indentPadding the indent padding
200 public String getStats(boolean formatted, String indentPadding) {
202 StringBuilder sb = new StringBuilder(128);
206 // generate CSV in the following format
209 * label,minValue,maxValue,avgValue,numSamples,stepSize,numSteps,stepCounters
211 sb.append(indentPadding);
212 sb.append(label).append(",");
213 sb.append(minValue).append(",");
214 sb.append(maxValue).append(",");
215 if (numSamples == 0) {
216 sb.append(0).append(",");
218 sb.append((sampleValueTotal / numSamples)).append(",");
220 sb.append(numSamples).append(",");
221 sb.append(numBins).append(",");
222 sb.append(String.format(floatFormatStr, stepSize));
225 while (counter < numBins) {
227 if (counter != (numBins)) {
231 sb.append(histogramBins[counter]);
237 return sb.toString();
242 sb.append(indentPadding).append("Label = ").append(label).append("\n");
243 sb.append(indentPadding).append("Min = ").append(minValue).append("\n");
244 sb.append(indentPadding).append("Max = ").append(maxValue).append("\n");
245 sb.append(indentPadding).append("numSamples = ").append(numSamples).append("\n");
247 if (numSamples == 0) {
248 sb.append(indentPadding).append("Avg = ").append(0).append("\n");
250 sb.append(indentPadding).append("Avg = ").append((sampleValueTotal / numSamples))
254 sb.append(indentPadding).append("StepSize = ").append(String.format(floatFormatStr, stepSize))
257 sb.append(indentPadding).append("Sample Histogram:").append("\n");
260 while (counter < numBins) {
262 if (counter == (numBins - 1)) {
264 double leftBound = (stepSize * counter);
265 sb.append(indentPadding).append("\t")
266 .append(" x >= " + String.format(floatFormatStr, leftBound) + " : "
267 + histogramBins[counter])
271 double leftBound = (stepSize * counter);
272 double rightBound = ((stepSize) * (counter + 1));
273 sb.append(indentPadding).append("\t")
274 .append((String.format(floatFormatStr, leftBound) + " < x < "
275 + String.format(floatFormatStr, rightBound) + " : " + histogramBins[counter]))
283 return sb.toString();