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.
25 package org.onap.aai.sparky.analytics;
28 * A class that models a histogram for reporting and tracking long values with variable steps, bins,
29 * and floating point accuracy.
33 public final class HistogramSampler {
37 private long binMaxValue;
41 private double stepSize;
43 private long sampleValueTotal;
45 private long minValue = -1;
47 private long maxValue = 0;
49 private long numSamples = 0;
51 private long decimalPointAccuracy = 0;
53 private static String FORMAT_FLOAT_TEMPLATE = "%%.%df";
55 private String floatFormatStr;
57 private long[] histogramBins;
60 * Instantiates a new histogram sampler.
62 * @param label the label
63 * @param maxValue the max value
64 * @param numBins the num bins
65 * @param decimalPointAccuracy the decimal point accuracy
67 public HistogramSampler(String label, long maxValue, int numBins, int decimalPointAccuracy) {
69 this.binMaxValue = maxValue;
70 this.numBins = numBins;
71 this.stepSize = ((double) binMaxValue / (double) numBins);
72 this.decimalPointAccuracy = decimalPointAccuracy;
73 this.floatFormatStr = String.format(FORMAT_FLOAT_TEMPLATE, this.decimalPointAccuracy);
76 * [numBins + 1] => last bin is catch-all for outliers
79 initializeHistogramBins(numBins + 1);
84 * Initialize histogram bins.
86 * @param numBins the num bins
88 private void initializeHistogramBins(int numBins) {
90 histogramBins = new long[numBins];
92 while (counter < numBins) {
93 histogramBins[counter] = 0;
100 * Is it really necessary to synchronize the collection, or should we simply switch the underlying
101 * data type to an AtomicLong
107 * @param value the value
109 public synchronized void track(long value) {
115 sampleValueTotal += value;
118 if (minValue == -1) {
122 if (value < minValue) {
126 if (value > maxValue) {
131 * One step bin determination
134 if (value < (numBins * stepSize)) {
136 int index = (int) (value / stepSize);
137 histogramBins[index]++;
140 // peg the metric in the outlier bin
141 histogramBins[numBins - 1]++;
149 public void clear() {
152 while (counter < numBins) {
153 histogramBins[counter] = 0;
160 sampleValueTotal = 0;
165 * Re initialize bins.
167 * @param label the label
168 * @param numBins the num bins
169 * @param maxValue the max value
170 * @param decimalPointAccuracy the decimal point accuracy
172 public void reInitializeBins(String label, int numBins, long maxValue, int decimalPointAccuracy) {
174 this.decimalPointAccuracy = decimalPointAccuracy;
175 this.floatFormatStr = String.format(FORMAT_FLOAT_TEMPLATE, this.decimalPointAccuracy);
176 this.numBins = numBins;
179 initializeHistogramBins(numBins);
180 this.stepSize = (maxValue / numBins);
184 public long getNumberOfSamples() {
188 public long getTotalValueSum() {
189 return sampleValueTotal;
195 * @param formatted the formatted
196 * @param indentPadding the indent padding
199 public String getStats(boolean formatted, String indentPadding) {
201 StringBuilder sb = new StringBuilder(128);
205 // generate CSV in the following format
208 * label,minValue,maxValue,avgValue,numSamples,stepSize,numSteps,stepCounters
210 sb.append(indentPadding);
211 sb.append(label).append(",");
212 sb.append(minValue).append(",");
213 sb.append(maxValue).append(",");
214 if (numSamples == 0) {
215 sb.append(0).append(",");
217 sb.append((sampleValueTotal / numSamples)).append(",");
219 sb.append(numSamples).append(",");
220 sb.append(numBins).append(",");
221 sb.append(String.format(floatFormatStr, stepSize));
224 while (counter < numBins) {
226 if (counter != (numBins)) {
230 sb.append(histogramBins[counter]);
236 return sb.toString();
241 sb.append(indentPadding).append("Label = ").append(label).append("\n");
242 sb.append(indentPadding).append("Min = ").append(minValue).append("\n");
243 sb.append(indentPadding).append("Max = ").append(maxValue).append("\n");
244 sb.append(indentPadding).append("numSamples = ").append(numSamples).append("\n");
246 if (numSamples == 0) {
247 sb.append(indentPadding).append("Avg = ").append(0).append("\n");
249 sb.append(indentPadding).append("Avg = ").append((sampleValueTotal / numSamples))
253 sb.append(indentPadding).append("StepSize = ").append(String.format(floatFormatStr, stepSize))
256 sb.append(indentPadding).append("Sample Histogram:").append("\n");
259 while (counter < numBins) {
261 if (counter == (numBins - 1)) {
263 double leftBound = (stepSize * counter);
264 sb.append(indentPadding).append("\t")
265 .append(" x >= " + String.format(floatFormatStr, leftBound) + " : "
266 + histogramBins[counter])
270 double leftBound = (stepSize * counter);
271 double rightBound = ((stepSize) * (counter + 1));
272 sb.append(indentPadding).append("\t")
273 .append((String.format(floatFormatStr, leftBound) + " < x < "
274 + String.format(floatFormatStr, rightBound) + " : " + histogramBins[counter]))
282 return sb.toString();