diff options
Diffstat (limited to 'api/src/main/java/io/opencensus/metrics/export/Distribution.java')
-rw-r--r-- | api/src/main/java/io/opencensus/metrics/export/Distribution.java | 345 |
1 files changed, 345 insertions, 0 deletions
diff --git a/api/src/main/java/io/opencensus/metrics/export/Distribution.java b/api/src/main/java/io/opencensus/metrics/export/Distribution.java new file mode 100644 index 00000000..d55f101c --- /dev/null +++ b/api/src/main/java/io/opencensus/metrics/export/Distribution.java @@ -0,0 +1,345 @@ +/* + * Copyright 2018, OpenCensus Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.opencensus.metrics.export; + +import com.google.auto.value.AutoValue; +import io.opencensus.common.ExperimentalApi; +import io.opencensus.common.Function; +import io.opencensus.common.Timestamp; +import io.opencensus.internal.Utils; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +/** + * {@link Distribution} contains summary statistics for a population of values. It optionally + * contains a histogram representing the distribution of those values across a set of buckets. + * + * @since 0.17 + */ +@ExperimentalApi +@AutoValue +@Immutable +public abstract class Distribution { + + Distribution() {} + + /** + * Creates a {@link Distribution}. + * + * @param count the count of the population values. + * @param sum the sum of the population values. + * @param sumOfSquaredDeviations the sum of squared deviations of the population values. + * @param bucketOptions the bucket options used to create a histogram for the distribution. + * @param buckets {@link Bucket}s of a histogram. + * @return a {@code Distribution}. + * @since 0.17 + */ + public static Distribution create( + long count, + double sum, + double sumOfSquaredDeviations, + BucketOptions bucketOptions, + List<Bucket> buckets) { + Utils.checkArgument(count >= 0, "count should be non-negative."); + Utils.checkArgument( + sumOfSquaredDeviations >= 0, "sum of squared deviations should be non-negative."); + if (count == 0) { + Utils.checkArgument(sum == 0, "sum should be 0 if count is 0."); + Utils.checkArgument( + sumOfSquaredDeviations == 0, "sum of squared deviations should be 0 if count is 0."); + } + Utils.checkNotNull(bucketOptions, "bucketOptions"); + List<Bucket> bucketsCopy = + Collections.unmodifiableList(new ArrayList<Bucket>(Utils.checkNotNull(buckets, "buckets"))); + Utils.checkListElementNotNull(bucketsCopy, "bucket"); + return new AutoValue_Distribution( + count, sum, sumOfSquaredDeviations, bucketOptions, bucketsCopy); + } + + /** + * Returns the aggregated count. + * + * @return the aggregated count. + * @since 0.17 + */ + public abstract long getCount(); + + /** + * Returns the aggregated sum. + * + * @return the aggregated sum. + * @since 0.17 + */ + public abstract double getSum(); + + /** + * Returns the aggregated sum of squared deviations. + * + * <p>The sum of squared deviations from the mean of the values in the population. For values x_i + * this is: + * + * <p>Sum[i=1..n]((x_i - mean)^2) + * + * <p>If count is zero then this field must be zero. + * + * @return the aggregated sum of squared deviations. + * @since 0.17 + */ + public abstract double getSumOfSquaredDeviations(); + + /** + * Returns bucket options used to create a histogram for the distribution. + * + * @return the {@code BucketOptions} associated with the {@code Distribution}, or {@code null} if + * there isn't one. + * @since 0.17 + */ + @Nullable + public abstract BucketOptions getBucketOptions(); + + /** + * Returns the aggregated histogram {@link Bucket}s. + * + * @return the aggregated histogram buckets. + * @since 0.17 + */ + public abstract List<Bucket> getBuckets(); + + /** + * The bucket options used to create a histogram for the distribution. + * + * @since 0.17 + */ + @Immutable + public abstract static class BucketOptions { + + private BucketOptions() {} + + /** + * Returns a {@link ExplicitOptions}. + * + * <p>The bucket boundaries for that histogram are described by bucket_bounds. This defines + * size(bucket_bounds) + 1 (= N) buckets. The boundaries for bucket index i are: + * + * <ul> + * <li>{@code [0, bucket_bounds[i]) for i == 0} + * <li>{@code [bucket_bounds[i-1], bucket_bounds[i]) for 0 < i < N-1} + * <li>{@code [bucket_bounds[i-1], +infinity) for i == N-1} + * </ul> + * + * <p>If bucket_bounds has no elements (zero size), then there is no histogram associated with + * the Distribution. If bucket_bounds has only one element, there are no finite buckets, and + * that single element is the common boundary of the overflow and underflow buckets. The values + * must be monotonically increasing. + * + * @param bucketBoundaries the bucket boundaries of a distribution (given explicitly). The + * values must be strictly increasing and should be positive values. + * @return a {@code ExplicitOptions} {@code BucketOptions}. + * @since 0.17 + */ + public static BucketOptions explicitOptions(List<Double> bucketBoundaries) { + return ExplicitOptions.create(bucketBoundaries); + } + + /** + * Applies the given match function to the underlying BucketOptions. + * + * @param explicitFunction the function that should be applied if the BucketOptions has type + * {@code ExplicitOptions}. + * @param defaultFunction the function that should be applied if the BucketOptions has a type + * that was added after this {@code match} method was added to the API. See {@link + * io.opencensus.common.Functions} for some common functions for handling unknown types. + * @return the result of the function applied to the underlying BucketOptions. + * @since 0.17 + */ + public abstract <T> T match( + Function<? super ExplicitOptions, T> explicitFunction, + Function<? super BucketOptions, T> defaultFunction); + + /** A Bucket with explicit bounds {@link BucketOptions}. */ + @AutoValue + @Immutable + public abstract static class ExplicitOptions extends BucketOptions { + + ExplicitOptions() {} + + @Override + public final <T> T match( + Function<? super ExplicitOptions, T> explicitFunction, + Function<? super BucketOptions, T> defaultFunction) { + return explicitFunction.apply(this); + } + + /** + * Creates a {@link ExplicitOptions}. + * + * @param bucketBoundaries the bucket boundaries of a distribution (given explicitly). The + * values must be strictly increasing and should be positive. + * @return a {@code ExplicitOptions}. + * @since 0.17 + */ + private static ExplicitOptions create(List<Double> bucketBoundaries) { + Utils.checkNotNull(bucketBoundaries, "bucketBoundaries"); + List<Double> bucketBoundariesCopy = + Collections.unmodifiableList(new ArrayList<Double>(bucketBoundaries)); + checkBucketBoundsAreSorted(bucketBoundariesCopy); + return new AutoValue_Distribution_BucketOptions_ExplicitOptions(bucketBoundariesCopy); + } + + private static void checkBucketBoundsAreSorted(List<Double> bucketBoundaries) { + if (bucketBoundaries.size() >= 1) { + double previous = Utils.checkNotNull(bucketBoundaries.get(0), "bucketBoundary"); + Utils.checkArgument(previous > 0, "bucket boundary should be > 0"); + for (int i = 1; i < bucketBoundaries.size(); i++) { + double next = Utils.checkNotNull(bucketBoundaries.get(i), "bucketBoundary"); + Utils.checkArgument(previous < next, "bucket boundaries not sorted."); + previous = next; + } + } + } + + /** + * Returns the bucket boundaries of this distribution. + * + * @return the bucket boundaries of this distribution. + * @since 0.17 + */ + public abstract List<Double> getBucketBoundaries(); + } + } + + /** + * The histogram bucket of the population values. + * + * @since 0.17 + */ + @AutoValue + @Immutable + public abstract static class Bucket { + + Bucket() {} + + /** + * Creates a {@link Bucket}. + * + * @param count the number of values in each bucket of the histogram. + * @return a {@code Bucket}. + * @since 0.17 + */ + public static Bucket create(long count) { + Utils.checkArgument(count >= 0, "bucket count should be non-negative."); + return new AutoValue_Distribution_Bucket(count, null); + } + + /** + * Creates a {@link Bucket} with an {@link Exemplar}. + * + * @param count the number of values in each bucket of the histogram. + * @param exemplar the {@code Exemplar} of this {@code Bucket}. + * @return a {@code Bucket}. + * @since 0.17 + */ + public static Bucket create(long count, Exemplar exemplar) { + Utils.checkArgument(count >= 0, "bucket count should be non-negative."); + Utils.checkNotNull(exemplar, "exemplar"); + return new AutoValue_Distribution_Bucket(count, exemplar); + } + + /** + * Returns the number of values in each bucket of the histogram. + * + * @return the number of values in each bucket of the histogram. + * @since 0.17 + */ + public abstract long getCount(); + + /** + * Returns the {@link Exemplar} associated with the {@link Bucket}, or {@code null} if there + * isn't one. + * + * @return the {@code Exemplar} associated with the {@code Bucket}, or {@code null} if there + * isn't one. + * @since 0.17 + */ + @Nullable + public abstract Exemplar getExemplar(); + } + + /** + * An example point that may be used to annotate aggregated distribution values, associated with a + * histogram bucket. + * + * @since 0.17 + */ + @Immutable + @AutoValue + public abstract static class Exemplar { + + Exemplar() {} + + /** + * Returns value of the {@link Exemplar} point. + * + * @return value of the {@code Exemplar} point. + * @since 0.17 + */ + public abstract double getValue(); + + /** + * Returns the time that this {@link Exemplar}'s value was recorded. + * + * @return the time that this {@code Exemplar}'s value was recorded. + * @since 0.17 + */ + public abstract Timestamp getTimestamp(); + + /** + * Returns the contextual information about the example value, represented as a string map. + * + * @return the contextual information about the example value. + * @since 0.17 + */ + public abstract Map<String, String> getAttachments(); + + /** + * Creates an {@link Exemplar}. + * + * @param value value of the {@link Exemplar} point. + * @param timestamp the time that this {@code Exemplar}'s value was recorded. + * @param attachments the contextual information about the example value. + * @return an {@code Exemplar}. + * @since 0.17 + */ + public static Exemplar create( + double value, Timestamp timestamp, Map<String, String> attachments) { + Utils.checkNotNull(attachments, "attachments"); + Map<String, String> attachmentsCopy = + Collections.unmodifiableMap(new HashMap<String, String>(attachments)); + for (Entry<String, String> entry : attachmentsCopy.entrySet()) { + Utils.checkNotNull(entry.getKey(), "key of attachments"); + Utils.checkNotNull(entry.getValue(), "value of attachments"); + } + return new AutoValue_Distribution_Exemplar(value, timestamp, attachmentsCopy); + } + } +} |