2 * Copyright 2016 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.
19 #include <folly/Conv.h>
20 #include <folly/stats/Histogram-defs.h>
21 #include <folly/stats/MultiLevelTimeSeries-defs.h>
22 #include <folly/stats/BucketedTimeSeries-defs.h>
26 template <class T, class TT, class C>
27 template <typename ReturnType>
28 ReturnType TimeseriesHistogram<T, TT, C>::avg(int level) const {
29 ValueType total = ValueType();
31 for (unsigned int b = 0; b < buckets_.getNumBuckets(); ++b) {
32 const auto& levelObj = buckets_.getByIndex(b).getLevel(level);
33 total += levelObj.sum();
34 nsamples += levelObj.count();
36 return folly::detail::avgHelper<ReturnType>(total, nsamples);
39 template <class T, class TT, class C>
40 template <typename ReturnType>
41 ReturnType TimeseriesHistogram<T, TT, C>::avg(TimeType start,
43 ValueType total = ValueType();
45 for (unsigned int b = 0; b < buckets_.getNumBuckets(); ++b) {
46 const auto& levelObj = buckets_.getByIndex(b).getLevel(start, end);
47 total += levelObj.sum(start, end);
48 nsamples += levelObj.count(start, end);
50 return folly::detail::avgHelper<ReturnType>(total, nsamples);
53 template <class T, class TT, class C>
54 template <typename ReturnType>
55 ReturnType TimeseriesHistogram<T, TT, C>::rate(TimeType start,
57 ValueType total = ValueType();
59 for (unsigned int b = 0; b < buckets_.getNumBuckets(); ++b) {
60 const auto& level = buckets_.getByIndex(b).getLevel(start);
61 total += level.sum(start, end);
62 elapsed = std::max(elapsed, level.elapsed(start, end));
64 return folly::detail::rateHelper<ReturnType, TimeType, TimeType>(
68 template <typename T, typename TT, typename C>
69 TimeseriesHistogram<T, TT, C>::TimeseriesHistogram(ValueType bucketSize,
72 const ContainerType& copyMe)
73 : buckets_(bucketSize, min, max, copyMe),
74 haveNotSeenValue_(true),
75 singleUniqueValue_(false) {
78 template <typename T, typename TT, typename C>
79 void TimeseriesHistogram<T, TT, C>::addValue(TimeType now,
80 const ValueType& value) {
81 buckets_.getByValue(value).addValue(now, value);
82 maybeHandleSingleUniqueValue(value);
85 template <typename T, typename TT, typename C>
86 void TimeseriesHistogram<T, TT, C>::addValue(TimeType now,
87 const ValueType& value,
89 buckets_.getByValue(value).addValue(now, value, times);
90 maybeHandleSingleUniqueValue(value);
93 template <typename T, typename TT, typename C>
94 void TimeseriesHistogram<T, TT, C>::addValues(
95 TimeType now, const folly::Histogram<ValueType>& hist) {
96 CHECK_EQ(hist.getMin(), getMin());
97 CHECK_EQ(hist.getMax(), getMax());
98 CHECK_EQ(hist.getBucketSize(), getBucketSize());
99 CHECK_EQ(hist.getNumBuckets(), getNumBuckets());
101 for (unsigned int n = 0; n < hist.getNumBuckets(); ++n) {
102 const typename folly::Histogram<ValueType>::Bucket& histBucket =
103 hist.getBucketByIndex(n);
104 Bucket& myBucket = buckets_.getByIndex(n);
105 myBucket.addValueAggregated(now, histBucket.sum, histBucket.count);
108 // We don't bother with the singleUniqueValue_ tracking.
109 haveNotSeenValue_ = false;
110 singleUniqueValue_ = false;
113 template <typename T, typename TT, typename C>
114 void TimeseriesHistogram<T, TT, C>::maybeHandleSingleUniqueValue(
115 const ValueType& value) {
116 if (haveNotSeenValue_) {
118 singleUniqueValue_ = true;
119 haveNotSeenValue_ = false;
120 } else if (singleUniqueValue_) {
121 if (value != firstValue_) {
122 singleUniqueValue_ = false;
127 template <typename T, typename TT, typename C>
128 T TimeseriesHistogram<T, TT, C>::getPercentileEstimate(double pct,
130 if (singleUniqueValue_) {
134 return buckets_.getPercentileEstimate(pct / 100.0, CountFromLevel(level),
135 AvgFromLevel(level));
138 template <typename T, typename TT, typename C>
139 T TimeseriesHistogram<T, TT, C>::getPercentileEstimate(double pct,
141 TimeType end) const {
142 if (singleUniqueValue_) {
146 return buckets_.getPercentileEstimate(pct / 100.0,
147 CountFromInterval(start, end),
148 AvgFromInterval<T>(start, end));
151 template <typename T, typename TT, typename C>
152 int TimeseriesHistogram<T, TT, C>::getPercentileBucketIdx(
156 return buckets_.getPercentileBucketIdx(pct / 100.0, CountFromLevel(level));
159 template <typename T, typename TT, typename C>
160 int TimeseriesHistogram<T, TT, C>::getPercentileBucketIdx(double pct,
162 TimeType end) const {
163 return buckets_.getPercentileBucketIdx(pct / 100.0,
164 CountFromInterval(start, end));
167 template <typename T, typename TT, typename C>
168 T TimeseriesHistogram<T, TT, C>::rate(int level) const {
169 ValueType total = ValueType();
171 for (unsigned int b = 0; b < buckets_.getNumBuckets(); ++b) {
172 const auto& levelObj = buckets_.getByIndex(b).getLevel(level);
173 total += levelObj.sum();
174 elapsed = std::max(elapsed, levelObj.elapsed());
176 return elapsed == TimeType(0) ? 0 : (total / elapsed.count());
179 template <typename T, typename TT, typename C>
180 void TimeseriesHistogram<T, TT, C>::clear() {
181 for (size_t i = 0; i < buckets_.getNumBuckets(); i++) {
182 buckets_.getByIndex(i).clear();
186 template <typename T, typename TT, typename C>
187 void TimeseriesHistogram<T, TT, C>::update(TimeType now) {
188 for (size_t i = 0; i < buckets_.getNumBuckets(); i++) {
189 buckets_.getByIndex(i).update(now);
193 template <typename T, typename TT, typename C>
194 std::string TimeseriesHistogram<T, TT, C>::getString(int level) const {
197 for (size_t i = 0; i < buckets_.getNumBuckets(); i++) {
199 toAppend(",", &result);
201 const ContainerType& cont = buckets_.getByIndex(i);
202 toAppend(buckets_.getBucketMin(i),
203 ":", cont.count(level),
204 ":", cont.template avg<ValueType>(level), &result);
210 template <typename T, typename TT, typename C>
211 std::string TimeseriesHistogram<T, TT, C>::getString(TimeType start,
212 TimeType end) const {
215 for (size_t i = 0; i < buckets_.getNumBuckets(); i++) {
217 toAppend(",", &result);
219 const ContainerType& cont = buckets_.getByIndex(i);
220 toAppend(buckets_.getBucketMin(i),
221 ":", cont.count(start, end),
222 ":", cont.avg(start, end), &result);