2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * Copyright © 2017-2018 Amdocs
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
21 package org.onap.aai.sparky.analytics;
24 * A class that models a histogram for reporting and tracking long values with variable steps, bins,
25 * and floating point accuracy.
29 public final class HistogramSampler {
33 private long binMaxValue;
37 private double stepSize;
39 private long sampleValueTotal;
41 private long minValue = -1;
43 private long maxValue = 0;
45 private long numSamples = 0;
47 private long decimalPointAccuracy = 0;
49 private static String FORMAT_FLOAT_TEMPLATE = "%%.%df";
51 private String floatFormatStr;
53 private long[] histogramBins;
56 * Instantiates a new histogram sampler.
58 * @param label the label
59 * @param maxValue the max value
60 * @param numBins the num bins
61 * @param decimalPointAccuracy the decimal point accuracy
63 public HistogramSampler(String label, long maxValue, int numBins, int decimalPointAccuracy) {
65 this.binMaxValue = maxValue;
66 this.numBins = numBins;
67 this.stepSize = ((double) binMaxValue / (double) numBins);
68 this.decimalPointAccuracy = decimalPointAccuracy;
69 this.floatFormatStr = String.format(FORMAT_FLOAT_TEMPLATE, this.decimalPointAccuracy);
72 * [numBins + 1] => last bin is catch-all for outliers
75 initializeHistogramBins(numBins + 1);
80 * Initialize histogram bins.
82 * @param numBins the num bins
84 private void initializeHistogramBins(int numBins) {
86 histogramBins = new long[numBins];
88 while (counter < numBins) {
89 histogramBins[counter] = 0;
96 * Is it really necessary to synchronize the collection, or should we simply switch the underlying
97 * data type to an AtomicLong
103 * @param value the value
105 public synchronized void track(long value) {
111 sampleValueTotal += value;
114 if (minValue == -1) {
118 if (value < minValue) {
122 if (value > maxValue) {
127 * One step bin determination
130 if (value < (numBins * stepSize)) {
132 int index = (int) (value / stepSize);
133 histogramBins[index]++;
136 // peg the metric in the outlier bin
137 histogramBins[numBins - 1]++;
145 public void clear() {
148 while (counter < numBins) {
149 histogramBins[counter] = 0;
156 sampleValueTotal = 0;
161 * Re initialize bins.
163 * @param label the label
164 * @param numBins the num bins
165 * @param maxValue the max value
166 * @param decimalPointAccuracy the decimal point accuracy
168 public void reInitializeBins(String label, int numBins, long maxValue, int decimalPointAccuracy) {
170 this.decimalPointAccuracy = decimalPointAccuracy;
171 this.floatFormatStr = String.format(FORMAT_FLOAT_TEMPLATE, this.decimalPointAccuracy);
172 this.numBins = numBins;
175 initializeHistogramBins(numBins);
176 this.stepSize = (maxValue / numBins);
180 public long getNumberOfSamples() {
184 public long getTotalValueSum() {
185 return sampleValueTotal;
191 * @param formatted the formatted
192 * @param indentPadding the indent padding
195 public String getStats(boolean formatted, String indentPadding) {
197 StringBuilder sb = new StringBuilder(128);
201 // generate CSV in the following format
204 * label,minValue,maxValue,avgValue,numSamples,stepSize,numSteps,stepCounters
206 sb.append(indentPadding);
207 sb.append(label).append(",");
208 sb.append(minValue).append(",");
209 sb.append(maxValue).append(",");
210 if (numSamples == 0) {
211 sb.append(0).append(",");
213 sb.append((sampleValueTotal / numSamples)).append(",");
215 sb.append(numSamples).append(",");
216 sb.append(numBins).append(",");
217 sb.append(String.format(floatFormatStr, stepSize));
220 while (counter < numBins) {
222 if (counter != (numBins)) {
226 sb.append(histogramBins[counter]);
232 return sb.toString();
237 sb.append(indentPadding).append("Label = ").append(label).append("\n");
238 sb.append(indentPadding).append("Min = ").append(minValue).append("\n");
239 sb.append(indentPadding).append("Max = ").append(maxValue).append("\n");
240 sb.append(indentPadding).append("numSamples = ").append(numSamples).append("\n");
242 if (numSamples == 0) {
243 sb.append(indentPadding).append("Avg = ").append(0).append("\n");
245 sb.append(indentPadding).append("Avg = ").append((sampleValueTotal / numSamples))
249 sb.append(indentPadding).append("StepSize = ").append(String.format(floatFormatStr, stepSize))
252 sb.append(indentPadding).append("Sample Histogram:").append("\n");
255 while (counter < numBins) {
257 if (counter == (numBins - 1)) {
259 double leftBound = (stepSize * counter);
260 sb.append(indentPadding).append("\t")
261 .append(" x >= " + String.format(floatFormatStr, leftBound) + " : "
262 + histogramBins[counter])
266 double leftBound = (stepSize * counter);
267 double rightBound = ((stepSize) * (counter + 1));
268 sb.append(indentPadding).append("\t")
269 .append((String.format(floatFormatStr, leftBound) + " < x < "
270 + String.format(floatFormatStr, rightBound) + " : " + histogramBins[counter]))
278 return sb.toString();