/* * Copyright 2013-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include namespace folly { template TimeseriesHistogram::TimeseriesHistogram( ValueType bucketSize, ValueType min, ValueType max, const ContainerType& copyMe) : buckets_(bucketSize, min, max, copyMe), haveNotSeenValue_(true), singleUniqueValue_(false) {} template void TimeseriesHistogram::addValue( TimePoint now, const ValueType& value) { buckets_.getByValue(value).addValue(now, value); maybeHandleSingleUniqueValue(value); } template void TimeseriesHistogram::addValue( TimePoint now, const ValueType& value, uint64_t times) { buckets_.getByValue(value).addValue(now, value, times); maybeHandleSingleUniqueValue(value); } template void TimeseriesHistogram::addValues( TimePoint now, const folly::Histogram& hist) { CHECK_EQ(hist.getMin(), getMin()); CHECK_EQ(hist.getMax(), getMax()); CHECK_EQ(hist.getBucketSize(), getBucketSize()); CHECK_EQ(hist.getNumBuckets(), getNumBuckets()); for (size_t n = 0; n < hist.getNumBuckets(); ++n) { const typename folly::Histogram::Bucket& histBucket = hist.getBucketByIndex(n); Bucket& myBucket = buckets_.getByIndex(n); myBucket.addValueAggregated(now, histBucket.sum, histBucket.count); } // We don't bother with the singleUniqueValue_ tracking. haveNotSeenValue_ = false; singleUniqueValue_ = false; } template void TimeseriesHistogram::maybeHandleSingleUniqueValue( const ValueType& value) { if (haveNotSeenValue_) { firstValue_ = value; singleUniqueValue_ = true; haveNotSeenValue_ = false; } else if (singleUniqueValue_) { if (value != firstValue_) { singleUniqueValue_ = false; } } } template T TimeseriesHistogram::getPercentileEstimate(double pct, size_t level) const { if (singleUniqueValue_) { return firstValue_; } return buckets_.getPercentileEstimate( pct / 100.0, CountFromLevel(level), AvgFromLevel(level)); } template T TimeseriesHistogram::getPercentileEstimate( double pct, TimePoint start, TimePoint end) const { if (singleUniqueValue_) { return firstValue_; } return buckets_.getPercentileEstimate( pct / 100.0, CountFromInterval(start, end), AvgFromInterval(start, end)); } template size_t TimeseriesHistogram::getPercentileBucketIdx( double pct, size_t level) const { return buckets_.getPercentileBucketIdx(pct / 100.0, CountFromLevel(level)); } template size_t TimeseriesHistogram::getPercentileBucketIdx( double pct, TimePoint start, TimePoint end) const { return buckets_.getPercentileBucketIdx( pct / 100.0, CountFromInterval(start, end)); } template void TimeseriesHistogram::clear() { for (size_t i = 0; i < buckets_.getNumBuckets(); i++) { buckets_.getByIndex(i).clear(); } } template void TimeseriesHistogram::update(TimePoint now) { for (size_t i = 0; i < buckets_.getNumBuckets(); i++) { buckets_.getByIndex(i).update(now); } } template std::string TimeseriesHistogram::getString(size_t level) const { std::string result; for (size_t i = 0; i < buckets_.getNumBuckets(); i++) { if (i > 0) { toAppend(",", &result); } const ContainerType& cont = buckets_.getByIndex(i); toAppend( buckets_.getBucketMin(i), ":", cont.count(level), ":", cont.template avg(level), &result); } return result; } template std::string TimeseriesHistogram::getString( TimePoint start, TimePoint end) const { std::string result; for (size_t i = 0; i < buckets_.getNumBuckets(); i++) { if (i > 0) { toAppend(",", &result); } const ContainerType& cont = buckets_.getByIndex(i); toAppend( buckets_.getBucketMin(i), ":", cont.count(start, end), ":", cont.avg(start, end), &result); } return result; } template void TimeseriesHistogram::computeAvgData( ValueType* total, uint64_t* nsamples, size_t level) const { for (size_t b = 0; b < buckets_.getNumBuckets(); ++b) { const auto& levelObj = buckets_.getByIndex(b).getLevel(level); *total += levelObj.sum(); *nsamples += levelObj.count(); } } template void TimeseriesHistogram::computeAvgData( ValueType* total, uint64_t* nsamples, TimePoint start, TimePoint end) const { for (size_t b = 0; b < buckets_.getNumBuckets(); ++b) { const auto& levelObj = buckets_.getByIndex(b).getLevel(start); *total += levelObj.sum(start, end); *nsamples += levelObj.count(start, end); } } template void TimeseriesHistogram::computeRateData( ValueType* total, Duration* elapsed, size_t level) const { for (size_t b = 0; b < buckets_.getNumBuckets(); ++b) { const auto& levelObj = buckets_.getByIndex(b).getLevel(level); *total += levelObj.sum(); *elapsed = std::max(*elapsed, levelObj.elapsed()); } } template void TimeseriesHistogram::computeRateData( ValueType* total, Duration* elapsed, TimePoint start, TimePoint end) const { for (size_t b = 0; b < buckets_.getNumBuckets(); ++b) { const auto& level = buckets_.getByIndex(b).getLevel(start); *total += level.sum(start, end); *elapsed = std::max(*elapsed, level.elapsed(start, end)); } } } // namespace folly