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 TT, typename C>
27 TimeseriesHistogram<T, TT, C>::TimeseriesHistogram(ValueType bucketSize,
30 const ContainerType& copyMe)
31 : buckets_(bucketSize, min, max, copyMe),
32 haveNotSeenValue_(true),
33 singleUniqueValue_(false) {
36 template <typename T, typename TT, typename C>
37 void TimeseriesHistogram<T, TT, C>::addValue(TimeType now,
38 const ValueType& value) {
39 buckets_.getByValue(value).addValue(now, value);
40 maybeHandleSingleUniqueValue(value);
43 template <typename T, typename TT, typename C>
44 void TimeseriesHistogram<T, TT, C>::addValue(TimeType now,
45 const ValueType& value,
47 buckets_.getByValue(value).addValue(now, value, times);
48 maybeHandleSingleUniqueValue(value);
51 template <typename T, typename TT, typename C>
52 void TimeseriesHistogram<T, TT, C>::addValues(
53 TimeType now, const folly::Histogram<ValueType>& hist) {
54 CHECK_EQ(hist.getMin(), getMin());
55 CHECK_EQ(hist.getMax(), getMax());
56 CHECK_EQ(hist.getBucketSize(), getBucketSize());
57 CHECK_EQ(hist.getNumBuckets(), getNumBuckets());
59 for (unsigned int n = 0; n < hist.getNumBuckets(); ++n) {
60 const typename folly::Histogram<ValueType>::Bucket& histBucket =
61 hist.getBucketByIndex(n);
62 Bucket& myBucket = buckets_.getByIndex(n);
63 myBucket.addValueAggregated(now, histBucket.sum, histBucket.count);
66 // We don't bother with the singleUniqueValue_ tracking.
67 haveNotSeenValue_ = false;
68 singleUniqueValue_ = false;
71 template <typename T, typename TT, typename C>
72 void TimeseriesHistogram<T, TT, C>::maybeHandleSingleUniqueValue(
73 const ValueType& value) {
74 if (haveNotSeenValue_) {
76 singleUniqueValue_ = true;
77 haveNotSeenValue_ = false;
78 } else if (singleUniqueValue_) {
79 if (value != firstValue_) {
80 singleUniqueValue_ = false;
85 template <typename T, typename TT, typename C>
86 T TimeseriesHistogram<T, TT, C>::getPercentileEstimate(double pct,
88 if (singleUniqueValue_) {
92 return buckets_.getPercentileEstimate(pct / 100.0, CountFromLevel(level),
96 template <typename T, typename TT, typename C>
97 T TimeseriesHistogram<T, TT, C>::getPercentileEstimate(double pct,
100 if (singleUniqueValue_) {
104 return buckets_.getPercentileEstimate(pct / 100.0,
105 CountFromInterval(start, end),
106 AvgFromInterval<T>(start, end));
109 template <typename T, typename TT, typename C>
110 int TimeseriesHistogram<T, TT, C>::getPercentileBucketIdx(
114 return buckets_.getPercentileBucketIdx(pct / 100.0, CountFromLevel(level));
117 template <typename T, typename TT, typename C>
118 int TimeseriesHistogram<T, TT, C>::getPercentileBucketIdx(double pct,
120 TimeType end) const {
121 return buckets_.getPercentileBucketIdx(pct / 100.0,
122 CountFromInterval(start, end));
125 template <typename T, typename TT, typename C>
126 void TimeseriesHistogram<T, TT, C>::clear() {
127 for (size_t i = 0; i < buckets_.getNumBuckets(); i++) {
128 buckets_.getByIndex(i).clear();
132 template <typename T, typename TT, typename C>
133 void TimeseriesHistogram<T, TT, C>::update(TimeType now) {
134 for (size_t i = 0; i < buckets_.getNumBuckets(); i++) {
135 buckets_.getByIndex(i).update(now);
139 template <typename T, typename TT, typename C>
140 std::string TimeseriesHistogram<T, TT, C>::getString(int level) const {
143 for (size_t i = 0; i < buckets_.getNumBuckets(); i++) {
145 toAppend(",", &result);
147 const ContainerType& cont = buckets_.getByIndex(i);
148 toAppend(buckets_.getBucketMin(i),
149 ":", cont.count(level),
150 ":", cont.template avg<ValueType>(level), &result);
156 template <typename T, typename TT, typename C>
157 std::string TimeseriesHistogram<T, TT, C>::getString(TimeType start,
158 TimeType end) const {
161 for (size_t i = 0; i < buckets_.getNumBuckets(); i++) {
163 toAppend(",", &result);
165 const ContainerType& cont = buckets_.getByIndex(i);
166 toAppend(buckets_.getBucketMin(i),
167 ":", cont.count(start, end),
168 ":", cont.avg(start, end), &result);
174 template <class T, class TT, class C>
175 void TimeseriesHistogram<T, TT, C>::computeAvgData(
179 for (unsigned int b = 0; b < buckets_.getNumBuckets(); ++b) {
180 const auto& levelObj = buckets_.getByIndex(b).getLevel(level);
181 *total += levelObj.sum();
182 *nsamples += levelObj.count();
186 template <class T, class TT, class C>
187 void TimeseriesHistogram<T, TT, C>::computeAvgData(
191 TimeType end) const {
192 for (unsigned int b = 0; b < buckets_.getNumBuckets(); ++b) {
193 const auto& levelObj = buckets_.getByIndex(b).getLevel(start);
194 *total += levelObj.sum(start, end);
195 *nsamples += levelObj.count(start, end);
199 template <typename T, typename TT, typename C>
200 void TimeseriesHistogram<T, TT, C>::computeRateData(
204 for (unsigned int b = 0; b < buckets_.getNumBuckets(); ++b) {
205 const auto& levelObj = buckets_.getByIndex(b).getLevel(level);
206 *total += levelObj.sum();
207 *elapsed = std::max(*elapsed, levelObj.elapsed());
211 template <class T, class TT, class C>
212 void TimeseriesHistogram<T, TT, C>::computeRateData(
216 TimeType end) const {
217 for (unsigned int b = 0; b < buckets_.getNumBuckets(); ++b) {
218 const auto& level = buckets_.getByIndex(b).getLevel(start);
219 *total += level.sum(start, end);
220 *elapsed = std::max(*elapsed, level.elapsed(start, end));