/Users/deen/code/yugabyte-db/src/yb/rocksdb/util/statistics.cc
Line | Count | Source (jump to first uncovered line) |
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 | | // The following only applies to changes made to this file as part of YugaByte development. |
7 | | // |
8 | | // Portions Copyright (c) YugaByte, Inc. |
9 | | // |
10 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
11 | | // in compliance with the License. You may obtain a copy of the License at |
12 | | // |
13 | | // http://www.apache.org/licenses/LICENSE-2.0 |
14 | | // |
15 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
16 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
17 | | // or implied. See the License for the specific language governing permissions and limitations |
18 | | // under the License. |
19 | | // |
20 | | #include "yb/rocksdb/util/statistics.h" |
21 | | |
22 | | #ifndef __STDC_FORMAT_MACROS |
23 | | #define __STDC_FORMAT_MACROS |
24 | | #endif |
25 | | |
26 | | #include <inttypes.h> |
27 | | #include <algorithm> |
28 | | #include "yb/rocksdb/statistics.h" |
29 | | #include "yb/rocksdb/port/likely.h" |
30 | | #include "yb/util/format.h" |
31 | | #include "yb/util/hdr_histogram.h" |
32 | | #include "yb/util/metrics.h" |
33 | | |
34 | | namespace rocksdb { |
35 | | |
36 | | using yb::GaugePrototype; |
37 | | using yb::HistogramPrototype; |
38 | | using yb::MetricEntity; |
39 | | using yb::MetricRegistry; |
40 | | using yb::MetricPrototype; |
41 | | |
42 | | std::shared_ptr<Statistics> CreateDBStatistics( |
43 | | const scoped_refptr<MetricEntity>& hist_entity, |
44 | | const scoped_refptr<MetricEntity>& tick_entity, |
45 | 178k | const bool for_intents) { |
46 | 178k | return std::make_shared<StatisticsMetricImpl>(hist_entity, tick_entity, for_intents); |
47 | 178k | } |
48 | | |
49 | 366 | std::shared_ptr<Statistics> CreateDBStatisticsForTests(bool for_intents) { |
50 | 366 | static MetricRegistry metric_registry; |
51 | 366 | static yb::MetricEntityPrototype prototype_table("table"), prototype_tablet("tablet"); |
52 | 366 | static scoped_refptr<MetricEntity> table_metric_entity( |
53 | 366 | prototype_table.Instantiate(&metric_registry, "table-entity-for-tests")); |
54 | 366 | static scoped_refptr<MetricEntity> tablet_metric_entity( |
55 | 366 | prototype_tablet.Instantiate(&metric_registry, "tablet-entity-for-tests")); |
56 | 366 | auto stats = CreateDBStatistics(table_metric_entity, tablet_metric_entity, for_intents); |
57 | 366 | stats->resetTickersForTest(); |
58 | 366 | return stats; |
59 | 366 | } |
60 | | |
61 | | class StatisticsMetricPrototypes { |
62 | | public: |
63 | 9.61k | StatisticsMetricPrototypes() { |
64 | 9.61k | const auto kNumHistograms = HistogramsNameMap.size(); |
65 | 9.61k | const auto kNumTickers = TickersNameMap.size(); |
66 | | // Metrics use a map based on the metric prototype's address. |
67 | | // We reserve the capacity apriori so that the elements are not moved around. |
68 | 9.61k | metric_names_.reserve(kNumHistograms + 2 * kNumTickers); |
69 | 9.61k | descriptions_.reserve(kNumHistograms + 2 * kNumTickers); |
70 | | |
71 | 144k | for (size_t i = 0; i < kNumHistograms; i++) { |
72 | 134k | CHECK_EQ(i, HistogramsNameMap[i].first); |
73 | 134k | metric_names_.emplace_back(HistogramsNameMap[i].second); |
74 | 134k | const auto& hist_name = metric_names_.back(); |
75 | | |
76 | 134k | descriptions_.emplace_back(yb::Format("Per-table Rocksdb Histogram for $0", hist_name)); |
77 | 134k | const auto& description = descriptions_.back(); |
78 | | |
79 | 134k | hist_prototypes_.emplace_back(std::make_unique<HistogramPrototype>( |
80 | 134k | ::yb::MetricPrototype::CtorArgs( |
81 | 134k | "table", hist_name.c_str(), description.c_str(), yb::MetricUnit::kMicroseconds, |
82 | 134k | description.c_str(), yb::MetricLevel::kInfo), |
83 | 134k | 2, 1)); |
84 | 134k | } |
85 | | |
86 | 874k | for (size_t i = 0; i < kNumTickers; i++) { |
87 | 865k | CHECK_EQ(i, TickersNameMap[i].first); |
88 | 865k | metric_names_.emplace_back(TickersNameMap[i].second); |
89 | 865k | const auto& ticker_name = metric_names_.back(); |
90 | | |
91 | 865k | descriptions_.emplace_back( |
92 | 865k | yb::Format("Per-tablet Regular Rocksdb Ticker for $0", ticker_name)); |
93 | 865k | const auto& description = descriptions_.back(); |
94 | | |
95 | 865k | regular_ticker_prototypes_.emplace_back( |
96 | 865k | std::make_unique<GaugePrototype<uint64_t>>(::yb::MetricPrototype::CtorArgs( |
97 | 865k | "tablet", ticker_name.c_str(), description.c_str(), yb::MetricUnit::kRequests, |
98 | 865k | description.c_str(), yb::MetricLevel::kInfo))); |
99 | 865k | } |
100 | | |
101 | 874k | for (size_t i = 0; i < kNumTickers; i++) { |
102 | 865k | CHECK_EQ(i, TickersNameMap[i].first); |
103 | 865k | metric_names_.emplace_back(yb::Format("intentsdb_$0", TickersNameMap[i].second)); |
104 | 865k | const auto& ticker_name = metric_names_.back(); |
105 | | |
106 | 865k | descriptions_.emplace_back( |
107 | 865k | yb::Format("Per-tablet Intents Rocksdb Ticker for $0", ticker_name)); |
108 | 865k | const auto& description = descriptions_.back(); |
109 | | |
110 | 865k | intents_ticker_prototypes_.emplace_back( |
111 | 865k | std::make_unique<GaugePrototype<uint64_t>>(::yb::MetricPrototype::CtorArgs( |
112 | 865k | "tablet", ticker_name.c_str(), description.c_str(), yb::MetricUnit::kRequests, |
113 | 865k | description.c_str(), yb::MetricLevel::kInfo))); |
114 | 865k | } |
115 | 9.61k | } |
116 | | |
117 | 2.49M | const std::vector<std::unique_ptr<HistogramPrototype>>& hist_prototypes() const { |
118 | 2.49M | return hist_prototypes_; |
119 | 2.49M | } |
120 | 8.00M | const std::vector<std::unique_ptr<GaugePrototype<uint64_t>>>& regular_ticker_prototypes() const { |
121 | 8.00M | return regular_ticker_prototypes_; |
122 | 8.00M | } |
123 | 17.8k | const std::vector<std::unique_ptr<GaugePrototype<uint64_t>>>& intents_ticker_prototypes() const { |
124 | 17.8k | return intents_ticker_prototypes_; |
125 | 17.8k | } |
126 | | |
127 | | private: |
128 | | std::vector<std::unique_ptr<HistogramPrototype>> hist_prototypes_; |
129 | | std::vector<std::unique_ptr<GaugePrototype<uint64_t>>> regular_ticker_prototypes_; |
130 | | std::vector<std::unique_ptr<GaugePrototype<uint64_t>>> intents_ticker_prototypes_; |
131 | | // store the names and descriptions generated because the MetricPrototypes only keep |
132 | | // a char * ptr to the name/description. |
133 | | std::vector<std::string> metric_names_; |
134 | | std::vector<std::string> descriptions_; |
135 | | |
136 | | DISALLOW_COPY_AND_ASSIGN(StatisticsMetricPrototypes); |
137 | | }; |
138 | | |
139 | | StatisticsMetricImpl::StatisticsMetricImpl( |
140 | | const scoped_refptr<MetricEntity>& hist_entity, |
141 | | const scoped_refptr<MetricEntity>& tick_entity, |
142 | 178k | const bool for_intents) { |
143 | 178k | static StatisticsMetricPrototypes prototypes; |
144 | 178k | const auto kNumHistograms = HistogramsNameMap.size(); |
145 | 178k | const auto kNumTickers = TickersNameMap.size(); |
146 | 2.67M | for (size_t i = 0; hist_entity && i < kNumHistograms; i++) { |
147 | 2.49M | histograms_.push_back(prototypes.hist_prototypes()[i]->Instantiate(hist_entity)); |
148 | 2.49M | } |
149 | | |
150 | 8.20M | for (size_t i = 0; tick_entity && i < kNumTickers; i++) { |
151 | 8.03M | tickers_.push_back( |
152 | 17.8k | for_intents ? prototypes.intents_ticker_prototypes()[i]->Instantiate(tick_entity, 0) |
153 | 8.01M | : prototypes.regular_ticker_prototypes()[i]->Instantiate(tick_entity, 0)); |
154 | 8.03M | } |
155 | 178k | } |
156 | | |
157 | 95.8k | StatisticsMetricImpl::~StatisticsMetricImpl() {} |
158 | | |
159 | 1.67k | uint64_t StatisticsMetricImpl::getTickerCount(uint32_t tickerType) const { |
160 | 1.67k | if (!tickers_.empty()) { |
161 | 1.67k | assert(tickerType < tickers_.size()); |
162 | | // Return its own ticker version |
163 | 1.67k | return tickers_[tickerType]->value(); |
164 | 1.67k | } |
165 | | |
166 | 0 | return 0; |
167 | 0 | } |
168 | | |
169 | 28 | void StatisticsMetricImpl::histogramData(uint32_t histogramType, HistogramData* const data) const { |
170 | 28 | assert(histogramType < histograms_.size()); |
171 | 28 | assert(data); |
172 | 28 | if (histograms_.empty()) { |
173 | 0 | return; |
174 | 0 | } |
175 | | |
176 | 28 | const yb::HdrHistogram* hist = histograms_[histogramType]->histogram(); |
177 | 28 | data->count = hist->CurrentCount(); |
178 | 28 | data->sum = hist->CurrentSum(); |
179 | 28 | data->min = hist->MinValue(); |
180 | 28 | data->max = hist->MaxValue(); |
181 | 28 | data->median = hist->ValueAtPercentile(50); |
182 | 28 | data->percentile95 = hist->ValueAtPercentile(95); |
183 | 28 | data->percentile99 = hist->ValueAtPercentile(99); |
184 | 28 | data->average = hist->MeanValue(); |
185 | | // Computing standard deviation is not supported by HdrHistogram. |
186 | | // We don't use it for Yugabyte anyways. |
187 | 28 | data->standard_deviation = -1; |
188 | 28 | } |
189 | | |
190 | 8.30M | void StatisticsMetricImpl::setTickerCount(uint32_t tickerType, uint64_t count) { |
191 | 8.30M | if (!tickers_.empty()) { |
192 | 5.62M | assert(tickerType < tickers_.size()); |
193 | 5.62M | tickers_[tickerType]->set_value(count); |
194 | 5.62M | if (tickerType == CURRENT_VERSION_SST_FILES_SIZE) { |
195 | 229k | setTickerCount(OLD_BK_COMPAT_CURRENT_VERSION_SST_FILES_SIZE, count); |
196 | 229k | } |
197 | 5.62M | } |
198 | 8.30M | } |
199 | | |
200 | 1.29G | void StatisticsMetricImpl::recordTick(uint32_t tickerType, uint64_t count) { |
201 | 1.29G | if (!tickers_.empty()) { |
202 | 1.01G | assert(tickerType < tickers_.size()); |
203 | 1.01G | tickers_[tickerType]->IncrementBy(count); |
204 | 1.01G | if (tickerType == CURRENT_VERSION_SST_FILES_SIZE) { |
205 | 0 | recordTick(OLD_BK_COMPAT_CURRENT_VERSION_SST_FILES_SIZE, count); |
206 | 0 | } |
207 | 1.01G | } |
208 | 1.29G | } |
209 | | |
210 | 366 | void StatisticsMetricImpl::resetTickersForTest() { |
211 | 33.3k | for (uint32_t i = 0; i < tickers_.size(); i++) { |
212 | 32.9k | setTickerCount(i, 0); |
213 | 32.9k | } |
214 | 366 | } |
215 | | |
216 | 15.0M | void StatisticsMetricImpl::measureTime(uint32_t histogramType, uint64_t value) { |
217 | 15.0M | if (!histograms_.empty()) { |
218 | 15.0M | assert(histogramType < histograms_.size()); |
219 | 15.0M | histograms_[histogramType]->Increment(value); |
220 | 15.0M | } |
221 | 15.0M | } |
222 | | |
223 | | } // namespace rocksdb |