• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
getTagMap(TagContext ctx)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
getTagValues( Map<? extends TagKey, ? extends TagValue> tags, List<? extends TagKey> columns)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 view’s 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
createMutableAggregation( Aggregation aggregation, final Measure measure)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