]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/monitoring/statistics.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / rocksdb / monitoring / statistics.cc
1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under the BSD-style license found in the
3 // LICENSE file in the root directory of this source tree. An additional grant
4 // of patent rights can be found in the PATENTS file in the same directory.
5 //
6 #include "monitoring/statistics.h"
7
8 #ifndef __STDC_FORMAT_MACROS
9 #define __STDC_FORMAT_MACROS
10 #endif
11
12 #include <inttypes.h>
13 #include "rocksdb/statistics.h"
14 #include "port/likely.h"
15 #include <algorithm>
16 #include <cstdio>
17
18 namespace rocksdb {
19
20 std::shared_ptr<Statistics> CreateDBStatistics() {
21 return std::make_shared<StatisticsImpl>(nullptr, false);
22 }
23
24 StatisticsImpl::StatisticsImpl(
25 std::shared_ptr<Statistics> stats,
26 bool enable_internal_stats)
27 : stats_shared_(stats),
28 stats_(stats.get()),
29 enable_internal_stats_(enable_internal_stats) {
30 }
31
32 StatisticsImpl::~StatisticsImpl() {}
33
34 uint64_t StatisticsImpl::getTickerCount(uint32_t tickerType) const {
35 MutexLock lock(&aggregate_lock_);
36 return getTickerCountLocked(tickerType);
37 }
38
39 uint64_t StatisticsImpl::getTickerCountLocked(uint32_t tickerType) const {
40 assert(
41 enable_internal_stats_ ?
42 tickerType < INTERNAL_TICKER_ENUM_MAX :
43 tickerType < TICKER_ENUM_MAX);
44 uint64_t thread_local_sum = 0;
45 tickers_[tickerType].thread_value->Fold(
46 [](void* curr_ptr, void* res) {
47 auto* sum_ptr = static_cast<uint64_t*>(res);
48 *sum_ptr += static_cast<std::atomic_uint_fast64_t*>(curr_ptr)->load(
49 std::memory_order_relaxed);
50 },
51 &thread_local_sum);
52 return thread_local_sum +
53 tickers_[tickerType].merged_sum.load(std::memory_order_relaxed);
54 }
55
56 std::unique_ptr<HistogramImpl>
57 StatisticsImpl::HistogramInfo::getMergedHistogram() const {
58 std::unique_ptr<HistogramImpl> res_hist(new HistogramImpl());
59 {
60 MutexLock lock(&merge_lock);
61 res_hist->Merge(merged_hist);
62 }
63 thread_value->Fold(
64 [](void* curr_ptr, void* res) {
65 auto tmp_res_hist = static_cast<HistogramImpl*>(res);
66 auto curr_hist = static_cast<HistogramImpl*>(curr_ptr);
67 tmp_res_hist->Merge(*curr_hist);
68 },
69 res_hist.get());
70 return res_hist;
71 }
72
73 void StatisticsImpl::histogramData(uint32_t histogramType,
74 HistogramData* const data) const {
75 MutexLock lock(&aggregate_lock_);
76 histogramDataLocked(histogramType, data);
77 }
78
79 void StatisticsImpl::histogramDataLocked(uint32_t histogramType,
80 HistogramData* const data) const {
81 assert(
82 enable_internal_stats_ ?
83 histogramType < INTERNAL_HISTOGRAM_ENUM_MAX :
84 histogramType < HISTOGRAM_ENUM_MAX);
85 histograms_[histogramType].getMergedHistogram()->Data(data);
86 }
87
88 std::string StatisticsImpl::getHistogramString(uint32_t histogramType) const {
89 MutexLock lock(&aggregate_lock_);
90 assert(enable_internal_stats_ ? histogramType < INTERNAL_HISTOGRAM_ENUM_MAX
91 : histogramType < HISTOGRAM_ENUM_MAX);
92 return histograms_[histogramType].getMergedHistogram()->ToString();
93 }
94
95 StatisticsImpl::ThreadTickerInfo* StatisticsImpl::getThreadTickerInfo(
96 uint32_t tickerType) {
97 auto info_ptr =
98 static_cast<ThreadTickerInfo*>(tickers_[tickerType].thread_value->Get());
99 if (info_ptr == nullptr) {
100 info_ptr =
101 new ThreadTickerInfo(0 /* value */, &tickers_[tickerType].merged_sum);
102 tickers_[tickerType].thread_value->Reset(info_ptr);
103 }
104 return info_ptr;
105 }
106
107 StatisticsImpl::ThreadHistogramInfo* StatisticsImpl::getThreadHistogramInfo(
108 uint32_t histogram_type) {
109 auto info_ptr = static_cast<ThreadHistogramInfo*>(
110 histograms_[histogram_type].thread_value->Get());
111 if (info_ptr == nullptr) {
112 info_ptr = new ThreadHistogramInfo(&histograms_[histogram_type].merged_hist,
113 &histograms_[histogram_type].merge_lock);
114 histograms_[histogram_type].thread_value->Reset(info_ptr);
115 }
116 return info_ptr;
117 }
118
119 void StatisticsImpl::setTickerCount(uint32_t tickerType, uint64_t count) {
120 {
121 MutexLock lock(&aggregate_lock_);
122 setTickerCountLocked(tickerType, count);
123 }
124 if (stats_ && tickerType < TICKER_ENUM_MAX) {
125 stats_->setTickerCount(tickerType, count);
126 }
127 }
128
129 void StatisticsImpl::setTickerCountLocked(uint32_t tickerType, uint64_t count) {
130 assert(enable_internal_stats_ ? tickerType < INTERNAL_TICKER_ENUM_MAX
131 : tickerType < TICKER_ENUM_MAX);
132 if (tickerType < TICKER_ENUM_MAX || enable_internal_stats_) {
133 tickers_[tickerType].thread_value->Fold(
134 [](void* curr_ptr, void* res) {
135 static_cast<std::atomic<uint64_t>*>(curr_ptr)->store(
136 0, std::memory_order_relaxed);
137 },
138 nullptr /* res */);
139 tickers_[tickerType].merged_sum.store(count, std::memory_order_relaxed);
140 }
141 }
142
143 uint64_t StatisticsImpl::getAndResetTickerCount(uint32_t tickerType) {
144 uint64_t sum = 0;
145 {
146 MutexLock lock(&aggregate_lock_);
147 assert(enable_internal_stats_ ? tickerType < INTERNAL_TICKER_ENUM_MAX
148 : tickerType < TICKER_ENUM_MAX);
149 if (tickerType < TICKER_ENUM_MAX || enable_internal_stats_) {
150 tickers_[tickerType].thread_value->Fold(
151 [](void* curr_ptr, void* res) {
152 auto* sum_ptr = static_cast<uint64_t*>(res);
153 *sum_ptr += static_cast<std::atomic<uint64_t>*>(curr_ptr)->exchange(
154 0, std::memory_order_relaxed);
155 },
156 &sum);
157 sum += tickers_[tickerType].merged_sum.exchange(
158 0, std::memory_order_relaxed);
159 }
160 }
161 if (stats_ && tickerType < TICKER_ENUM_MAX) {
162 stats_->setTickerCount(tickerType, 0);
163 }
164 return sum;
165 }
166
167 void StatisticsImpl::recordTick(uint32_t tickerType, uint64_t count) {
168 assert(
169 enable_internal_stats_ ?
170 tickerType < INTERNAL_TICKER_ENUM_MAX :
171 tickerType < TICKER_ENUM_MAX);
172 if (tickerType < TICKER_ENUM_MAX || enable_internal_stats_) {
173 auto info_ptr = getThreadTickerInfo(tickerType);
174 info_ptr->value.fetch_add(count, std::memory_order_relaxed);
175 }
176 if (stats_ && tickerType < TICKER_ENUM_MAX) {
177 stats_->recordTick(tickerType, count);
178 }
179 }
180
181 void StatisticsImpl::measureTime(uint32_t histogramType, uint64_t value) {
182 assert(
183 enable_internal_stats_ ?
184 histogramType < INTERNAL_HISTOGRAM_ENUM_MAX :
185 histogramType < HISTOGRAM_ENUM_MAX);
186 if (histogramType < HISTOGRAM_ENUM_MAX || enable_internal_stats_) {
187 getThreadHistogramInfo(histogramType)->value.Add(value);
188 }
189 if (stats_ && histogramType < HISTOGRAM_ENUM_MAX) {
190 stats_->measureTime(histogramType, value);
191 }
192 }
193
194 Status StatisticsImpl::Reset() {
195 MutexLock lock(&aggregate_lock_);
196 for (uint32_t i = 0; i < TICKER_ENUM_MAX; ++i) {
197 setTickerCountLocked(i, 0);
198 }
199 for (uint32_t i = 0; i < HISTOGRAM_ENUM_MAX; ++i) {
200 histograms_[i].thread_value->Fold(
201 [](void* curr_ptr, void* res) {
202 static_cast<HistogramImpl*>(curr_ptr)->Clear();
203 },
204 nullptr /* res */);
205 }
206 return Status::OK();
207 }
208
209 namespace {
210
211 // a buffer size used for temp string buffers
212 const int kTmpStrBufferSize = 200;
213
214 } // namespace
215
216 std::string StatisticsImpl::ToString() const {
217 MutexLock lock(&aggregate_lock_);
218 std::string res;
219 res.reserve(20000);
220 for (const auto& t : TickersNameMap) {
221 if (t.first < TICKER_ENUM_MAX || enable_internal_stats_) {
222 char buffer[kTmpStrBufferSize];
223 snprintf(buffer, kTmpStrBufferSize, "%s COUNT : %" PRIu64 "\n",
224 t.second.c_str(), getTickerCountLocked(t.first));
225 res.append(buffer);
226 }
227 }
228 for (const auto& h : HistogramsNameMap) {
229 if (h.first < HISTOGRAM_ENUM_MAX || enable_internal_stats_) {
230 char buffer[kTmpStrBufferSize];
231 HistogramData hData;
232 histogramDataLocked(h.first, &hData);
233 snprintf(
234 buffer, kTmpStrBufferSize,
235 "%s statistics Percentiles :=> 50 : %f 95 : %f 99 : %f 100 : %f\n",
236 h.second.c_str(), hData.median, hData.percentile95,
237 hData.percentile99, hData.max);
238 res.append(buffer);
239 }
240 }
241 res.shrink_to_fit();
242 return res;
243 }
244
245 bool StatisticsImpl::HistEnabledForType(uint32_t type) const {
246 if (LIKELY(!enable_internal_stats_)) {
247 return type < HISTOGRAM_ENUM_MAX;
248 }
249 return true;
250 }
251
252 } // namespace rocksdb