Java tutorial
/* * 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 com.google.common.collect.Iterables; import com.google.common.collect.Lists; import io.opencensus.common.Function; import io.opencensus.common.Functions; import io.opencensus.common.Timestamp; import io.opencensus.metrics.data.AttachmentValue; import io.opencensus.stats.Aggregation; import io.opencensus.stats.AggregationData; import io.opencensus.stats.AggregationData.CountData; import io.opencensus.stats.AggregationData.DistributionData; import io.opencensus.stats.AggregationData.LastValueDataDouble; import io.opencensus.stats.AggregationData.LastValueDataLong; import io.opencensus.stats.AggregationData.MeanData; import io.opencensus.stats.AggregationData.SumDataDouble; import io.opencensus.stats.AggregationData.SumDataLong; import io.opencensus.stats.Measure; import io.opencensus.stats.View; import io.opencensus.stats.ViewData; import io.opencensus.stats.ViewData.AggregationWindowData; import io.opencensus.stats.ViewData.AggregationWindowData.CumulativeData; import io.opencensus.stats.ViewData.AggregationWindowData.IntervalData; import io.opencensus.tags.Tag; import io.opencensus.tags.TagContext; import io.opencensus.tags.TagValue; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.annotation.Nullable; /** Stats test utilities. */ final class StatsTestUtil { private static final Timestamp EMPTY = Timestamp.create(0, 0); private StatsTestUtil() { } /** * Creates an {@link AggregationData} by adding the given sequence of values, based on the * definition of the given {@link Aggregation}. * * @param aggregation the {@code Aggregation} to apply the values to. * @param values the values to add to the {@code MutableAggregation}s. * @return an {@code AggregationData}. */ static AggregationData createAggregationData(Aggregation aggregation, Measure measure, double... values) { MutableAggregation mutableAggregation = RecordUtils.createMutableAggregation(aggregation, measure); for (double value : values) { mutableAggregation.add(value, Collections.<String, AttachmentValue>emptyMap(), EMPTY); } return mutableAggregation.toAggregationData(); } /** * Compare the actual and expected AggregationMap within the given tolerance. * * @param expected the expected map. * @param actual the actual mapping from {@code List<TagValue>} to {@code AggregationData}. * @param tolerance the tolerance used for {@code double} comparison. */ static void assertAggregationMapEquals( Map<? extends List<? extends TagValue>, ? extends AggregationData> actual, Map<? extends List<? extends TagValue>, ? extends AggregationData> expected, double tolerance) { assertThat(actual.keySet()).containsExactlyElementsIn(expected.keySet()); for (Entry<? extends List<? extends TagValue>, ? extends AggregationData> entry : actual.entrySet()) { assertAggregationDataEquals(expected.get(entry.getKey()), entry.getValue(), tolerance); } } /** * Compare the expected and actual {@code AggregationData} within the given tolerance. * * @param expected the expected {@code AggregationData}. * @param actual the actual {@code AggregationData}. * @param tolerance the tolerance used for {@code double} comparison. */ static void assertAggregationDataEquals(AggregationData expected, final AggregationData actual, final double tolerance) { expected.match(new Function<SumDataDouble, Void>() { @Override public Void apply(SumDataDouble arg) { assertThat(actual).isInstanceOf(SumDataDouble.class); assertThat(((SumDataDouble) actual).getSum()).isWithin(tolerance).of(arg.getSum()); return null; } }, new Function<SumDataLong, Void>() { @Override public Void apply(SumDataLong arg) { assertThat(actual).isInstanceOf(SumDataLong.class); assertThat(((SumDataLong) actual).getSum()).isEqualTo(arg.getSum()); return null; } }, new Function<CountData, Void>() { @Override public Void apply(CountData arg) { assertThat(actual).isInstanceOf(CountData.class); assertThat(((CountData) actual).getCount()).isEqualTo(arg.getCount()); return null; } }, new Function<DistributionData, Void>() { @Override public Void apply(DistributionData arg) { assertThat(actual).isInstanceOf(DistributionData.class); assertDistributionDataEquals(arg, (DistributionData) actual, tolerance); return null; } }, new Function<LastValueDataDouble, Void>() { @Override public Void apply(LastValueDataDouble arg) { assertThat(actual).isInstanceOf(LastValueDataDouble.class); assertThat(((LastValueDataDouble) actual).getLastValue()).isWithin(tolerance) .of(arg.getLastValue()); return null; } }, new Function<LastValueDataLong, Void>() { @Override public Void apply(LastValueDataLong arg) { assertThat(actual).isInstanceOf(LastValueDataLong.class); assertThat(((LastValueDataLong) actual).getLastValue()).isEqualTo(arg.getLastValue()); return null; } }, new Function<AggregationData, Void>() { @Override public Void apply(AggregationData arg) { if (arg instanceof MeanData) { assertThat(actual).isInstanceOf(MeanData.class); assertThat(((MeanData) actual).getMean()).isWithin(tolerance).of(((MeanData) arg).getMean()); return null; } throw new IllegalArgumentException("Unknown Aggregation."); } }); } // Create an empty ViewData with the given View. static ViewData createEmptyViewData(View view) { return ViewData.create(view, Collections.<List<TagValue>, AggregationData>emptyMap(), view.getWindow().match( Functions.<AggregationWindowData>returnConstant( CumulativeData.create(ZERO_TIMESTAMP, ZERO_TIMESTAMP)), Functions.<AggregationWindowData>returnConstant(IntervalData.create(ZERO_TIMESTAMP)), Functions.<AggregationWindowData>throwAssertionError())); } // Compare the expected and actual DistributionData within the given tolerance. private static void assertDistributionDataEquals(DistributionData expected, DistributionData actual, double tolerance) { assertThat(actual.getMean()).isWithin(tolerance).of(expected.getMean()); assertThat(actual.getCount()).isEqualTo(expected.getCount()); assertThat(actual.getMean()).isWithin(tolerance).of(expected.getMean()); assertThat(actual.getSumOfSquaredDeviations()).isWithin(tolerance).of(expected.getSumOfSquaredDeviations()); assertThat(removeTrailingZeros(actual.getBucketCounts())) .isEqualTo(removeTrailingZeros(expected.getBucketCounts())); } @Nullable private static List<Long> removeTrailingZeros(List<Long> longs) { if (longs == null) { return null; } List<Long> truncated = new ArrayList<Long>(longs); while (!truncated.isEmpty() && Iterables.getLast(truncated) == 0) { truncated.remove(truncated.size() - 1); } return truncated; } static final class SimpleTagContext extends TagContext { private final List<Tag> tags; SimpleTagContext(Tag... tags) { this.tags = Collections.unmodifiableList(Lists.newArrayList(tags)); } @Override protected Iterator<Tag> getIterator() { return tags.iterator(); } } }