Home | History | Annotate | Download | only in stats
      1 /*
      2  * Copyright 2018, OpenCensus Authors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package io.opencensus.implcore.stats;
     18 
     19 import com.google.common.annotations.VisibleForTesting;
     20 import com.google.common.collect.Maps;
     21 import io.opencensus.common.Function;
     22 import io.opencensus.common.Functions;
     23 import io.opencensus.implcore.stats.MutableAggregation.MutableCount;
     24 import io.opencensus.implcore.stats.MutableAggregation.MutableDistribution;
     25 import io.opencensus.implcore.stats.MutableAggregation.MutableLastValueDouble;
     26 import io.opencensus.implcore.stats.MutableAggregation.MutableLastValueLong;
     27 import io.opencensus.implcore.stats.MutableAggregation.MutableMean;
     28 import io.opencensus.implcore.stats.MutableAggregation.MutableSumDouble;
     29 import io.opencensus.implcore.stats.MutableAggregation.MutableSumLong;
     30 import io.opencensus.implcore.tags.TagContextImpl;
     31 import io.opencensus.stats.Aggregation;
     32 import io.opencensus.stats.Aggregation.Count;
     33 import io.opencensus.stats.Aggregation.Distribution;
     34 import io.opencensus.stats.Aggregation.LastValue;
     35 import io.opencensus.stats.Aggregation.Sum;
     36 import io.opencensus.stats.AggregationData;
     37 import io.opencensus.stats.Measure;
     38 import io.opencensus.stats.Measure.MeasureDouble;
     39 import io.opencensus.stats.Measure.MeasureLong;
     40 import io.opencensus.stats.Measurement;
     41 import io.opencensus.stats.Measurement.MeasurementDouble;
     42 import io.opencensus.stats.Measurement.MeasurementLong;
     43 import io.opencensus.tags.InternalUtils;
     44 import io.opencensus.tags.Tag;
     45 import io.opencensus.tags.TagContext;
     46 import io.opencensus.tags.TagKey;
     47 import io.opencensus.tags.TagValue;
     48 import java.util.ArrayList;
     49 import java.util.Iterator;
     50 import java.util.List;
     51 import java.util.Map;
     52 import java.util.Map.Entry;
     53 
     54 /*>>>
     55 import org.checkerframework.checker.nullness.qual.Nullable;
     56 */
     57 
     58 @SuppressWarnings("deprecation")
     59 /* Common static utilities for stats recording. */
     60 final class RecordUtils {
     61 
     62   @javax.annotation.Nullable @VisibleForTesting static final TagValue UNKNOWN_TAG_VALUE = null;
     63 
     64   static Map<TagKey, TagValue> getTagMap(TagContext ctx) {
     65     if (ctx instanceof TagContextImpl) {
     66       return ((TagContextImpl) ctx).getTags();
     67     } else {
     68       Map<TagKey, TagValue> tags = Maps.newHashMap();
     69       for (Iterator<Tag> i = InternalUtils.getTags(ctx); i.hasNext(); ) {
     70         Tag tag = i.next();
     71         tags.put(tag.getKey(), tag.getValue());
     72       }
     73       return tags;
     74     }
     75   }
     76 
     77   @VisibleForTesting
     78   static List</*@Nullable*/ TagValue> getTagValues(
     79       Map<? extends TagKey, ? extends TagValue> tags, List<? extends TagKey> columns) {
     80     List</*@Nullable*/ TagValue> tagValues = new ArrayList</*@Nullable*/ TagValue>(columns.size());
     81     // Record all the measures in a "Greedy" way.
     82     // Every view aggregates every measure. This is similar to doing a GROUPBY views keys.
     83     for (int i = 0; i < columns.size(); ++i) {
     84       TagKey tagKey = columns.get(i);
     85       if (!tags.containsKey(tagKey)) {
     86         // replace not found key values by null.
     87         tagValues.add(UNKNOWN_TAG_VALUE);
     88       } else {
     89         tagValues.add(tags.get(tagKey));
     90       }
     91     }
     92     return tagValues;
     93   }
     94 
     95   /**
     96    * Create an empty {@link MutableAggregation} based on the given {@link Aggregation}.
     97    *
     98    * @param aggregation {@code Aggregation}.
     99    * @return an empty {@code MutableAggregation}.
    100    */
    101   @VisibleForTesting
    102   static MutableAggregation createMutableAggregation(
    103       Aggregation aggregation, final Measure measure) {
    104     return aggregation.match(
    105         new Function<Sum, MutableAggregation>() {
    106           @Override
    107           public MutableAggregation apply(Sum arg) {
    108             return measure.match(
    109                 CreateMutableSumDouble.INSTANCE,
    110                 CreateMutableSumLong.INSTANCE,
    111                 Functions.<MutableAggregation>throwAssertionError());
    112           }
    113         },
    114         CreateMutableCount.INSTANCE,
    115         CreateMutableDistribution.INSTANCE,
    116         new Function<LastValue, MutableAggregation>() {
    117           @Override
    118           public MutableAggregation apply(LastValue arg) {
    119             return measure.match(
    120                 CreateMutableLastValueDouble.INSTANCE,
    121                 CreateMutableLastValueLong.INSTANCE,
    122                 Functions.<MutableAggregation>throwAssertionError());
    123           }
    124         },
    125         AggregationDefaultFunction.INSTANCE);
    126   }
    127 
    128   // Covert a mapping from TagValues to MutableAggregation, to a mapping from TagValues to
    129   // AggregationData.
    130   static <T> Map<T, AggregationData> createAggregationMap(
    131       Map<T, MutableAggregation> tagValueAggregationMap, Measure measure) {
    132     Map<T, AggregationData> map = Maps.newHashMap();
    133     for (Entry<T, MutableAggregation> entry : tagValueAggregationMap.entrySet()) {
    134       map.put(entry.getKey(), entry.getValue().toAggregationData());
    135     }
    136     return map;
    137   }
    138 
    139   static double getDoubleValueFromMeasurement(Measurement measurement) {
    140     return measurement.match(
    141         GET_VALUE_FROM_MEASUREMENT_DOUBLE,
    142         GET_VALUE_FROM_MEASUREMENT_LONG,
    143         Functions.<Double>throwAssertionError());
    144   }
    145 
    146   // static inner Function classes
    147 
    148   private static final Function<MeasurementDouble, Double> GET_VALUE_FROM_MEASUREMENT_DOUBLE =
    149       new Function<MeasurementDouble, Double>() {
    150         @Override
    151         public Double apply(MeasurementDouble arg) {
    152           return arg.getValue();
    153         }
    154       };
    155 
    156   private static final Function<MeasurementLong, Double> GET_VALUE_FROM_MEASUREMENT_LONG =
    157       new Function<MeasurementLong, Double>() {
    158         @Override
    159         public Double apply(MeasurementLong arg) {
    160           // TODO: consider checking truncation here.
    161           return (double) arg.getValue();
    162         }
    163       };
    164 
    165   private static final class CreateMutableSumDouble
    166       implements Function<MeasureDouble, MutableAggregation> {
    167     @Override
    168     public MutableAggregation apply(MeasureDouble arg) {
    169       return MutableSumDouble.create();
    170     }
    171 
    172     private static final CreateMutableSumDouble INSTANCE = new CreateMutableSumDouble();
    173   }
    174 
    175   private static final class CreateMutableSumLong
    176       implements Function<MeasureLong, MutableAggregation> {
    177     @Override
    178     public MutableAggregation apply(MeasureLong arg) {
    179       return MutableSumLong.create();
    180     }
    181 
    182     private static final CreateMutableSumLong INSTANCE = new CreateMutableSumLong();
    183   }
    184 
    185   private static final class CreateMutableCount implements Function<Count, MutableAggregation> {
    186     @Override
    187     public MutableAggregation apply(Count arg) {
    188       return MutableCount.create();
    189     }
    190 
    191     private static final CreateMutableCount INSTANCE = new CreateMutableCount();
    192   }
    193 
    194   // TODO(songya): remove this once Mean aggregation is completely removed. Before that
    195   // we need to continue supporting Mean, since it could still be used by users and some
    196   // deprecated RPC views.
    197   private static final class AggregationDefaultFunction
    198       implements Function<Aggregation, MutableAggregation> {
    199     @Override
    200     public MutableAggregation apply(Aggregation arg) {
    201       if (arg instanceof Aggregation.Mean) {
    202         return MutableMean.create();
    203       }
    204       throw new IllegalArgumentException("Unknown Aggregation.");
    205     }
    206 
    207     private static final AggregationDefaultFunction INSTANCE = new AggregationDefaultFunction();
    208   }
    209 
    210   private static final class CreateMutableDistribution
    211       implements Function<Distribution, MutableAggregation> {
    212     @Override
    213     public MutableAggregation apply(Distribution arg) {
    214       return MutableDistribution.create(arg.getBucketBoundaries());
    215     }
    216 
    217     private static final CreateMutableDistribution INSTANCE = new CreateMutableDistribution();
    218   }
    219 
    220   private static final class CreateMutableLastValueDouble
    221       implements Function<MeasureDouble, MutableAggregation> {
    222     @Override
    223     public MutableAggregation apply(MeasureDouble arg) {
    224       return MutableLastValueDouble.create();
    225     }
    226 
    227     private static final CreateMutableLastValueDouble INSTANCE = new CreateMutableLastValueDouble();
    228   }
    229 
    230   private static final class CreateMutableLastValueLong
    231       implements Function<MeasureLong, MutableAggregation> {
    232     @Override
    233     public MutableAggregation apply(MeasureLong arg) {
    234       return MutableLastValueLong.create();
    235     }
    236 
    237     private static final CreateMutableLastValueLong INSTANCE = new CreateMutableLastValueLong();
    238   }
    239 
    240   private RecordUtils() {}
    241 }
    242