aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBogdan Drutu <bdrutu@google.com>2018-10-02 16:44:12 -0400
committerGitHub <noreply@github.com>2018-10-02 16:44:12 -0400
commitbcfd159c58e80036bbbe1468bf305154d001982e (patch)
tree274154a86904f767aa38eeb28b5a4870e89a47cc
parent84630fb6ae3474039cec4977c989b1a30e695906 (diff)
downloadopencensus-java-bcfd159c58e80036bbbe1468bf305154d001982e.tar.gz
Make metrics compatible with the current proto definition. (#1479)
* Make metrics compatible with the current proto definition. * Fix minor comments from the review. * Fix @Nullable.
-rw-r--r--api/src/main/java/io/opencensus/metrics/Distribution.java24
-rw-r--r--api/src/main/java/io/opencensus/metrics/Metric.java6
-rw-r--r--api/src/main/java/io/opencensus/metrics/MetricDescriptor.java24
-rw-r--r--api/src/main/java/io/opencensus/metrics/Summary.java187
-rw-r--r--api/src/main/java/io/opencensus/metrics/Value.java54
-rw-r--r--api/src/test/java/io/opencensus/metrics/DistributionTest.java29
-rw-r--r--api/src/test/java/io/opencensus/metrics/PointTest.java2
-rw-r--r--api/src/test/java/io/opencensus/metrics/SummaryTest.java189
-rw-r--r--api/src/test/java/io/opencensus/metrics/ValueTest.java35
-rw-r--r--impl_core/src/main/java/io/opencensus/implcore/stats/MutableAggregation.java6
10 files changed, 521 insertions, 35 deletions
diff --git a/api/src/main/java/io/opencensus/metrics/Distribution.java b/api/src/main/java/io/opencensus/metrics/Distribution.java
index 87f99635..9294b838 100644
--- a/api/src/main/java/io/opencensus/metrics/Distribution.java
+++ b/api/src/main/java/io/opencensus/metrics/Distribution.java
@@ -45,17 +45,17 @@ public abstract class Distribution {
/**
* Creates a {@link Distribution}.
*
- * @param mean mean of the population values.
- * @param count count of the population values.
- * @param sumOfSquaredDeviations sum of squared deviations of the population values.
+ * @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 bucketBoundaries bucket boundaries of a histogram.
* @param buckets {@link Bucket}s of a histogram.
* @return a {@code Distribution}.
* @since 0.17
*/
public static Distribution create(
- double mean,
long count,
+ double sum,
double sumOfSquaredDeviations,
List<Double> bucketBoundaries,
List<Bucket> buckets) {
@@ -63,13 +63,13 @@ public abstract class Distribution {
Utils.checkArgument(
sumOfSquaredDeviations >= 0, "sum of squared deviations should be non-negative.");
if (count == 0) {
- Utils.checkArgument(mean == 0, "mean should be 0 if count is 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.");
}
return new AutoValue_Distribution(
- mean,
count,
+ sum,
sumOfSquaredDeviations,
copyBucketBounds(bucketBoundaries),
copyBucketCount(buckets));
@@ -100,20 +100,20 @@ public abstract class Distribution {
}
/**
- * Returns the aggregated mean.
+ * Returns the aggregated count.
*
- * @return the aggregated mean.
+ * @return the aggregated count.
* @since 0.17
*/
- public abstract double getMean();
+ public abstract long getCount();
/**
- * Returns the aggregated count.
+ * Returns the aggregated sum.
*
- * @return the aggregated count.
+ * @return the aggregated sum.
* @since 0.17
*/
- public abstract long getCount();
+ public abstract double getSum();
/**
* Returns the aggregated sum of squared deviations.
diff --git a/api/src/main/java/io/opencensus/metrics/Metric.java b/api/src/main/java/io/opencensus/metrics/Metric.java
index b463420c..0c108b56 100644
--- a/api/src/main/java/io/opencensus/metrics/Metric.java
+++ b/api/src/main/java/io/opencensus/metrics/Metric.java
@@ -22,6 +22,7 @@ import io.opencensus.internal.Utils;
import io.opencensus.metrics.Value.ValueDistribution;
import io.opencensus.metrics.Value.ValueDouble;
import io.opencensus.metrics.Value.ValueLong;
+import io.opencensus.metrics.Value.ValueSummary;
import java.util.List;
import javax.annotation.concurrent.Immutable;
@@ -88,9 +89,14 @@ public abstract class Metric {
Utils.checkArgument(
value instanceof ValueDouble, "Type mismatch: %s, %s.", type, valueClassName);
break;
+ case GAUGE_DISTRIBUTION:
case CUMULATIVE_DISTRIBUTION:
Utils.checkArgument(
value instanceof ValueDistribution, "Type mismatch: %s, %s.", type, valueClassName);
+ break;
+ case SUMMARY:
+ Utils.checkArgument(
+ value instanceof ValueSummary, "Type mismatch: %s, %s.", type, valueClassName);
}
}
}
diff --git a/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java b/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java
index e20730e9..5146cd85 100644
--- a/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java
+++ b/api/src/main/java/io/opencensus/metrics/MetricDescriptor.java
@@ -127,6 +127,15 @@ public abstract class MetricDescriptor {
GAUGE_DOUBLE,
/**
+ * An instantaneous measurement of a distribution value. The count and sum can go both up and
+ * down. Used in scenarios like a snapshot of time the current items in a queue have spent
+ * there.
+ *
+ * @since 0.17
+ */
+ GAUGE_DISTRIBUTION,
+
+ /**
* An cumulative measurement of an int64 value.
*
* @since 0.17
@@ -141,10 +150,23 @@ public abstract class MetricDescriptor {
CUMULATIVE_DOUBLE,
/**
- * An cumulative measurement of a distribution value.
+ * An cumulative measurement of a distribution value. The count and sum can only go up, if
+ * resets then the start_time should also be reset.
*
* @since 0.17
*/
CUMULATIVE_DISTRIBUTION,
+
+ /**
+ * Some frameworks implemented DISTRIBUTION as a summary of observations (usually things like
+ * request durations and response sizes). While it also provides a total count of observations
+ * and a sum of all observed values, it calculates configurable quantiles over a sliding time
+ * window.
+ *
+ * <p>This is not recommended, since it cannot be aggregated.
+ *
+ * @since 0.17
+ */
+ SUMMARY,
}
}
diff --git a/api/src/main/java/io/opencensus/metrics/Summary.java b/api/src/main/java/io/opencensus/metrics/Summary.java
new file mode 100644
index 00000000..f23667bb
--- /dev/null
+++ b/api/src/main/java/io/opencensus/metrics/Summary.java
@@ -0,0 +1,187 @@
+/*
+ * 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;
+
+import com.google.auto.value.AutoValue;
+import io.opencensus.common.ExperimentalApi;
+import io.opencensus.internal.Utils;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * Implementation of the {@link Distribution} as a summary of observations.
+ *
+ * <p>This is not recommended, since it cannot be aggregated.
+ *
+ * @since 0.17
+ */
+@ExperimentalApi
+@AutoValue
+@Immutable
+public abstract class Summary {
+ Summary() {}
+
+ /**
+ * Creates a {@link Summary}.
+ *
+ * @param count the count of the population values.
+ * @param sum the sum of the population values.
+ * @param snapshot bucket boundaries of a histogram.
+ * @return a {@code Summary} with the given values.
+ * @since 0.17
+ */
+ public static Summary create(@Nullable Long count, @Nullable Double sum, Snapshot snapshot) {
+ checkCountAndSum(count, sum);
+ Utils.checkNotNull(snapshot, "snapshot");
+ return new AutoValue_Summary(count, sum, snapshot);
+ }
+
+ /**
+ * Returns the aggregated count. If not available returns {@code null}.
+ *
+ * @return the aggregated count.
+ * @since 0.17
+ */
+ @Nullable
+ public abstract Long getCount();
+
+ /**
+ * Returns the aggregated sum. If not available returns {@code null}.
+ *
+ * @return the aggregated sum.
+ * @since 0.17
+ */
+ @Nullable
+ public abstract Double getSum();
+
+ /**
+ * Returns the {@link Snapshot}.
+ *
+ * @return the {@code Snapshot}.
+ * @since 0.17
+ */
+ public abstract Snapshot getSnapshot();
+
+ /**
+ * Represents the summary observation of the recorded events over a sliding time window.
+ *
+ * @since 0.17
+ */
+ @Immutable
+ @AutoValue
+ public abstract static class Snapshot {
+ /**
+ * Returns the number of values in this {@code Snapshot}. If not available returns {@code null}.
+ *
+ * @return the number of values in this {@code Snapshot}.
+ * @since 0.17
+ */
+ @Nullable
+ public abstract Long getCount();
+
+ /**
+ * Returns the sum of values in this {@code Snapshot}. If not available returns {@code null}.
+ *
+ * @return the sum of values in this {@code Snapshot}.
+ * @since 0.17
+ */
+ @Nullable
+ public abstract Double getSum();
+
+ /**
+ * Returns the list of {@code ValueAtPercentile}s in this {@code Snapshot}.
+ *
+ * @return the list of {@code ValueAtPercentile}s in this {@code Snapshot}.
+ * @since 0.17
+ */
+ public abstract List<ValueAtPercentile> getValueAtPercentiles();
+
+ /**
+ * Creates a {@link Snapshot}.
+ *
+ * @param count the number of values in this {@code Snapshot}.
+ * @param sum the number of values in this {@code Snapshot}.
+ * @param valueAtPercentiles the list of {@code ValueAtPercentile}.
+ * @return a {@code Snapshot} with the given values.
+ * @since 0.17
+ */
+ public static Snapshot create(
+ @Nullable Long count, @Nullable Double sum, List<ValueAtPercentile> valueAtPercentiles) {
+ checkCountAndSum(count, sum);
+ Utils.checkNotNull(valueAtPercentiles, "valueAtPercentiles");
+ Utils.checkListElementNotNull(valueAtPercentiles, "value in valueAtPercentiles");
+ return new AutoValue_Summary_Snapshot(
+ count,
+ sum,
+ Collections.unmodifiableList(new ArrayList<ValueAtPercentile>(valueAtPercentiles)));
+ }
+
+ /**
+ * Represents the value at a given percentile of a distribution.
+ *
+ * @since 0.17
+ */
+ @Immutable
+ @AutoValue
+ public abstract static class ValueAtPercentile {
+ /**
+ * Returns the percentile in this {@code ValueAtPercentile}.
+ *
+ * <p>Must be in the interval (0.0, 100.0].
+ *
+ * @return the percentile in this {@code ValueAtPercentile}.
+ * @since 0.17
+ */
+ public abstract double getPercentile();
+
+ /**
+ * Returns the value in this {@code ValueAtPercentile}.
+ *
+ * @return the value in this {@code ValueAtPercentile}.
+ * @since 0.17
+ */
+ public abstract double getValue();
+
+ /**
+ * Creates a {@link ValueAtPercentile}.
+ *
+ * @param percentile the percentile in this {@code ValueAtPercentile}.
+ * @param value the value in this {@code ValueAtPercentile}.
+ * @return a {@code ValueAtPercentile} with the given values.
+ * @since 0.17
+ */
+ public static ValueAtPercentile create(double percentile, double value) {
+ Utils.checkArgument(
+ 0 < percentile && percentile <= 100.0,
+ "percentile must be in the interval (0.0, 100.0]");
+ Utils.checkArgument(value >= 0, "value must be non-negative");
+ return new AutoValue_Summary_Snapshot_ValueAtPercentile(percentile, value);
+ }
+ }
+ }
+
+ private static void checkCountAndSum(@Nullable Long count, @Nullable Double sum) {
+ Utils.checkArgument(count == null || count >= 0, "count must be non-negative.");
+ Utils.checkArgument(sum == null || sum >= 0, "sum must be non-negative.");
+ if (count != null && count == 0) {
+ Utils.checkArgument(sum == null || sum == 0, "sum must be 0 if count is 0.");
+ }
+ }
+}
diff --git a/api/src/main/java/io/opencensus/metrics/Value.java b/api/src/main/java/io/opencensus/metrics/Value.java
index 5dd70c8d..1bc63b79 100644
--- a/api/src/main/java/io/opencensus/metrics/Value.java
+++ b/api/src/main/java/io/opencensus/metrics/Value.java
@@ -76,6 +76,17 @@ public abstract class Value {
}
/**
+ * Returns a {@link Summary} {@link Value}.
+ *
+ * @param value value in {@link Summary}.
+ * @return a {@code Summary} {@code Value}.
+ * @since 0.17
+ */
+ public static Value summaryValue(Summary value) {
+ return ValueSummary.create(value);
+ }
+
+ /**
* Applies the given match function to the underlying data type.
*
* @since 0.17
@@ -84,6 +95,7 @@ public abstract class Value {
Function<? super Double, T> doubleFunction,
Function<? super Long, T> longFunction,
Function<? super Distribution, T> distributionFunction,
+ Function<? super Summary, T> summaryFunction,
Function<? super Value, T> defaultFunction);
/** A 64-bit double-precision floating-point {@link Value}. */
@@ -98,6 +110,7 @@ public abstract class Value {
Function<? super Double, T> doubleFunction,
Function<? super Long, T> longFunction,
Function<? super Distribution, T> distributionFunction,
+ Function<? super Summary, T> summaryFunction,
Function<? super Value, T> defaultFunction) {
return doubleFunction.apply(getValue());
}
@@ -132,6 +145,7 @@ public abstract class Value {
Function<? super Double, T> doubleFunction,
Function<? super Long, T> longFunction,
Function<? super Distribution, T> distributionFunction,
+ Function<? super Summary, T> summaryFunction,
Function<? super Value, T> defaultFunction) {
return longFunction.apply(getValue());
}
@@ -169,6 +183,7 @@ public abstract class Value {
Function<? super Double, T> doubleFunction,
Function<? super Long, T> longFunction,
Function<? super Distribution, T> distributionFunction,
+ Function<? super Summary, T> summaryFunction,
Function<? super Value, T> defaultFunction) {
return distributionFunction.apply(getValue());
}
@@ -191,6 +206,41 @@ public abstract class Value {
abstract Distribution getValue();
}
- // TODO(songya): Add support for Summary type.
- // This is an aggregation that produces percentiles directly.
+ /**
+ * {@link ValueSummary} contains a snapshot representing values calculated over an arbitrary time
+ * window.
+ */
+ @AutoValue
+ @Immutable
+ abstract static class ValueSummary extends Value {
+
+ ValueSummary() {}
+
+ @Override
+ public final <T> T match(
+ Function<? super Double, T> doubleFunction,
+ Function<? super Long, T> longFunction,
+ Function<? super Distribution, T> distributionFunction,
+ Function<? super Summary, T> summaryFunction,
+ Function<? super Value, T> defaultFunction) {
+ return summaryFunction.apply(getValue());
+ }
+
+ /**
+ * Creates a {@link ValueSummary}.
+ *
+ * @param value the {@link Summary} value.
+ * @return a {@code ValueSummary}.
+ */
+ static ValueSummary create(Summary value) {
+ return new AutoValue_Value_ValueSummary(value);
+ }
+
+ /**
+ * Returns the {@link Summary} value.
+ *
+ * @return the {@code Summary} value.
+ */
+ abstract Summary getValue();
+ }
}
diff --git a/api/src/test/java/io/opencensus/metrics/DistributionTest.java b/api/src/test/java/io/opencensus/metrics/DistributionTest.java
index d511e317..5ee88dd6 100644
--- a/api/src/test/java/io/opencensus/metrics/DistributionTest.java
+++ b/api/src/test/java/io/opencensus/metrics/DistributionTest.java
@@ -32,7 +32,7 @@ import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
-/** Unit tests for {@link Value}. */
+/** Unit tests for {@link Distribution}. */
@RunWith(JUnit4.class)
public class DistributionTest {
@@ -40,6 +40,7 @@ public class DistributionTest {
private static final Timestamp TIMESTAMP = Timestamp.create(1, 0);
private static final Map<String, String> ATTACHMENTS = Collections.singletonMap("key", "value");
+ private static final double TOLERANCE = 1e-6;
@Test
public void createAndGet_Bucket() {
@@ -66,7 +67,7 @@ public class DistributionTest {
@Test
public void createAndGet_Exemplar() {
Exemplar exemplar = Exemplar.create(-9.9, TIMESTAMP, ATTACHMENTS);
- assertThat(exemplar.getValue()).isEqualTo(-9.9);
+ assertThat(exemplar.getValue()).isWithin(TOLERANCE).of(-9.9);
assertThat(exemplar.getTimestamp()).isEqualTo(TIMESTAMP);
assertThat(exemplar.getAttachments()).isEqualTo(ATTACHMENTS);
}
@@ -78,10 +79,10 @@ public class DistributionTest {
List<Bucket> buckets =
Arrays.asList(
Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4, exemplar));
- Distribution distribution = Distribution.create(6.6, 10, 678.54, bucketBounds, buckets);
- assertThat(distribution.getMean()).isEqualTo(6.6);
+ Distribution distribution = Distribution.create(10, 6.6, 678.54, bucketBounds, buckets);
assertThat(distribution.getCount()).isEqualTo(10);
- assertThat(distribution.getSumOfSquaredDeviations()).isEqualTo(678.54);
+ assertThat(distribution.getSum()).isWithin(TOLERANCE).of(6.6);
+ assertThat(distribution.getSumOfSquaredDeviations()).isWithin(TOLERANCE).of(678.54);
assertThat(distribution.getBucketBoundaries())
.containsExactlyElementsIn(bucketBounds)
.inOrder();
@@ -125,7 +126,7 @@ public class DistributionTest {
Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4));
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("count should be non-negative.");
- Distribution.create(6.6, -10, 678.54, bucketBounds, buckets);
+ Distribution.create(-10, 6.6, 678.54, bucketBounds, buckets);
}
@Test
@@ -135,7 +136,7 @@ public class DistributionTest {
Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0));
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("sum of squared deviations should be non-negative.");
- Distribution.create(6.6, 0, -678.54, bucketBounds, buckets);
+ Distribution.create(0, 6.6, -678.54, bucketBounds, buckets);
}
@Test
@@ -144,8 +145,8 @@ public class DistributionTest {
List<Bucket> buckets =
Arrays.asList(Bucket.create(0), Bucket.create(0), Bucket.create(0), Bucket.create(0));
thrown.expect(IllegalArgumentException.class);
- thrown.expectMessage("mean should be 0 if count is 0.");
- Distribution.create(6.6, 0, 0, bucketBounds, buckets);
+ thrown.expectMessage("sum should be 0 if count is 0.");
+ Distribution.create(0, 6.6, 0, bucketBounds, buckets);
}
@Test
@@ -164,7 +165,7 @@ public class DistributionTest {
Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4));
thrown.expect(NullPointerException.class);
thrown.expectMessage("bucketBoundaries list should not be null.");
- Distribution.create(6.6, 10, 678.54, null, buckets);
+ Distribution.create(10, 6.6, 678.54, null, buckets);
}
@Test
@@ -174,7 +175,7 @@ public class DistributionTest {
Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4));
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("bucket boundaries not sorted.");
- Distribution.create(6.6, 10, 678.54, bucketBounds, buckets);
+ Distribution.create(10, 6.6, 678.54, bucketBounds, buckets);
}
@Test
@@ -182,7 +183,7 @@ public class DistributionTest {
List<Double> bucketBounds = Arrays.asList(-1.0, 0.0, 1.0);
thrown.expect(NullPointerException.class);
thrown.expectMessage("bucket list should not be null.");
- Distribution.create(6.6, 10, 678.54, bucketBounds, null);
+ Distribution.create(10, 6.6, 678.54, bucketBounds, null);
}
@Test
@@ -192,7 +193,7 @@ public class DistributionTest {
Arrays.asList(Bucket.create(3), Bucket.create(1), null, Bucket.create(4));
thrown.expect(NullPointerException.class);
thrown.expectMessage("bucket should not be null.");
- Distribution.create(6.6, 10, 678.54, bucketBounds, buckets);
+ Distribution.create(10, 6.6, 678.54, bucketBounds, buckets);
}
@Test
@@ -215,7 +216,7 @@ public class DistributionTest {
Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))))
.addEqualityGroup(
Distribution.create(
- -7,
+ 7,
10,
23.456,
Arrays.asList(-5.0, 0.0, 5.0),
diff --git a/api/src/test/java/io/opencensus/metrics/PointTest.java b/api/src/test/java/io/opencensus/metrics/PointTest.java
index cb6175c1..708814c5 100644
--- a/api/src/test/java/io/opencensus/metrics/PointTest.java
+++ b/api/src/test/java/io/opencensus/metrics/PointTest.java
@@ -35,8 +35,8 @@ public class PointTest {
private static final Value DISTRIBUTION_VALUE =
Value.distributionValue(
Distribution.create(
- 6.6,
10,
+ 6.6,
678.54,
Arrays.asList(-1.0, 0.0, 1.0),
Arrays.asList(
diff --git a/api/src/test/java/io/opencensus/metrics/SummaryTest.java b/api/src/test/java/io/opencensus/metrics/SummaryTest.java
new file mode 100644
index 00000000..0b70d94e
--- /dev/null
+++ b/api/src/test/java/io/opencensus/metrics/SummaryTest.java
@@ -0,0 +1,189 @@
+/*
+ * 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;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.testing.EqualsTester;
+import io.opencensus.metrics.Summary.Snapshot;
+import io.opencensus.metrics.Summary.Snapshot.ValueAtPercentile;
+import java.util.Collections;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link Summary}. */
+@RunWith(JUnit4.class)
+public class SummaryTest {
+
+ @Rule public final ExpectedException thrown = ExpectedException.none();
+ private static final double TOLERANCE = 1e-6;
+
+ @Test
+ public void createAndGet_ValueAtPercentile() {
+ ValueAtPercentile valueAtPercentile = ValueAtPercentile.create(99.5, 10.2);
+ assertThat(valueAtPercentile.getPercentile()).isWithin(TOLERANCE).of(99.5);
+ assertThat(valueAtPercentile.getValue()).isWithin(TOLERANCE).of(10.2);
+ }
+
+ @Test
+ public void createValueAtPercentile_InvalidValueAtPercentileInterval() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("percentile must be in the interval (0.0, 100.0]");
+ ValueAtPercentile.create(100.1, 10.2);
+ }
+
+ @Test
+ public void createValueAtPercentile_NegativeValue() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("value must be non-negative");
+ ValueAtPercentile.create(99.5, -10.2);
+ }
+
+ @Test
+ public void createAndGet_Snapshot() {
+ Snapshot snapshot =
+ Snapshot.create(
+ 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)));
+ assertThat(snapshot.getCount()).isEqualTo(10);
+ assertThat(snapshot.getSum()).isWithin(TOLERANCE).of(87.07);
+ assertThat(snapshot.getValueAtPercentiles())
+ .containsExactly(ValueAtPercentile.create(99.5, 10.2));
+ }
+
+ @Test
+ public void createAndGet_Snapshot_WithNullCountAndSum() {
+ Snapshot snapshot =
+ Snapshot.create(
+ null, null, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)));
+ assertThat(snapshot.getCount()).isNull();
+ assertThat(snapshot.getSum()).isNull();
+ assertThat(snapshot.getValueAtPercentiles())
+ .containsExactly(ValueAtPercentile.create(99.5, 10.2));
+ }
+
+ @Test
+ public void createSnapshot_NegativeCount() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("count must be non-negative");
+ Snapshot.create(-10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)));
+ }
+
+ @Test
+ public void createSnapshot_NegativeSum() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("sum must be non-negative");
+ Snapshot.create(10L, -87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)));
+ }
+
+ @Test
+ public void createSnapshot_ZeroCountAndNonZeroSum() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("sum must be 0 if count is 0");
+ Snapshot.create(0L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)));
+ }
+
+ @Test
+ public void createSnapshot_NullValueAtPercentilesList() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("valueAtPercentiles");
+ Snapshot.create(10L, 87.07, null);
+ }
+
+ @Test
+ public void createSnapshot_OneNullValueAtPercentile() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("value in valueAtPercentiles");
+ Snapshot.create(10L, 87.07, Collections.<ValueAtPercentile>singletonList(null));
+ }
+
+ @Test
+ public void createAndGet_Summary() {
+ Snapshot snapshot =
+ Snapshot.create(
+ 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)));
+ Summary summary = Summary.create(10L, 6.6, snapshot);
+ assertThat(summary.getCount()).isEqualTo(10);
+ assertThat(summary.getSum()).isWithin(TOLERANCE).of(6.6);
+ assertThat(summary.getSnapshot()).isEqualTo(snapshot);
+ }
+
+ @Test
+ public void createSummary_NegativeCount() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("count must be non-negative");
+ Summary.create(
+ -10L, 6.6, Snapshot.create(null, null, Collections.<ValueAtPercentile>emptyList()));
+ }
+
+ @Test
+ public void createSummary_NegativeSum() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("sum must be non-negative");
+ Summary.create(
+ 10L, -6.6, Snapshot.create(null, null, Collections.<ValueAtPercentile>emptyList()));
+ }
+
+ @Test
+ public void createSummary_ZeroCountAndNonZeroSum() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("sum must be 0 if count is 0");
+ Summary.create(
+ 0L, 6.6, Snapshot.create(null, null, Collections.<ValueAtPercentile>emptyList()));
+ }
+
+ @Test
+ public void createSummary_NullSnapshot() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("snapshot");
+ Summary.create(10L, 6.6, null);
+ }
+
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(
+ Summary.create(
+ 10L,
+ 10.0,
+ Snapshot.create(
+ 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)))),
+ Summary.create(
+ 10L,
+ 10.0,
+ Snapshot.create(
+ 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)))))
+ .addEqualityGroup(
+ Summary.create(
+ 7L,
+ 10.0,
+ Snapshot.create(
+ 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)))))
+ .addEqualityGroup(
+ Summary.create(
+ 10L,
+ 7.0,
+ Snapshot.create(
+ 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(99.5, 10.2)))))
+ .addEqualityGroup(
+ Summary.create(
+ 10L, 10.0, Snapshot.create(null, null, Collections.<ValueAtPercentile>emptyList())))
+ .testEquals();
+ }
+}
diff --git a/api/src/test/java/io/opencensus/metrics/ValueTest.java b/api/src/test/java/io/opencensus/metrics/ValueTest.java
index 63430b28..a65202a8 100644
--- a/api/src/test/java/io/opencensus/metrics/ValueTest.java
+++ b/api/src/test/java/io/opencensus/metrics/ValueTest.java
@@ -22,11 +22,15 @@ import com.google.common.testing.EqualsTester;
import io.opencensus.common.Function;
import io.opencensus.common.Functions;
import io.opencensus.metrics.Distribution.Bucket;
+import io.opencensus.metrics.Summary.Snapshot;
+import io.opencensus.metrics.Summary.Snapshot.ValueAtPercentile;
import io.opencensus.metrics.Value.ValueDistribution;
import io.opencensus.metrics.Value.ValueDouble;
import io.opencensus.metrics.Value.ValueLong;
+import io.opencensus.metrics.Value.ValueSummary;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -35,6 +39,7 @@ import org.junit.runners.JUnit4;
/** Unit tests for {@link Value}. */
@RunWith(JUnit4.class)
public class ValueTest {
+ private static final double TOLERANCE = 1e-6;
private static final Distribution DISTRIBUTION =
Distribution.create(
@@ -43,12 +48,18 @@ public class ValueTest {
1,
Arrays.asList(-5.0, 0.0, 5.0),
Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4)));
+ private static final Summary SUMMARY =
+ Summary.create(
+ 10L,
+ 10.0,
+ Snapshot.create(
+ 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(0.98, 10.2))));
@Test
public void createAndGet_ValueDouble() {
Value value = Value.doubleValue(-34.56);
assertThat(value).isInstanceOf(ValueDouble.class);
- assertThat(((ValueDouble) value).getValue()).isEqualTo(-34.56);
+ assertThat(((ValueDouble) value).getValue()).isWithin(TOLERANCE).of(-34.56);
}
@Test
@@ -66,6 +77,13 @@ public class ValueTest {
}
@Test
+ public void createAndGet_ValueSummary() {
+ Value value = Value.summaryValue(SUMMARY);
+ assertThat(value).isInstanceOf(ValueSummary.class);
+ assertThat(((ValueSummary) value).getValue()).isEqualTo(SUMMARY);
+ }
+
+ @Test
public void testEquals() {
new EqualsTester()
.addEqualityGroup(Value.doubleValue(1.0), Value.doubleValue(1.0))
@@ -75,7 +93,7 @@ public class ValueTest {
.addEqualityGroup(
Value.distributionValue(
Distribution.create(
- -7,
+ 7,
10,
23.456,
Arrays.asList(-5.0, 0.0, 5.0),
@@ -88,7 +106,10 @@ public class ValueTest {
public void testMatch() {
List<Value> values =
Arrays.asList(
- ValueDouble.create(1.0), ValueLong.create(-1), ValueDistribution.create(DISTRIBUTION));
+ ValueDouble.create(1.0),
+ ValueLong.create(-1),
+ ValueDistribution.create(DISTRIBUTION),
+ ValueSummary.create(SUMMARY));
List<Number> expected =
Arrays.<Number>asList(1.0, -1L, 10.0, 10L, 1.0, -5.0, 0.0, 5.0, 3L, 1L, 2L, 4L);
final List<Number> actual = new ArrayList<Number>();
@@ -111,7 +132,7 @@ public class ValueTest {
new Function<Distribution, Object>() {
@Override
public Object apply(Distribution arg) {
- actual.add(arg.getMean());
+ actual.add(arg.getSum());
actual.add(arg.getCount());
actual.add(arg.getSumOfSquaredDeviations());
actual.addAll(arg.getBucketBoundaries());
@@ -121,6 +142,12 @@ public class ValueTest {
return null;
}
},
+ new Function<Summary, Object>() {
+ @Override
+ public Object apply(Summary arg) {
+ return null;
+ }
+ },
Functions.throwAssertionError());
}
assertThat(actual).containsExactlyElementsIn(expected).inOrder();
diff --git a/impl_core/src/main/java/io/opencensus/implcore/stats/MutableAggregation.java b/impl_core/src/main/java/io/opencensus/implcore/stats/MutableAggregation.java
index a41850d2..eaf440ff 100644
--- a/impl_core/src/main/java/io/opencensus/implcore/stats/MutableAggregation.java
+++ b/impl_core/src/main/java/io/opencensus/implcore/stats/MutableAggregation.java
@@ -430,7 +430,11 @@ abstract class MutableAggregation {
return Point.create(
Value.distributionValue(
Distribution.create(
- mean, count, sumOfSquaredDeviations, bucketBoundaries.getBoundaries(), buckets)),
+ count,
+ mean * count,
+ sumOfSquaredDeviations,
+ bucketBoundaries.getBoundaries(),
+ buckets)),
timestamp);
}