TimeseriesHistogram-defs.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /*
  2. * Copyright 2013-present Facebook, Inc.
  3. *
  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
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  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.
  15. */
  16. #pragma once
  17. #include <folly/Conv.h>
  18. #include <folly/stats/BucketedTimeSeries-defs.h>
  19. #include <folly/stats/Histogram-defs.h>
  20. #include <folly/stats/MultiLevelTimeSeries-defs.h>
  21. #include <folly/stats/TimeseriesHistogram.h>
  22. namespace folly {
  23. template <typename T, typename CT, typename C>
  24. TimeseriesHistogram<T, CT, C>::TimeseriesHistogram(
  25. ValueType bucketSize,
  26. ValueType min,
  27. ValueType max,
  28. const ContainerType& copyMe)
  29. : buckets_(bucketSize, min, max, copyMe),
  30. haveNotSeenValue_(true),
  31. singleUniqueValue_(false) {}
  32. template <typename T, typename CT, typename C>
  33. void TimeseriesHistogram<T, CT, C>::addValue(
  34. TimePoint now,
  35. const ValueType& value) {
  36. buckets_.getByValue(value).addValue(now, value);
  37. maybeHandleSingleUniqueValue(value);
  38. }
  39. template <typename T, typename CT, typename C>
  40. void TimeseriesHistogram<T, CT, C>::addValue(
  41. TimePoint now,
  42. const ValueType& value,
  43. uint64_t times) {
  44. buckets_.getByValue(value).addValue(now, value, times);
  45. maybeHandleSingleUniqueValue(value);
  46. }
  47. template <typename T, typename CT, typename C>
  48. void TimeseriesHistogram<T, CT, C>::addValues(
  49. TimePoint now,
  50. const folly::Histogram<ValueType>& hist) {
  51. CHECK_EQ(hist.getMin(), getMin());
  52. CHECK_EQ(hist.getMax(), getMax());
  53. CHECK_EQ(hist.getBucketSize(), getBucketSize());
  54. CHECK_EQ(hist.getNumBuckets(), getNumBuckets());
  55. for (size_t n = 0; n < hist.getNumBuckets(); ++n) {
  56. const typename folly::Histogram<ValueType>::Bucket& histBucket =
  57. hist.getBucketByIndex(n);
  58. Bucket& myBucket = buckets_.getByIndex(n);
  59. myBucket.addValueAggregated(now, histBucket.sum, histBucket.count);
  60. }
  61. // We don't bother with the singleUniqueValue_ tracking.
  62. haveNotSeenValue_ = false;
  63. singleUniqueValue_ = false;
  64. }
  65. template <typename T, typename CT, typename C>
  66. void TimeseriesHistogram<T, CT, C>::maybeHandleSingleUniqueValue(
  67. const ValueType& value) {
  68. if (haveNotSeenValue_) {
  69. firstValue_ = value;
  70. singleUniqueValue_ = true;
  71. haveNotSeenValue_ = false;
  72. } else if (singleUniqueValue_) {
  73. if (value != firstValue_) {
  74. singleUniqueValue_ = false;
  75. }
  76. }
  77. }
  78. template <typename T, typename CT, typename C>
  79. T TimeseriesHistogram<T, CT, C>::getPercentileEstimate(double pct, size_t level)
  80. const {
  81. if (singleUniqueValue_) {
  82. return firstValue_;
  83. }
  84. return buckets_.getPercentileEstimate(
  85. pct / 100.0, CountFromLevel(level), AvgFromLevel(level));
  86. }
  87. template <typename T, typename CT, typename C>
  88. T TimeseriesHistogram<T, CT, C>::getPercentileEstimate(
  89. double pct,
  90. TimePoint start,
  91. TimePoint end) const {
  92. if (singleUniqueValue_) {
  93. return firstValue_;
  94. }
  95. return buckets_.getPercentileEstimate(
  96. pct / 100.0,
  97. CountFromInterval(start, end),
  98. AvgFromInterval<T>(start, end));
  99. }
  100. template <typename T, typename CT, typename C>
  101. size_t TimeseriesHistogram<T, CT, C>::getPercentileBucketIdx(
  102. double pct,
  103. size_t level) const {
  104. return buckets_.getPercentileBucketIdx(pct / 100.0, CountFromLevel(level));
  105. }
  106. template <typename T, typename CT, typename C>
  107. size_t TimeseriesHistogram<T, CT, C>::getPercentileBucketIdx(
  108. double pct,
  109. TimePoint start,
  110. TimePoint end) const {
  111. return buckets_.getPercentileBucketIdx(
  112. pct / 100.0, CountFromInterval(start, end));
  113. }
  114. template <typename T, typename CT, typename C>
  115. void TimeseriesHistogram<T, CT, C>::clear() {
  116. for (size_t i = 0; i < buckets_.getNumBuckets(); i++) {
  117. buckets_.getByIndex(i).clear();
  118. }
  119. }
  120. template <typename T, typename CT, typename C>
  121. void TimeseriesHistogram<T, CT, C>::update(TimePoint now) {
  122. for (size_t i = 0; i < buckets_.getNumBuckets(); i++) {
  123. buckets_.getByIndex(i).update(now);
  124. }
  125. }
  126. template <typename T, typename CT, typename C>
  127. std::string TimeseriesHistogram<T, CT, C>::getString(size_t level) const {
  128. std::string result;
  129. for (size_t i = 0; i < buckets_.getNumBuckets(); i++) {
  130. if (i > 0) {
  131. toAppend(",", &result);
  132. }
  133. const ContainerType& cont = buckets_.getByIndex(i);
  134. toAppend(
  135. buckets_.getBucketMin(i),
  136. ":",
  137. cont.count(level),
  138. ":",
  139. cont.template avg<ValueType>(level),
  140. &result);
  141. }
  142. return result;
  143. }
  144. template <typename T, typename CT, typename C>
  145. std::string TimeseriesHistogram<T, CT, C>::getString(
  146. TimePoint start,
  147. TimePoint end) const {
  148. std::string result;
  149. for (size_t i = 0; i < buckets_.getNumBuckets(); i++) {
  150. if (i > 0) {
  151. toAppend(",", &result);
  152. }
  153. const ContainerType& cont = buckets_.getByIndex(i);
  154. toAppend(
  155. buckets_.getBucketMin(i),
  156. ":",
  157. cont.count(start, end),
  158. ":",
  159. cont.avg(start, end),
  160. &result);
  161. }
  162. return result;
  163. }
  164. template <class T, class CT, class C>
  165. void TimeseriesHistogram<T, CT, C>::computeAvgData(
  166. ValueType* total,
  167. uint64_t* nsamples,
  168. size_t level) const {
  169. for (size_t b = 0; b < buckets_.getNumBuckets(); ++b) {
  170. const auto& levelObj = buckets_.getByIndex(b).getLevel(level);
  171. *total += levelObj.sum();
  172. *nsamples += levelObj.count();
  173. }
  174. }
  175. template <class T, class CT, class C>
  176. void TimeseriesHistogram<T, CT, C>::computeAvgData(
  177. ValueType* total,
  178. uint64_t* nsamples,
  179. TimePoint start,
  180. TimePoint end) const {
  181. for (size_t b = 0; b < buckets_.getNumBuckets(); ++b) {
  182. const auto& levelObj = buckets_.getByIndex(b).getLevel(start);
  183. *total += levelObj.sum(start, end);
  184. *nsamples += levelObj.count(start, end);
  185. }
  186. }
  187. template <typename T, typename CT, typename C>
  188. void TimeseriesHistogram<T, CT, C>::computeRateData(
  189. ValueType* total,
  190. Duration* elapsed,
  191. size_t level) const {
  192. for (size_t b = 0; b < buckets_.getNumBuckets(); ++b) {
  193. const auto& levelObj = buckets_.getByIndex(b).getLevel(level);
  194. *total += levelObj.sum();
  195. *elapsed = std::max(*elapsed, levelObj.elapsed());
  196. }
  197. }
  198. template <class T, class CT, class C>
  199. void TimeseriesHistogram<T, CT, C>::computeRateData(
  200. ValueType* total,
  201. Duration* elapsed,
  202. TimePoint start,
  203. TimePoint end) const {
  204. for (size_t b = 0; b < buckets_.getNumBuckets(); ++b) {
  205. const auto& level = buckets_.getByIndex(b).getLevel(start);
  206. *total += level.sum(start, end);
  207. *elapsed = std::max(*elapsed, level.elapsed(start, end));
  208. }
  209. }
  210. } // namespace folly