• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017, OpenCensus Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.opencensus.stats;
18 
19 import com.google.auto.value.AutoValue;
20 import io.opencensus.internal.Utils;
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.List;
24 import java.util.logging.Level;
25 import java.util.logging.Logger;
26 import javax.annotation.concurrent.Immutable;
27 
28 /**
29  * The bucket boundaries for a histogram.
30  *
31  * @since 0.8
32  */
33 @Immutable
34 @AutoValue
35 public abstract class BucketBoundaries {
36 
37   private static final Logger logger = Logger.getLogger(BucketBoundaries.class.getName());
38 
39   /**
40    * Returns a {@code BucketBoundaries} with the given buckets.
41    *
42    * @param bucketBoundaries the boundaries for the buckets in the underlying histogram.
43    * @return a new {@code BucketBoundaries} with the specified boundaries.
44    * @throws NullPointerException if {@code bucketBoundaries} is null.
45    * @throws IllegalArgumentException if {@code bucketBoundaries} is not sorted.
46    * @since 0.8
47    */
create(List<Double> bucketBoundaries)48   public static final BucketBoundaries create(List<Double> bucketBoundaries) {
49     Utils.checkNotNull(bucketBoundaries, "bucketBoundaries");
50     List<Double> bucketBoundariesCopy = new ArrayList<Double>(bucketBoundaries); // Deep copy.
51     // Check if sorted.
52     if (bucketBoundariesCopy.size() > 1) {
53       double previous = bucketBoundariesCopy.get(0);
54       for (int i = 1; i < bucketBoundariesCopy.size(); i++) {
55         double next = bucketBoundariesCopy.get(i);
56         Utils.checkArgument(previous < next, "Bucket boundaries not sorted.");
57         previous = next;
58       }
59     }
60     return new AutoValue_BucketBoundaries(
61         Collections.unmodifiableList(dropNegativeBucketBounds(bucketBoundariesCopy)));
62   }
63 
64   private static List<Double> dropNegativeBucketBounds(List<Double> bucketBoundaries) {
65     // Negative values (BucketBounds) are currently not supported by any of the backends
66     // that OC supports.
67     int negativeBucketBounds = 0;
68     int zeroBucketBounds = 0;
69     for (Double value : bucketBoundaries) {
70       if (value <= 0) {
71         if (value == 0) {
72           zeroBucketBounds++;
73         } else {
74           negativeBucketBounds++;
75         }
76       } else {
77         break;
78       }
79     }
80 
81     if (negativeBucketBounds > 0) {
82       logger.log(
83           Level.WARNING,
84           "Dropping "
85               + negativeBucketBounds
86               + " negative bucket boundaries, the values must be strictly > 0.");
87     }
88     return bucketBoundaries.subList(
89         negativeBucketBounds + zeroBucketBounds, bucketBoundaries.size());
90   }
91 
92   /**
93    * Returns a list of histogram bucket boundaries.
94    *
95    * @return a list of histogram bucket boundaries.
96    * @since 0.8
97    */
98   public abstract List<Double> getBoundaries();
99 }
100