2 * Copyright 2015 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #ifndef FOLLY_TIMESERIES_HISTOGRAM_DEF_H_
18 #define FOLLY_TIMESERIES_HISTOGRAM_DEF_H_
20 #include <folly/Conv.h>
21 #include <folly/stats/Histogram-defs.h>
22 #include <folly/stats/MultiLevelTimeSeries-defs.h>
23 #include <folly/stats/BucketedTimeSeries-defs.h>
27 template <class T, class TT, class C>
28 template <typename ReturnType>
29 ReturnType TimeseriesHistogram<T, TT, C>::avg(int level) const {
30 ValueType total = ValueType();
32 for (unsigned int b = 0; b < buckets_.getNumBuckets(); ++b) {
33 const auto& levelObj = buckets_.getByIndex(b).getLevel(level);
34 total += levelObj.sum();
35 nsamples += levelObj.count();
37 return folly::detail::avgHelper<ReturnType>(total, nsamples);
40 template <class T, class TT, class C>
41 template <typename ReturnType>
42 ReturnType TimeseriesHistogram<T, TT, C>::avg(TimeType start,
44 ValueType total = ValueType();
46 for (unsigned int b = 0; b < buckets_.getNumBuckets(); ++b) {
47 const auto& levelObj = buckets_.getByIndex(b).getLevel(start, end);
48 total += levelObj.sum(start, end);
49 nsamples += levelObj.count(start, end);
51 return folly::detail::avgHelper<ReturnType>(total, nsamples);
54 template <class T, class TT, class C>
55 template <typename ReturnType>
56 ReturnType TimeseriesHistogram<T, TT, C>::rate(TimeType start,
58 ValueType total = ValueType();
60 for (unsigned int b = 0; b < buckets_.getNumBuckets(); ++b) {
61 const auto& level = buckets_.getByIndex(b).getLevel(start);
62 total += level.sum(start, end);
63 elapsed = std::max(elapsed, level.elapsed(start, end));
65 return folly::detail::rateHelper<ReturnType, TimeType, TimeType>(
69 template <typename T, typename TT, typename C>
70 TimeseriesHistogram<T, TT, C>::TimeseriesHistogram(ValueType bucketSize,
73 const ContainerType& copyMe)
74 : buckets_(bucketSize, min, max, copyMe),
75 haveNotSeenValue_(true),
76 singleUniqueValue_(false) {
79 template <typename T, typename TT, typename C>
80 void TimeseriesHistogram<T, TT, C>::addValue(TimeType now,
81 const ValueType& value) {
82 buckets_.getByValue(value).addValue(now, value);
83 maybeHandleSingleUniqueValue(value);
86 template <typename T, typename TT, typename C>
87 void TimeseriesHistogram<T, TT, C>::addValue(TimeType now,
88 const ValueType& value,
90 buckets_.getByValue(value).addValue(now, value, times);
91 maybeHandleSingleUniqueValue(value);
94 template <typename T, typename TT, typename C>
95 void TimeseriesHistogram<T, TT, C>::addValues(
96 TimeType now, const folly::Histogram<ValueType>& hist) {
97 CHECK_EQ(hist.getMin(), getMin());
98 CHECK_EQ(hist.getMax(), getMax());
99 CHECK_EQ(hist.getBucketSize(), getBucketSize());
100 CHECK_EQ(hist.getNumBuckets(), getNumBuckets());
102 for (unsigned int n = 0; n < hist.getNumBuckets(); ++n) {
103 const typename folly::Histogram<ValueType>::Bucket& histBucket =
104 hist.getBucketByIndex(n);
105 Bucket& myBucket = buckets_.getByIndex(n);
106 myBucket.addValueAggregated(now, histBucket.sum, histBucket.count);
109 // We don't bother with the singleUniqueValue_ tracking.
110 haveNotSeenValue_ = false;
111 singleUniqueValue_ = false;
114 template <typename T, typename TT, typename C>
115 void TimeseriesHistogram<T, TT, C>::maybeHandleSingleUniqueValue(
116 const ValueType& value) {
117 if (haveNotSeenValue_) {
119 singleUniqueValue_ = true;
120 haveNotSeenValue_ = false;
121 } else if (singleUniqueValue_) {
122 if (value != firstValue_) {
123 singleUniqueValue_ = false;
128 template <typename T, typename TT, typename C>
129 T TimeseriesHistogram<T, TT, C>::getPercentileEstimate(double pct,
131 if (singleUniqueValue_) {
135 return buckets_.getPercentileEstimate(pct / 100.0, CountFromLevel(level),
136 AvgFromLevel(level));
139 template <typename T, typename TT, typename C>
140 T TimeseriesHistogram<T, TT, C>::getPercentileEstimate(double pct,
142 TimeType end) const {
143 if (singleUniqueValue_) {
147 return buckets_.getPercentileEstimate(pct / 100.0,
148 CountFromInterval(start, end),
149 AvgFromInterval<T>(start, end));
152 template <typename T, typename TT, typename C>
153 int TimeseriesHistogram<T, TT, C>::getPercentileBucketIdx(
157 return buckets_.getPercentileBucketIdx(pct / 100.0, CountFromLevel(level));
160 template <typename T, typename TT, typename C>
161 int TimeseriesHistogram<T, TT, C>::getPercentileBucketIdx(double pct,
163 TimeType end) const {
164 return buckets_.getPercentileBucketIdx(pct / 100.0,
165 CountFromInterval(start, end));
168 template <typename T, typename TT, typename C>
169 T TimeseriesHistogram<T, TT, C>::rate(int level) const {
170 ValueType total = ValueType();
172 for (unsigned int b = 0; b < buckets_.getNumBuckets(); ++b) {
173 const auto& levelObj = buckets_.getByIndex(b).getLevel(level);
174 total += levelObj.sum();
175 elapsed = std::max(elapsed, levelObj.elapsed());
177 return elapsed == TimeType(0) ? 0 : (total / elapsed.count());
180 template <typename T, typename TT, typename C>
181 void TimeseriesHistogram<T, TT, C>::clear() {
182 for (size_t i = 0; i < buckets_.getNumBuckets(); i++) {
183 buckets_.getByIndex(i).clear();
187 template <typename T, typename TT, typename C>
188 void TimeseriesHistogram<T, TT, C>::update(TimeType now) {
189 for (size_t i = 0; i < buckets_.getNumBuckets(); i++) {
190 buckets_.getByIndex(i).update(now);
194 template <typename T, typename TT, typename C>
195 std::string TimeseriesHistogram<T, TT, C>::getString(int level) const {
198 for (size_t i = 0; i < buckets_.getNumBuckets(); i++) {
200 toAppend(",", &result);
202 const ContainerType& cont = buckets_.getByIndex(i);
203 toAppend(buckets_.getBucketMin(i),
204 ":", cont.count(level),
205 ":", cont.template avg<ValueType>(level), &result);
211 template <typename T, typename TT, typename C>
212 std::string TimeseriesHistogram<T, TT, C>::getString(TimeType start,
213 TimeType end) const {
216 for (size_t i = 0; i < buckets_.getNumBuckets(); i++) {
218 toAppend(",", &result);
220 const ContainerType& cont = buckets_.getByIndex(i);
221 toAppend(buckets_.getBucketMin(i),
222 ":", cont.count(start, end),
223 ":", cont.avg(start, end), &result);