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 <typename T, typename CT, typename C>
27 TimeseriesHistogram<T, CT, C>::TimeseriesHistogram(
31 const ContainerType& copyMe)
32 : buckets_(bucketSize, min, max, copyMe),
33 haveNotSeenValue_(true),
34 singleUniqueValue_(false) {}
36 template <typename T, typename CT, typename C>
37 void TimeseriesHistogram<T, CT, C>::addValue(
39 const ValueType& value) {
40 buckets_.getByValue(value).addValue(now, value);
41 maybeHandleSingleUniqueValue(value);
44 template <typename T, typename CT, typename C>
45 void TimeseriesHistogram<T, CT, C>::addValue(
47 const ValueType& value,
49 buckets_.getByValue(value).addValue(now, value, times);
50 maybeHandleSingleUniqueValue(value);
53 template <typename T, typename CT, typename C>
54 void TimeseriesHistogram<T, CT, C>::addValues(
56 const folly::Histogram<ValueType>& hist) {
57 CHECK_EQ(hist.getMin(), getMin());
58 CHECK_EQ(hist.getMax(), getMax());
59 CHECK_EQ(hist.getBucketSize(), getBucketSize());
60 CHECK_EQ(hist.getNumBuckets(), getNumBuckets());
62 for (unsigned int n = 0; n < hist.getNumBuckets(); ++n) {
63 const typename folly::Histogram<ValueType>::Bucket& histBucket =
64 hist.getBucketByIndex(n);
65 Bucket& myBucket = buckets_.getByIndex(n);
66 myBucket.addValueAggregated(now, histBucket.sum, histBucket.count);
69 // We don't bother with the singleUniqueValue_ tracking.
70 haveNotSeenValue_ = false;
71 singleUniqueValue_ = false;
74 template <typename T, typename CT, typename C>
75 void TimeseriesHistogram<T, CT, C>::maybeHandleSingleUniqueValue(
76 const ValueType& value) {
77 if (haveNotSeenValue_) {
79 singleUniqueValue_ = true;
80 haveNotSeenValue_ = false;
81 } else if (singleUniqueValue_) {
82 if (value != firstValue_) {
83 singleUniqueValue_ = false;
88 template <typename T, typename CT, typename C>
89 T TimeseriesHistogram<T, CT, C>::getPercentileEstimate(double pct, int level)
91 if (singleUniqueValue_) {
95 return buckets_.getPercentileEstimate(pct / 100.0, CountFromLevel(level),
99 template <typename T, typename CT, typename C>
100 T TimeseriesHistogram<T, CT, C>::getPercentileEstimate(
103 TimeType end) const {
104 if (singleUniqueValue_) {
108 return buckets_.getPercentileEstimate(pct / 100.0,
109 CountFromInterval(start, end),
110 AvgFromInterval<T>(start, end));
113 template <typename T, typename CT, typename C>
114 int TimeseriesHistogram<T, CT, C>::getPercentileBucketIdx(double pct, int level)
116 return buckets_.getPercentileBucketIdx(pct / 100.0, CountFromLevel(level));
119 template <typename T, typename CT, typename C>
120 int TimeseriesHistogram<T, CT, C>::getPercentileBucketIdx(
123 TimeType end) const {
124 return buckets_.getPercentileBucketIdx(pct / 100.0,
125 CountFromInterval(start, end));
128 template <typename T, typename CT, typename C>
129 void TimeseriesHistogram<T, CT, C>::clear() {
130 for (size_t i = 0; i < buckets_.getNumBuckets(); i++) {
131 buckets_.getByIndex(i).clear();
135 template <typename T, typename CT, typename C>
136 void TimeseriesHistogram<T, CT, C>::update(TimeType now) {
137 for (size_t i = 0; i < buckets_.getNumBuckets(); i++) {
138 buckets_.getByIndex(i).update(now);
142 template <typename T, typename CT, typename C>
143 std::string TimeseriesHistogram<T, CT, C>::getString(int level) const {
146 for (size_t i = 0; i < buckets_.getNumBuckets(); i++) {
148 toAppend(",", &result);
150 const ContainerType& cont = buckets_.getByIndex(i);
151 toAppend(buckets_.getBucketMin(i),
152 ":", cont.count(level),
153 ":", cont.template avg<ValueType>(level), &result);
159 template <typename T, typename CT, typename C>
160 std::string TimeseriesHistogram<T, CT, C>::getString(
162 TimeType end) const {
165 for (size_t i = 0; i < buckets_.getNumBuckets(); i++) {
167 toAppend(",", &result);
169 const ContainerType& cont = buckets_.getByIndex(i);
170 toAppend(buckets_.getBucketMin(i),
171 ":", cont.count(start, end),
172 ":", cont.avg(start, end), &result);
178 template <class T, class CT, class C>
179 void TimeseriesHistogram<T, CT, C>::computeAvgData(
183 for (unsigned int b = 0; b < buckets_.getNumBuckets(); ++b) {
184 const auto& levelObj = buckets_.getByIndex(b).getLevel(level);
185 *total += levelObj.sum();
186 *nsamples += levelObj.count();
190 template <class T, class CT, class C>
191 void TimeseriesHistogram<T, CT, C>::computeAvgData(
195 TimeType end) const {
196 for (unsigned int b = 0; b < buckets_.getNumBuckets(); ++b) {
197 const auto& levelObj = buckets_.getByIndex(b).getLevel(start);
198 *total += levelObj.sum(start, end);
199 *nsamples += levelObj.count(start, end);
203 template <typename T, typename CT, typename C>
204 void TimeseriesHistogram<T, CT, C>::computeRateData(
208 for (unsigned int b = 0; b < buckets_.getNumBuckets(); ++b) {
209 const auto& levelObj = buckets_.getByIndex(b).getLevel(level);
210 *total += levelObj.sum();
211 *elapsed = std::max(*elapsed, levelObj.elapsed());
215 template <class T, class CT, class C>
216 void TimeseriesHistogram<T, CT, C>::computeRateData(
220 TimeType end) const {
221 for (unsigned int b = 0; b < buckets_.getNumBuckets(); ++b) {
222 const auto& level = buckets_.getByIndex(b).getLevel(start);
223 *total += level.sum(start, end);
224 *elapsed = std::max(*elapsed, level.elapsed(start, end));