aboutsummaryrefslogtreecommitdiff
path: root/impl_core/src/test/java/io/opencensus/implcore/stats/StatsRecorderImplTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'impl_core/src/test/java/io/opencensus/implcore/stats/StatsRecorderImplTest.java')
-rw-r--r--impl_core/src/test/java/io/opencensus/implcore/stats/StatsRecorderImplTest.java349
1 files changed, 349 insertions, 0 deletions
diff --git a/impl_core/src/test/java/io/opencensus/implcore/stats/StatsRecorderImplTest.java b/impl_core/src/test/java/io/opencensus/implcore/stats/StatsRecorderImplTest.java
new file mode 100644
index 00000000..bd8b5b88
--- /dev/null
+++ b/impl_core/src/test/java/io/opencensus/implcore/stats/StatsRecorderImplTest.java
@@ -0,0 +1,349 @@
+/*
+ * 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 static io.opencensus.implcore.stats.MutableViewData.ZERO_TIMESTAMP;
+import static io.opencensus.implcore.stats.StatsTestUtil.createEmptyViewData;
+
+import com.google.common.collect.ImmutableMap;
+import io.grpc.Context;
+import io.opencensus.common.Duration;
+import io.opencensus.common.Timestamp;
+import io.opencensus.implcore.internal.SimpleEventQueue;
+import io.opencensus.implcore.stats.StatsTestUtil.SimpleTagContext;
+import io.opencensus.stats.Aggregation.Count;
+import io.opencensus.stats.Aggregation.Distribution;
+import io.opencensus.stats.Aggregation.Sum;
+import io.opencensus.stats.AggregationData.CountData;
+import io.opencensus.stats.AggregationData.DistributionData;
+import io.opencensus.stats.AggregationData.DistributionData.Exemplar;
+import io.opencensus.stats.BucketBoundaries;
+import io.opencensus.stats.Measure.MeasureDouble;
+import io.opencensus.stats.MeasureMap;
+import io.opencensus.stats.StatsCollectionState;
+import io.opencensus.stats.StatsComponent;
+import io.opencensus.stats.StatsRecorder;
+import io.opencensus.stats.View;
+import io.opencensus.stats.View.AggregationWindow.Cumulative;
+import io.opencensus.stats.ViewData;
+import io.opencensus.stats.ViewData.AggregationWindowData.CumulativeData;
+import io.opencensus.stats.ViewManager;
+import io.opencensus.tags.Tag;
+import io.opencensus.tags.TagContext;
+import io.opencensus.tags.TagKey;
+import io.opencensus.tags.TagValue;
+import io.opencensus.tags.unsafe.ContextUtils;
+import io.opencensus.testing.common.TestClock;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link StatsRecorderImpl}. */
+@RunWith(JUnit4.class)
+public final class StatsRecorderImplTest {
+ private static final TagKey KEY = TagKey.create("KEY");
+ private static final TagValue VALUE = TagValue.create("VALUE");
+ private static final TagValue VALUE_2 = TagValue.create("VALUE_2");
+ private static final MeasureDouble MEASURE_DOUBLE =
+ MeasureDouble.create("my measurement", "description", "us");
+ private static final MeasureDouble MEASURE_DOUBLE_NO_VIEW_1 =
+ MeasureDouble.create("my measurement no view 1", "description", "us");
+ private static final MeasureDouble MEASURE_DOUBLE_NO_VIEW_2 =
+ MeasureDouble.create("my measurement no view 2", "description", "us");
+ private static final View.Name VIEW_NAME = View.Name.create("my view");
+ private static final BucketBoundaries BUCKET_BOUNDARIES =
+ BucketBoundaries.create(Arrays.asList(-10.0, 0.0, 10.0));
+ private static final Distribution DISTRIBUTION = Distribution.create(BUCKET_BOUNDARIES);
+ private static final Distribution DISTRIBUTION_NO_HISTOGRAM =
+ Distribution.create(BucketBoundaries.create(Collections.<Double>emptyList()));
+ private static final Timestamp START_TIME = Timestamp.fromMillis(0);
+ private static final Duration ONE_SECOND = Duration.fromMillis(1000);
+
+ private final TestClock testClock = TestClock.create();
+ private final StatsComponent statsComponent =
+ new StatsComponentImplBase(new SimpleEventQueue(), testClock);
+
+ private final ViewManager viewManager = statsComponent.getViewManager();
+ private final StatsRecorder statsRecorder = statsComponent.getStatsRecorder();
+
+ @Test
+ public void record_CurrentContextNotSet() {
+ View view =
+ View.create(
+ VIEW_NAME,
+ "description",
+ MEASURE_DOUBLE,
+ Sum.create(),
+ Arrays.asList(KEY),
+ Cumulative.create());
+ viewManager.registerView(view);
+ statsRecorder.newMeasureMap().put(MEASURE_DOUBLE, 1.0).record();
+ ViewData viewData = viewManager.getView(VIEW_NAME);
+
+ // record() should have used the default TagContext, so the tag value should be null.
+ assertThat(viewData.getAggregationMap().keySet())
+ .containsExactly(Arrays.asList((TagValue) null));
+ }
+
+ @Test
+ public void record_CurrentContextSet() {
+ View view =
+ View.create(
+ VIEW_NAME,
+ "description",
+ MEASURE_DOUBLE,
+ Sum.create(),
+ Arrays.asList(KEY),
+ Cumulative.create());
+ viewManager.registerView(view);
+ Context orig =
+ Context.current()
+ .withValue(ContextUtils.TAG_CONTEXT_KEY, new SimpleTagContext(Tag.create(KEY, VALUE)))
+ .attach();
+ try {
+ statsRecorder.newMeasureMap().put(MEASURE_DOUBLE, 1.0).record();
+ } finally {
+ Context.current().detach(orig);
+ }
+ ViewData viewData = viewManager.getView(VIEW_NAME);
+
+ // record() should have used the given TagContext.
+ assertThat(viewData.getAggregationMap().keySet()).containsExactly(Arrays.asList(VALUE));
+ }
+
+ @Test
+ public void record_UnregisteredMeasure() {
+ View view =
+ View.create(
+ VIEW_NAME,
+ "description",
+ MEASURE_DOUBLE,
+ Sum.create(),
+ Arrays.asList(KEY),
+ Cumulative.create());
+ viewManager.registerView(view);
+ statsRecorder
+ .newMeasureMap()
+ .put(MEASURE_DOUBLE_NO_VIEW_1, 1.0)
+ .put(MEASURE_DOUBLE, 2.0)
+ .put(MEASURE_DOUBLE_NO_VIEW_2, 3.0)
+ .record(new SimpleTagContext(Tag.create(KEY, VALUE)));
+ ViewData viewData = viewManager.getView(VIEW_NAME);
+
+ // There should be one entry.
+ StatsTestUtil.assertAggregationMapEquals(
+ viewData.getAggregationMap(),
+ ImmutableMap.of(
+ Arrays.asList(VALUE),
+ StatsTestUtil.createAggregationData(Sum.create(), MEASURE_DOUBLE, 2.0)),
+ 1e-6);
+ }
+
+ @Test
+ public void record_WithAttachments_Distribution() {
+ testClock.setTime(START_TIME);
+ View view =
+ View.create(VIEW_NAME, "description", MEASURE_DOUBLE, DISTRIBUTION, Arrays.asList(KEY));
+ viewManager.registerView(view);
+ recordWithAttachments();
+ ViewData viewData = viewManager.getView(VIEW_NAME);
+ assertThat(viewData).isNotNull();
+ DistributionData distributionData =
+ (DistributionData) viewData.getAggregationMap().get(Collections.singletonList(VALUE));
+ List<Exemplar> expected =
+ Arrays.asList(
+ Exemplar.create(-20.0, Timestamp.create(4, 0), Collections.singletonMap("k3", "v1")),
+ Exemplar.create(-5.0, Timestamp.create(5, 0), Collections.singletonMap("k3", "v3")),
+ Exemplar.create(1.0, Timestamp.create(2, 0), Collections.singletonMap("k2", "v2")),
+ Exemplar.create(12.0, Timestamp.create(3, 0), Collections.singletonMap("k1", "v3")));
+ assertThat(distributionData.getExemplars()).containsExactlyElementsIn(expected).inOrder();
+ }
+
+ @Test
+ public void record_WithAttachments_DistributionNoHistogram() {
+ testClock.setTime(START_TIME);
+ View view =
+ View.create(
+ VIEW_NAME,
+ "description",
+ MEASURE_DOUBLE,
+ DISTRIBUTION_NO_HISTOGRAM,
+ Arrays.asList(KEY));
+ viewManager.registerView(view);
+ recordWithAttachments();
+ ViewData viewData = viewManager.getView(VIEW_NAME);
+ assertThat(viewData).isNotNull();
+ DistributionData distributionData =
+ (DistributionData) viewData.getAggregationMap().get(Collections.singletonList(VALUE));
+ // Recording exemplar has no effect if there's no histogram.
+ assertThat(distributionData.getExemplars()).isEmpty();
+ }
+
+ @Test
+ public void record_WithAttachments_Count() {
+ testClock.setTime(START_TIME);
+ View view =
+ View.create(VIEW_NAME, "description", MEASURE_DOUBLE, Count.create(), Arrays.asList(KEY));
+ viewManager.registerView(view);
+ recordWithAttachments();
+ ViewData viewData = viewManager.getView(VIEW_NAME);
+ assertThat(viewData).isNotNull();
+ CountData countData =
+ (CountData) viewData.getAggregationMap().get(Collections.singletonList(VALUE));
+ // Recording exemplar does not affect views with an aggregation other than distribution.
+ assertThat(countData.getCount()).isEqualTo(6L);
+ }
+
+ private void recordWithAttachments() {
+ TagContext context = new SimpleTagContext(Tag.create(KEY, VALUE));
+
+ // The test Distribution has bucket boundaries [-10.0, 0.0, 10.0].
+
+ testClock.advanceTime(ONE_SECOND); // 1st second.
+ // -1.0 is in the 2nd bucket [-10.0, 0.0).
+ statsRecorder
+ .newMeasureMap()
+ .put(MEASURE_DOUBLE, -1.0)
+ .putAttachment("k1", "v1")
+ .record(context);
+
+ testClock.advanceTime(ONE_SECOND); // 2nd second.
+ // 1.0 is in the 3rd bucket [0.0, 10.0).
+ statsRecorder
+ .newMeasureMap()
+ .put(MEASURE_DOUBLE, 1.0)
+ .putAttachment("k2", "v2")
+ .record(context);
+
+ testClock.advanceTime(ONE_SECOND); // 3rd second.
+ // 12.0 is in the 4th bucket [10.0, +Inf).
+ statsRecorder
+ .newMeasureMap()
+ .put(MEASURE_DOUBLE, 12.0)
+ .putAttachment("k1", "v3")
+ .record(context);
+
+ testClock.advanceTime(ONE_SECOND); // 4th second.
+ // -20.0 is in the 1st bucket [-Inf, -10.0).
+ statsRecorder
+ .newMeasureMap()
+ .put(MEASURE_DOUBLE, -20.0)
+ .putAttachment("k3", "v1")
+ .record(context);
+
+ testClock.advanceTime(ONE_SECOND); // 5th second.
+ // -5.0 is in the 2nd bucket [-10.0, 0), should overwrite the previous exemplar -1.0.
+ statsRecorder
+ .newMeasureMap()
+ .put(MEASURE_DOUBLE, -5.0)
+ .putAttachment("k3", "v3")
+ .record(context);
+
+ testClock.advanceTime(ONE_SECOND); // 6th second.
+ // -3.0 is in the 2nd bucket [-10.0, 0), but this value doesn't come with attachments, so it
+ // shouldn't overwrite the previous exemplar (-5.0).
+ statsRecorder.newMeasureMap().put(MEASURE_DOUBLE, -3.0).record(context);
+ }
+
+ @Test
+ public void recordTwice() {
+ View view =
+ View.create(
+ VIEW_NAME,
+ "description",
+ MEASURE_DOUBLE,
+ Sum.create(),
+ Arrays.asList(KEY),
+ Cumulative.create());
+ viewManager.registerView(view);
+ MeasureMap statsRecord = statsRecorder.newMeasureMap().put(MEASURE_DOUBLE, 1.0);
+ statsRecord.record(new SimpleTagContext(Tag.create(KEY, VALUE)));
+ statsRecord.record(new SimpleTagContext(Tag.create(KEY, VALUE_2)));
+ ViewData viewData = viewManager.getView(VIEW_NAME);
+
+ // There should be two entries.
+ StatsTestUtil.assertAggregationMapEquals(
+ viewData.getAggregationMap(),
+ ImmutableMap.of(
+ Arrays.asList(VALUE),
+ StatsTestUtil.createAggregationData(Sum.create(), MEASURE_DOUBLE, 1.0),
+ Arrays.asList(VALUE_2),
+ StatsTestUtil.createAggregationData(Sum.create(), MEASURE_DOUBLE, 1.0)),
+ 1e-6);
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ public void record_StatsDisabled() {
+ View view =
+ View.create(
+ VIEW_NAME,
+ "description",
+ MEASURE_DOUBLE,
+ Sum.create(),
+ Arrays.asList(KEY),
+ Cumulative.create());
+
+ viewManager.registerView(view);
+ statsComponent.setState(StatsCollectionState.DISABLED);
+ statsRecorder
+ .newMeasureMap()
+ .put(MEASURE_DOUBLE, 1.0)
+ .record(new SimpleTagContext(Tag.create(KEY, VALUE)));
+ assertThat(viewManager.getView(VIEW_NAME)).isEqualTo(createEmptyViewData(view));
+ }
+
+ @Test
+ @SuppressWarnings("deprecation")
+ public void record_StatsReenabled() {
+ View view =
+ View.create(
+ VIEW_NAME,
+ "description",
+ MEASURE_DOUBLE,
+ Sum.create(),
+ Arrays.asList(KEY),
+ Cumulative.create());
+ viewManager.registerView(view);
+
+ statsComponent.setState(StatsCollectionState.DISABLED);
+ statsRecorder
+ .newMeasureMap()
+ .put(MEASURE_DOUBLE, 1.0)
+ .record(new SimpleTagContext(Tag.create(KEY, VALUE)));
+ assertThat(viewManager.getView(VIEW_NAME)).isEqualTo(createEmptyViewData(view));
+
+ statsComponent.setState(StatsCollectionState.ENABLED);
+ assertThat(viewManager.getView(VIEW_NAME).getAggregationMap()).isEmpty();
+ assertThat(viewManager.getView(VIEW_NAME).getWindowData())
+ .isNotEqualTo(CumulativeData.create(ZERO_TIMESTAMP, ZERO_TIMESTAMP));
+ statsRecorder
+ .newMeasureMap()
+ .put(MEASURE_DOUBLE, 4.0)
+ .record(new SimpleTagContext(Tag.create(KEY, VALUE)));
+ StatsTestUtil.assertAggregationMapEquals(
+ viewManager.getView(VIEW_NAME).getAggregationMap(),
+ ImmutableMap.of(
+ Arrays.asList(VALUE),
+ StatsTestUtil.createAggregationData(Sum.create(), MEASURE_DOUBLE, 4.0)),
+ 1e-6);
+ }
+}