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