aboutsummaryrefslogtreecommitdiff
path: root/api
diff options
context:
space:
mode:
authorYang Song <songy23@users.noreply.github.com>2018-06-29 11:48:27 -0700
committerGitHub <noreply@github.com>2018-06-29 11:48:27 -0700
commita7893d2a3fc4ef7fae138b67b22f3ffd51e5f529 (patch)
tree5c1cd53b0ae2acc49a50950e6d4ea48542bee1fc /api
parent273c9536f9ec33af05830ce9d7aaf37e35fd86db (diff)
downloadopencensus-java-a7893d2a3fc4ef7fae138b67b22f3ffd51e5f529.tar.gz
Stats: Add Exemplar class to DistributionData. (#1287)
Diffstat (limited to 'api')
-rw-r--r--api/src/main/java/io/opencensus/stats/AggregationData.java119
-rw-r--r--api/src/test/java/io/opencensus/stats/AggregationDataTest.java63
2 files changed, 179 insertions, 3 deletions
diff --git a/api/src/main/java/io/opencensus/stats/AggregationData.java b/api/src/main/java/io/opencensus/stats/AggregationData.java
index 95ac3282..eb7d40b3 100644
--- a/api/src/main/java/io/opencensus/stats/AggregationData.java
+++ b/api/src/main/java/io/opencensus/stats/AggregationData.java
@@ -18,10 +18,14 @@ package io.opencensus.stats;
import com.google.auto.value.AutoValue;
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.concurrent.Immutable;
/**
@@ -268,8 +272,9 @@ public abstract class AggregationData {
* @param max max value.
* @param sumOfSquaredDeviations sum of squared deviations.
* @param bucketCounts histogram bucket counts.
+ * @param exemplars the exemplars associated with histogram buckets.
* @return a {@code DistributionData}.
- * @since 0.8
+ * @since 0.16
*/
public static DistributionData create(
double mean,
@@ -277,7 +282,8 @@ public abstract class AggregationData {
double min,
double max,
double sumOfSquaredDeviations,
- List<Long> bucketCounts) {
+ List<Long> bucketCounts,
+ List<Exemplar> exemplars) {
if (min != Double.POSITIVE_INFINITY || max != Double.NEGATIVE_INFINITY) {
Utils.checkArgument(min <= max, "max should be greater or equal to min.");
}
@@ -288,8 +294,48 @@ public abstract class AggregationData {
Utils.checkNotNull(bucket, "bucket should not be null.");
}
+ Utils.checkNotNull(exemplars, "exemplar list should not be null.");
+ for (Exemplar exemplar : exemplars) {
+ Utils.checkNotNull(exemplar, "exemplar should not be null.");
+ }
+
return new AutoValue_AggregationData_DistributionData(
- mean, count, min, max, sumOfSquaredDeviations, bucketCountsCopy);
+ mean,
+ count,
+ min,
+ max,
+ sumOfSquaredDeviations,
+ bucketCountsCopy,
+ Collections.<Exemplar>unmodifiableList(new ArrayList<Exemplar>(exemplars)));
+ }
+
+ /**
+ * Creates a {@code DistributionData}.
+ *
+ * @param mean mean value.
+ * @param count count value.
+ * @param min min value.
+ * @param max max value.
+ * @param sumOfSquaredDeviations sum of squared deviations.
+ * @param bucketCounts histogram bucket counts.
+ * @return a {@code DistributionData}.
+ * @since 0.8
+ */
+ public static DistributionData create(
+ double mean,
+ long count,
+ double min,
+ double max,
+ double sumOfSquaredDeviations,
+ List<Long> bucketCounts) {
+ return create(
+ mean,
+ count,
+ min,
+ max,
+ sumOfSquaredDeviations,
+ bucketCounts,
+ Collections.<Exemplar>emptyList());
}
/**
@@ -341,6 +387,14 @@ public abstract class AggregationData {
*/
public abstract List<Long> getBucketCounts();
+ /**
+ * Returns the {@link Exemplar}s associated with histogram buckets.
+ *
+ * @return the {@code Exemplar}s associated with histogram buckets.
+ * @since 0.16
+ */
+ public abstract List<Exemplar> getExemplars();
+
@Override
public final <T> T match(
Function<? super SumDataDouble, T> p0,
@@ -352,6 +406,65 @@ public abstract class AggregationData {
Function<? super AggregationData, T> defaultFunction) {
return p3.apply(this);
}
+
+ /**
+ * An example point that may be used to annotate aggregated distribution values, associated with
+ * a histogram bucket.
+ *
+ * @since 0.16
+ */
+ @Immutable
+ @AutoValue
+ public abstract static class Exemplar {
+
+ Exemplar() {}
+
+ /**
+ * Returns value of the {@link Exemplar} point.
+ *
+ * @return value of the {@code Exemplar} point.
+ * @since 0.16
+ */
+ 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.16
+ */
+ 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.16
+ */
+ 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.16
+ */
+ 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_AggregationData_DistributionData_Exemplar(
+ value, timestamp, attachmentsCopy);
+ }
+ }
}
/**
diff --git a/api/src/test/java/io/opencensus/stats/AggregationDataTest.java b/api/src/test/java/io/opencensus/stats/AggregationDataTest.java
index 9f2aa589..60551600 100644
--- a/api/src/test/java/io/opencensus/stats/AggregationDataTest.java
+++ b/api/src/test/java/io/opencensus/stats/AggregationDataTest.java
@@ -21,8 +21,10 @@ import static com.google.common.truth.Truth.assertThat;
import com.google.common.testing.EqualsTester;
import io.opencensus.common.Function;
import io.opencensus.common.Functions;
+import io.opencensus.common.Timestamp;
import io.opencensus.stats.AggregationData.CountData;
import io.opencensus.stats.AggregationData.DistributionData;
+import io.opencensus.stats.AggregationData.DistributionData.Exemplar;
import io.opencensus.stats.AggregationData.LastValueDataDouble;
import io.opencensus.stats.AggregationData.LastValueDataLong;
import io.opencensus.stats.AggregationData.MeanData;
@@ -30,7 +32,9 @@ import io.opencensus.stats.AggregationData.SumDataDouble;
import io.opencensus.stats.AggregationData.SumDataLong;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
+import java.util.Map;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -42,6 +46,9 @@ import org.junit.runners.JUnit4;
public class AggregationDataTest {
private static final double TOLERANCE = 1e-6;
+ private static final Timestamp TIMESTAMP_1 = Timestamp.create(1, 0);
+ private static final Timestamp TIMESTAMP_2 = Timestamp.create(2, 0);
+ private static final Map<String, String> ATTACHMENTS = Collections.singletonMap("key", "value");
@Rule public ExpectedException thrown = ExpectedException.none();
@@ -58,6 +65,47 @@ public class AggregationDataTest {
}
@Test
+ public void testCreateDistributionDataWithExemplar() {
+ Exemplar exemplar1 = Exemplar.create(4, TIMESTAMP_2, ATTACHMENTS);
+ Exemplar exemplar2 = Exemplar.create(1, TIMESTAMP_1, ATTACHMENTS);
+ DistributionData distributionData =
+ DistributionData.create(
+ 7.7, 10, 1.1, 9.9, 32.2, Arrays.asList(4L, 1L), Arrays.asList(exemplar1, exemplar2));
+ assertThat(distributionData.getExemplars()).containsExactly(exemplar1, exemplar2).inOrder();
+ }
+
+ @Test
+ public void testExemplar() {
+ Exemplar exemplar = Exemplar.create(15.0, TIMESTAMP_1, ATTACHMENTS);
+ assertThat(exemplar.getValue()).isEqualTo(15.0);
+ assertThat(exemplar.getTimestamp()).isEqualTo(TIMESTAMP_1);
+ assertThat(exemplar.getAttachments()).isEqualTo(ATTACHMENTS);
+ }
+
+ @Test
+ public void testExemplar_PreventNullAttachments() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("attachments");
+ Exemplar.create(15, TIMESTAMP_1, null);
+ }
+
+ @Test
+ public void testExemplar_PreventNullAttachmentKey() {
+ Map<String, String> attachments = Collections.singletonMap(null, "value");
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("key of attachment");
+ Exemplar.create(15, TIMESTAMP_1, attachments);
+ }
+
+ @Test
+ public void testExemplar_PreventNullAttachmentValue() {
+ Map<String, String> attachments = Collections.singletonMap("key", null);
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("value of attachment");
+ Exemplar.create(15, TIMESTAMP_1, attachments);
+ }
+
+ @Test
public void preventNullBucketCountList() {
thrown.expect(NullPointerException.class);
thrown.expectMessage("bucket counts should not be null.");
@@ -72,6 +120,21 @@ public class AggregationDataTest {
}
@Test
+ public void preventNullExemplarList() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("exemplar list should not be null.");
+ DistributionData.create(1, 1, 1, 1, 0, Arrays.asList(0L, 1L, 1L), null);
+ }
+
+ @Test
+ public void preventNullExemplar() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("exemplar should not be null.");
+ DistributionData.create(
+ 1, 1, 1, 1, 0, Arrays.asList(0L, 1L, 1L), Collections.<Exemplar>singletonList(null));
+ }
+
+ @Test
public void preventMinIsGreaterThanMax() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("max should be greater or equal to min.");