1 /* 2 * Copyright 2017, 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 static com.google.common.base.Preconditions.checkArgument; 20 import static com.google.common.base.Preconditions.checkNotNull; 21 22 import com.google.common.collect.Maps; 23 import io.opencensus.common.Duration; 24 import io.opencensus.common.Timestamp; 25 import io.opencensus.metrics.data.AttachmentValue; 26 import io.opencensus.stats.Aggregation; 27 import io.opencensus.stats.Measure; 28 import io.opencensus.tags.TagValue; 29 import java.util.List; 30 import java.util.Map; 31 32 /*>>> 33 import org.checkerframework.checker.nullness.qual.Nullable; 34 */ 35 36 /** The bucket with aggregated {@code MeasureValue}s used for {@code IntervalViewData}. */ 37 final class IntervalBucket { 38 39 private static final Duration ZERO = Duration.create(0, 0); 40 41 private final Timestamp start; 42 private final Duration duration; 43 private final Aggregation aggregation; 44 private final Measure measure; 45 private final Map<List</*@Nullable*/ TagValue>, MutableAggregation> tagValueAggregationMap = 46 Maps.newHashMap(); 47 IntervalBucket(Timestamp start, Duration duration, Aggregation aggregation, Measure measure)48 IntervalBucket(Timestamp start, Duration duration, Aggregation aggregation, Measure measure) { 49 this.start = checkNotNull(start, "Start"); 50 this.duration = checkNotNull(duration, "Duration"); 51 checkArgument(duration.compareTo(ZERO) > 0, "Duration must be positive"); 52 this.aggregation = checkNotNull(aggregation, "Aggregation"); 53 this.measure = checkNotNull(measure, "measure"); 54 } 55 getTagValueAggregationMap()56 Map<List</*@Nullable*/ TagValue>, MutableAggregation> getTagValueAggregationMap() { 57 return tagValueAggregationMap; 58 } 59 getStart()60 Timestamp getStart() { 61 return start; 62 } 63 64 // Puts a new value into the internal MutableAggregations, based on the TagValues. record( List< TagValue> tagValues, double value, Map<String, AttachmentValue> attachments, Timestamp timestamp)65 void record( 66 List</*@Nullable*/ TagValue> tagValues, 67 double value, 68 Map<String, AttachmentValue> attachments, 69 Timestamp timestamp) { 70 if (!tagValueAggregationMap.containsKey(tagValues)) { 71 tagValueAggregationMap.put( 72 tagValues, RecordUtils.createMutableAggregation(aggregation, measure)); 73 } 74 tagValueAggregationMap.get(tagValues).add(value, attachments, timestamp); 75 } 76 77 /* 78 * Returns how much fraction of duration has passed in this IntervalBucket. For example, if this 79 * bucket starts at 10s and has a duration of 20s, and now is 15s, then getFraction() should 80 * return (15 - 10) / 20 = 0.25. 81 * 82 * This IntervalBucket must be current, i.e. the current timestamp must be within 83 * [this.start, this.start + this.duration). 84 */ getFraction(Timestamp now)85 double getFraction(Timestamp now) { 86 Duration elapsedTime = now.subtractTimestamp(start); 87 checkArgument( 88 elapsedTime.compareTo(ZERO) >= 0 && elapsedTime.compareTo(duration) < 0, 89 "This bucket must be current."); 90 return ((double) elapsedTime.toMillis()) / duration.toMillis(); 91 } 92 93 void clearStats() { 94 tagValueAggregationMap.clear(); 95 } 96 } 97