diff options
| author | Yang Song <songy23@users.noreply.github.com> | 2017-09-04 14:52:57 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-09-04 14:52:57 -0700 |
| commit | 8b19f6e3a6cf88ee2661df86e2415cea8fee0609 (patch) | |
| tree | 9e836cb7c76c3889a3146785c4e06f6d56b98f50 | |
| parent | e24096c600bd57969a38099c36abeca72f2aa517 (diff) | |
| download | platform_external_opencensus-java-8b19f6e3a6cf88ee2661df86e2415cea8fee0609.tar.gz platform_external_opencensus-java-8b19f6e3a6cf88ee2661df86e2415cea8fee0609.tar.bz2 platform_external_opencensus-java-8b19f6e3a6cf88ee2661df86e2415cea8fee0609.zip | |
Add IntervalBucket and tests. (#537)
| -rw-r--r-- | api/src/main/java/io/opencensus/common/Duration.java | 1 | ||||
| -rw-r--r-- | core_impl/src/main/java/io/opencensus/implcore/stats/IntervalBucket.java | 82 | ||||
| -rw-r--r-- | core_impl/src/test/java/io/opencensus/implcore/stats/IntervalBucketTest.java | 137 | ||||
| -rw-r--r-- | gradle/wrapper/gradle-wrapper.jar | bin | 54712 -> 54712 bytes | |||
| -rw-r--r-- | gradle/wrapper/gradle-wrapper.properties | 2 |
5 files changed, 221 insertions, 1 deletions
diff --git a/api/src/main/java/io/opencensus/common/Duration.java b/api/src/main/java/io/opencensus/common/Duration.java index e355d7ed..b69416e8 100644 --- a/api/src/main/java/io/opencensus/common/Duration.java +++ b/api/src/main/java/io/opencensus/common/Duration.java @@ -31,6 +31,7 @@ import javax.annotation.concurrent.Immutable; */ @Immutable @AutoValue +// TODO(songya): implements Comparable<Duration> public abstract class Duration { private static final Duration ZERO = create(0, 0); diff --git a/core_impl/src/main/java/io/opencensus/implcore/stats/IntervalBucket.java b/core_impl/src/main/java/io/opencensus/implcore/stats/IntervalBucket.java new file mode 100644 index 00000000..9d8c96be --- /dev/null +++ b/core_impl/src/main/java/io/opencensus/implcore/stats/IntervalBucket.java @@ -0,0 +1,82 @@ +/* + * Copyright 2017, 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.implcore.stats; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static io.opencensus.implcore.stats.MutableViewData.toMillis; + +import com.google.common.collect.Maps; +import io.opencensus.common.Duration; +import io.opencensus.common.Timestamp; +import io.opencensus.stats.Aggregation; +import io.opencensus.tags.TagValue; +import java.util.List; +import java.util.Map; + +/** The bucket with aggregated {@code MeasureValue}s used for {@code IntervalViewData}. */ +final class IntervalBucket { + + private final Timestamp start; + private final Duration duration; + private final List<Aggregation> aggregations; + private final Map<List<TagValue>, List<MutableAggregation>> tagValueAggregationMap = + Maps.newHashMap(); + + IntervalBucket(Timestamp start, Duration duration, List<Aggregation> aggregations) { + checkNotNull(start, "Start"); + checkNotNull(duration, "Duration"); + checkNotNull(aggregations, "Aggregations"); + this.start = start; + this.duration = duration; + this.aggregations = aggregations; + } + + Map<List<TagValue>, List<MutableAggregation>> getTagValueAggregationMap() { + return tagValueAggregationMap; + } + + Timestamp getStart() { + return start; + } + + // Puts a new value into the internal MutableAggregations, based on the TagValues. + void record(List<TagValue> tagValues, double value) { + if (!tagValueAggregationMap.containsKey(tagValues)) { + tagValueAggregationMap.put( + tagValues, MutableViewData.createMutableAggregations(aggregations)); + } + for (MutableAggregation aggregation : tagValueAggregationMap.get(tagValues)) { + aggregation.add(value); + } + } + + /* + * Returns how much fraction of duration has passed in this IntervalBucket. For example, if this + * bucket starts at 10s and has a duration of 20s, and now is 15s, then getFraction() should + * return (15 - 10) / 20 = 0.25. + * + * This IntervalBucket must be current, i.e. the current timestamp must be within + * [this.start, this.start + this.duration). + */ + double getFraction(Timestamp now) { + Duration elapsedTime = now.subtractTimestamp(start); + checkArgument(toMillis(elapsedTime) >= 0 && toMillis(elapsedTime) < toMillis(duration), + "This bucket must be current."); + return ((double) toMillis(elapsedTime)) / toMillis(duration); + } +} diff --git a/core_impl/src/test/java/io/opencensus/implcore/stats/IntervalBucketTest.java b/core_impl/src/test/java/io/opencensus/implcore/stats/IntervalBucketTest.java new file mode 100644 index 00000000..0eaf08f8 --- /dev/null +++ b/core_impl/src/test/java/io/opencensus/implcore/stats/IntervalBucketTest.java @@ -0,0 +1,137 @@ +/* + * Copyright 2017, 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.implcore.stats; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.common.Duration; +import io.opencensus.common.Timestamp; +import io.opencensus.implcore.stats.MutableAggregation.MutableCount; +import io.opencensus.implcore.stats.MutableAggregation.MutableHistogram; +import io.opencensus.implcore.stats.MutableAggregation.MutableSum; +import io.opencensus.stats.Aggregation; +import io.opencensus.stats.Aggregation.Count; +import io.opencensus.stats.Aggregation.Histogram; +import io.opencensus.stats.Aggregation.Sum; +import io.opencensus.stats.BucketBoundaries; +import io.opencensus.tags.TagValue; +import io.opencensus.tags.TagValue.TagValueString; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link IntervalBucket}. */ +@RunWith(JUnit4.class) +public class IntervalBucketTest { + + @Rule public final ExpectedException thrown = ExpectedException.none(); + + private static final double TOLERANCE = 1e-6; + private static final Duration MINUTE = Duration.create(60, 0); + private static final Timestamp START = Timestamp.create(60, 0); + private static final BucketBoundaries BUCKET_BOUNDARIES = + BucketBoundaries.create(Arrays.asList(-10.0, 0.0, 10.0)); + private static final List<Aggregation> AGGREGATIONS_V1 = + Collections.unmodifiableList(Arrays.asList( + Sum.create(), Count.create(), Histogram.create(BUCKET_BOUNDARIES))); + + @Test + public void preventNullStartTime() { + thrown.expect(NullPointerException.class); + new IntervalBucket(null, MINUTE, AGGREGATIONS_V1); + } + + @Test + public void preventNullDuration() { + thrown.expect(NullPointerException.class); + new IntervalBucket(START, null, AGGREGATIONS_V1); + } + + @Test + public void preventNullAggregationList() { + thrown.expect(NullPointerException.class); + new IntervalBucket(START, MINUTE, null); + } + + @Test + public void testGetTagValueAggregationMap_empty() { + assertThat(new IntervalBucket(START, MINUTE, AGGREGATIONS_V1).getTagValueAggregationMap()) + .isEmpty(); + } + + @Test + public void testGetStart() { + assertThat(new IntervalBucket(START, MINUTE, AGGREGATIONS_V1).getStart()).isEqualTo(START); + } + + @Test + public void testRecord() { + IntervalBucket bucket = new IntervalBucket(START, MINUTE, AGGREGATIONS_V1); + List<TagValue> tagValues1 = Arrays.<TagValue>asList(TagValueString.create("VALUE1")); + List<TagValue> tagValues2 = Arrays.<TagValue>asList(TagValueString.create("VALUE2")); + bucket.record(tagValues1, 5.0); + bucket.record(tagValues1, 15.0); + bucket.record(tagValues2, 10.0); + assertThat(bucket.getTagValueAggregationMap()).containsKey(tagValues1); + verifyMutableAggregations(bucket.getTagValueAggregationMap().get(tagValues1), + 20.0, 2, new long[]{0, 0, 1, 1}, TOLERANCE); + assertThat(bucket.getTagValueAggregationMap()).containsKey(tagValues2); + verifyMutableAggregations(bucket.getTagValueAggregationMap().get(tagValues2), + 10.0, 1, new long[]{0, 0, 0, 1}, TOLERANCE); + } + + private static void verifyMutableAggregations( + List<MutableAggregation> aggregations, double sum, long count, long[] bucketCounts, + double tolerance) { + assertThat(aggregations).hasSize(3); + assertThat(aggregations.get(0)).isInstanceOf(MutableSum.class); + assertThat(((MutableSum) aggregations.get(0)).getSum()).isWithin(tolerance).of(sum); + assertThat(aggregations.get(1)).isInstanceOf(MutableCount.class); + assertThat(((MutableCount) aggregations.get(1)).getCount()).isEqualTo(count); + assertThat(aggregations.get(2)).isInstanceOf(MutableHistogram.class); + assertThat(((MutableHistogram) aggregations.get(2)).getBucketCounts()).isEqualTo(bucketCounts); + } + + @Test + public void testGetFraction() { + Timestamp thirtySecondsAfterStart = Timestamp.create(90, 0); + assertThat( + new IntervalBucket(START, MINUTE, AGGREGATIONS_V1).getFraction(thirtySecondsAfterStart)) + .isWithin(TOLERANCE).of(0.5); + } + + @Test + public void preventCallingGetFractionOnPastBuckets() { + IntervalBucket bucket = new IntervalBucket(START, MINUTE, AGGREGATIONS_V1); + Timestamp twoMinutesAfterStart = Timestamp.create(180, 0); + thrown.expect(IllegalArgumentException.class); + bucket.getFraction(twoMinutesAfterStart); + } + + @Test + public void preventCallingGetFractionOnFutureBuckets() { + IntervalBucket bucket = new IntervalBucket(START, MINUTE, AGGREGATIONS_V1); + Timestamp thirtySecondsBeforeStart = Timestamp.create(30, 0); + thrown.expect(IllegalArgumentException.class); + bucket.getFraction(thirtySecondsBeforeStart); + } +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar Binary files differindex cb893cbb..480539d4 100644 --- a/gradle/wrapper/gradle-wrapper.jar +++ b/gradle/wrapper/gradle-wrapper.jar diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1b1cd980..fc5988a7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,4 +1,4 @@ -#Tue Jul 11 16:36:46 PDT 2017 +#Sun Sep 03 20:39:13 PDT 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME |
