1 /* 2 * Copyright 2016-17, 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.stats; 18 19 import com.google.auto.value.AutoValue; 20 import io.opencensus.common.Duration; 21 import io.opencensus.common.Function; 22 import io.opencensus.internal.DefaultVisibilityForTesting; 23 import io.opencensus.internal.StringUtils; 24 import io.opencensus.internal.Utils; 25 import io.opencensus.tags.TagKey; 26 import java.util.ArrayList; 27 import java.util.Collections; 28 import java.util.Comparator; 29 import java.util.HashSet; 30 import java.util.List; 31 import javax.annotation.concurrent.Immutable; 32 33 /** 34 * A View specifies an aggregation and a set of tag keys. The aggregation will be broken down by the 35 * unique set of matching tag values for each measure. 36 * 37 * @since 0.8 38 */ 39 @Immutable 40 @AutoValue 41 @AutoValue.CopyAnnotations 42 @SuppressWarnings("deprecation") 43 public abstract class View { 44 45 @DefaultVisibilityForTesting static final int NAME_MAX_LENGTH = 255; 46 47 private static final Comparator<TagKey> TAG_KEY_COMPARATOR = 48 new Comparator<TagKey>() { 49 @Override 50 public int compare(TagKey key1, TagKey key2) { 51 return key1.getName().compareTo(key2.getName()); 52 } 53 }; 54 View()55 View() {} 56 57 /** 58 * Name of view. Must be unique. 59 * 60 * @since 0.8 61 */ getName()62 public abstract Name getName(); 63 64 /** 65 * More detailed description, for documentation purposes. 66 * 67 * @since 0.8 68 */ getDescription()69 public abstract String getDescription(); 70 71 /** 72 * Measure type of this view. 73 * 74 * @since 0.8 75 */ getMeasure()76 public abstract Measure getMeasure(); 77 78 /** 79 * The {@link Aggregation} associated with this {@link View}. 80 * 81 * @since 0.8 82 */ getAggregation()83 public abstract Aggregation getAggregation(); 84 85 /** 86 * Columns (a.k.a Tag Keys) to match with the associated {@link Measure}. 87 * 88 * <p>{@link Measure} will be recorded in a "greedy" way. That is, every view aggregates every 89 * measure. This is similar to doing a GROUPBY on view’s columns. Columns must be unique. 90 * 91 * @since 0.8 92 */ getColumns()93 public abstract List<TagKey> getColumns(); 94 95 /** 96 * Returns the time {@link AggregationWindow} for this {@code View}. 97 * 98 * @return the time {@link AggregationWindow}. 99 * @since 0.8 100 * @deprecated since 0.13. In the future all {@link View}s will be cumulative. 101 */ 102 @Deprecated getWindow()103 public abstract AggregationWindow getWindow(); 104 105 /** 106 * Constructs a new {@link View}. 107 * 108 * @param name the {@link Name} of view. Must be unique. 109 * @param description the description of view. 110 * @param measure the {@link Measure} to be aggregated by this view. 111 * @param aggregation the basic {@link Aggregation} that this view will support. 112 * @param columns the {@link TagKey}s that this view will aggregate on. Columns should not contain 113 * duplicates. 114 * @param window the {@link AggregationWindow} of view. 115 * @return a new {@link View}. 116 * @since 0.8 117 * @deprecated in favor of {@link #create(Name, String, Measure, Aggregation, List)}. 118 */ 119 @Deprecated create( Name name, String description, Measure measure, Aggregation aggregation, List<TagKey> columns, AggregationWindow window)120 public static View create( 121 Name name, 122 String description, 123 Measure measure, 124 Aggregation aggregation, 125 List<TagKey> columns, 126 AggregationWindow window) { 127 Utils.checkArgument( 128 new HashSet<TagKey>(columns).size() == columns.size(), "Columns have duplicate."); 129 130 List<TagKey> tagKeys = new ArrayList<TagKey>(columns); 131 Collections.sort(tagKeys, TAG_KEY_COMPARATOR); 132 return new AutoValue_View( 133 name, description, measure, aggregation, Collections.unmodifiableList(tagKeys), window); 134 } 135 136 /** 137 * Constructs a new {@link View}. 138 * 139 * @param name the {@link Name} of view. Must be unique. 140 * @param description the description of view. 141 * @param measure the {@link Measure} to be aggregated by this view. 142 * @param aggregation the basic {@link Aggregation} that this view will support. 143 * @param columns the {@link TagKey}s that this view will aggregate on. Columns should not contain 144 * duplicates. 145 * @return a new {@link View}. 146 * @since 0.13 147 */ create( Name name, String description, Measure measure, Aggregation aggregation, List<TagKey> columns)148 public static View create( 149 Name name, 150 String description, 151 Measure measure, 152 Aggregation aggregation, 153 List<TagKey> columns) { 154 Utils.checkArgument( 155 new HashSet<TagKey>(columns).size() == columns.size(), "Columns have duplicate."); 156 return create( 157 name, description, measure, aggregation, columns, AggregationWindow.Cumulative.create()); 158 } 159 160 /** 161 * The name of a {@code View}. 162 * 163 * @since 0.8 164 */ 165 // This type should be used as the key when associating data with Views. 166 @Immutable 167 @AutoValue 168 public abstract static class Name { 169 Name()170 Name() {} 171 172 /** 173 * Returns the name as a {@code String}. 174 * 175 * @return the name as a {@code String}. 176 * @since 0.8 177 */ asString()178 public abstract String asString(); 179 180 /** 181 * Creates a {@code View.Name} from a {@code String}. Should be a ASCII string with a length no 182 * greater than 255 characters. 183 * 184 * <p>Suggested format for name: {@code <web_host>/<path>}. 185 * 186 * @param name the name {@code String}. 187 * @return a {@code View.Name} with the given name {@code String}. 188 * @since 0.8 189 */ create(String name)190 public static Name create(String name) { 191 Utils.checkArgument( 192 StringUtils.isPrintableString(name) && name.length() <= NAME_MAX_LENGTH, 193 "Name should be a ASCII string with a length no greater than 255 characters."); 194 return new AutoValue_View_Name(name); 195 } 196 } 197 198 /** 199 * The time window for a {@code View}. 200 * 201 * @since 0.8 202 * @deprecated since 0.13. In the future all {@link View}s will be cumulative. 203 */ 204 @Deprecated 205 @Immutable 206 public abstract static class AggregationWindow { 207 AggregationWindow()208 private AggregationWindow() {} 209 210 /** 211 * Applies the given match function to the underlying data type. 212 * 213 * @since 0.8 214 */ match( Function<? super Cumulative, T> p0, Function<? super Interval, T> p1, Function<? super AggregationWindow, T> defaultFunction)215 public abstract <T> T match( 216 Function<? super Cumulative, T> p0, 217 Function<? super Interval, T> p1, 218 Function<? super AggregationWindow, T> defaultFunction); 219 220 /** 221 * Cumulative (infinite interval) time {@code AggregationWindow}. 222 * 223 * @since 0.8 224 * @deprecated since 0.13. In the future all {@link View}s will be cumulative. 225 */ 226 @Deprecated 227 @Immutable 228 @AutoValue 229 @AutoValue.CopyAnnotations 230 public abstract static class Cumulative extends AggregationWindow { 231 232 private static final Cumulative CUMULATIVE = 233 new AutoValue_View_AggregationWindow_Cumulative(); 234 Cumulative()235 Cumulative() {} 236 237 /** 238 * Constructs a cumulative {@code AggregationWindow} that does not have an explicit {@code 239 * Duration}. Instead, cumulative {@code AggregationWindow} always has an interval of infinite 240 * {@code Duration}. 241 * 242 * @return a cumulative {@code AggregationWindow}. 243 * @since 0.8 244 */ create()245 public static Cumulative create() { 246 return CUMULATIVE; 247 } 248 249 @Override match( Function<? super Cumulative, T> p0, Function<? super Interval, T> p1, Function<? super AggregationWindow, T> defaultFunction)250 public final <T> T match( 251 Function<? super Cumulative, T> p0, 252 Function<? super Interval, T> p1, 253 Function<? super AggregationWindow, T> defaultFunction) { 254 return p0.apply(this); 255 } 256 } 257 258 /** 259 * Interval (finite interval) time {@code AggregationWindow}. 260 * 261 * @since 0.8 262 * @deprecated since 0.13. In the future all {@link View}s will be cumulative. 263 */ 264 @Deprecated 265 @Immutable 266 @AutoValue 267 @AutoValue.CopyAnnotations 268 public abstract static class Interval extends AggregationWindow { 269 270 private static final Duration ZERO = Duration.create(0, 0); 271 Interval()272 Interval() {} 273 274 /** 275 * Returns the {@code Duration} associated with this {@code Interval}. 276 * 277 * @return a {@code Duration}. 278 * @since 0.8 279 */ getDuration()280 public abstract Duration getDuration(); 281 282 /** 283 * Constructs an interval {@code AggregationWindow} that has a finite explicit {@code 284 * Duration}. 285 * 286 * <p>The {@code Duration} should be able to round to milliseconds. Currently interval window 287 * cannot have smaller {@code Duration} such as microseconds or nanoseconds. 288 * 289 * @return an interval {@code AggregationWindow}. 290 * @since 0.8 291 */ create(Duration duration)292 public static Interval create(Duration duration) { 293 Utils.checkArgument(duration.compareTo(ZERO) > 0, "Duration must be positive"); 294 return new AutoValue_View_AggregationWindow_Interval(duration); 295 } 296 297 @Override match( Function<? super Cumulative, T> p0, Function<? super Interval, T> p1, Function<? super AggregationWindow, T> defaultFunction)298 public final <T> T match( 299 Function<? super Cumulative, T> p0, 300 Function<? super Interval, T> p1, 301 Function<? super AggregationWindow, T> defaultFunction) { 302 return p1.apply(this); 303 } 304 } 305 } 306 } 307