/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 | 301k | const bool for_intents) { |
46 | 301k | return std::make_shared<StatisticsMetricImpl>(hist_entity, tick_entity, for_intents); |
47 | 301k | } |
48 | | |
49 | 605 | std::shared_ptr<Statistics> CreateDBStatisticsForTests(bool for_intents) { |
50 | 605 | static MetricRegistry metric_registry; |
51 | 605 | static yb::MetricEntityPrototype prototype_table("table"), prototype_tablet("tablet"); |
52 | 605 | static scoped_refptr<MetricEntity> table_metric_entity( |
53 | 605 | prototype_table.Instantiate(&metric_registry, "table-entity-for-tests")); |
54 | 605 | static scoped_refptr<MetricEntity> tablet_metric_entity( |
55 | 605 | prototype_tablet.Instantiate(&metric_registry, "tablet-entity-for-tests")); |
56 | 605 | auto stats = CreateDBStatistics(table_metric_entity, tablet_metric_entity, for_intents); |
57 | 605 | stats->resetTickersForTest(); |
58 | 605 | return stats; |
59 | 605 | } |
60 | | |
61 | | class StatisticsMetricPrototypes { |
62 | | public: |
63 | 14.5k | StatisticsMetricPrototypes() { |
64 | 14.5k | const auto kNumHistograms = HistogramsNameMap.size(); |
65 | 14.5k | 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 | 14.5k | metric_names_.reserve(kNumHistograms + 2 * kNumTickers); |
69 | 14.5k | descriptions_.reserve(kNumHistograms + 2 * kNumTickers); |
70 | | |
71 | 217k | for (size_t i = 0; i < kNumHistograms; i++203k ) { |
72 | 203k | CHECK_EQ(i, HistogramsNameMap[i].first); |
73 | 203k | metric_names_.emplace_back(HistogramsNameMap[i].second); |
74 | 203k | const auto& hist_name = metric_names_.back(); |
75 | | |
76 | 203k | descriptions_.emplace_back(yb::Format("Per-table Rocksdb Histogram for $0", hist_name)); |
77 | 203k | const auto& description = descriptions_.back(); |
78 | | |
79 | 203k | hist_prototypes_.emplace_back(std::make_unique<HistogramPrototype>( |
80 | 203k | ::yb::MetricPrototype::CtorArgs( |
81 | 203k | "table", hist_name.c_str(), description.c_str(), yb::MetricUnit::kMicroseconds, |
82 | 203k | description.c_str(), yb::MetricLevel::kInfo), |
83 | 203k | 2, 1)); |
84 | 203k | } |
85 | | |
86 | 1.32M | for (size_t i = 0; i < kNumTickers; i++1.30M ) { |
87 | 1.30M | CHECK_EQ(i, TickersNameMap[i].first); |
88 | 1.30M | metric_names_.emplace_back(TickersNameMap[i].second); |
89 | 1.30M | const auto& ticker_name = metric_names_.back(); |
90 | | |
91 | 1.30M | descriptions_.emplace_back( |
92 | 1.30M | yb::Format("Per-tablet Regular Rocksdb Ticker for $0", ticker_name)); |
93 | 1.30M | const auto& description = descriptions_.back(); |
94 | | |
95 | 1.30M | regular_ticker_prototypes_.emplace_back( |
96 | 1.30M | std::make_unique<GaugePrototype<uint64_t>>(::yb::MetricPrototype::CtorArgs( |
97 | 1.30M | "tablet", ticker_name.c_str(), description.c_str(), yb::MetricUnit::kRequests, |
98 | 1.30M | description.c_str(), yb::MetricLevel::kInfo))); |
99 | 1.30M | } |
100 | | |
101 | 1.32M | for (size_t i = 0; i < kNumTickers; i++1.30M ) { |
102 | 1.30M | CHECK_EQ(i, TickersNameMap[i].first); |
103 | 1.30M | metric_names_.emplace_back(yb::Format("intentsdb_$0", TickersNameMap[i].second)); |
104 | 1.30M | const auto& ticker_name = metric_names_.back(); |
105 | | |
106 | 1.30M | descriptions_.emplace_back( |
107 | 1.30M | yb::Format("Per-tablet Intents Rocksdb Ticker for $0", ticker_name)); |
108 | 1.30M | const auto& description = descriptions_.back(); |
109 | | |
110 | 1.30M | intents_ticker_prototypes_.emplace_back( |
111 | 1.30M | std::make_unique<GaugePrototype<uint64_t>>(::yb::MetricPrototype::CtorArgs( |
112 | 1.30M | "tablet", ticker_name.c_str(), description.c_str(), yb::MetricUnit::kRequests, |
113 | 1.30M | description.c_str(), yb::MetricLevel::kInfo))); |
114 | 1.30M | } |
115 | 14.5k | } |
116 | | |
117 | 4.21M | const std::vector<std::unique_ptr<HistogramPrototype>>& hist_prototypes() const { |
118 | 4.21M | return hist_prototypes_; |
119 | 4.21M | } |
120 | 13.5M | const std::vector<std::unique_ptr<GaugePrototype<uint64_t>>>& regular_ticker_prototypes() const { |
121 | 13.5M | return regular_ticker_prototypes_; |
122 | 13.5M | } |
123 | 27.4k | const std::vector<std::unique_ptr<GaugePrototype<uint64_t>>>& intents_ticker_prototypes() const { |
124 | 27.4k | return intents_ticker_prototypes_; |
125 | 27.4k | } |
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 | 301k | const bool for_intents) { |
143 | 301k | static StatisticsMetricPrototypes prototypes; |
144 | 301k | const auto kNumHistograms = HistogramsNameMap.size(); |
145 | 301k | const auto kNumTickers = TickersNameMap.size(); |
146 | 4.51M | for (size_t i = 0; hist_entity && i < kNumHistograms4.51M ; i++4.21M ) { |
147 | 4.21M | histograms_.push_back(prototypes.hist_prototypes()[i]->Instantiate(hist_entity)); |
148 | 4.21M | } |
149 | | |
150 | 13.8M | for (size_t i = 0; tick_entity && i < kNumTickers13.7M ; i++13.5M ) { |
151 | 13.5M | tickers_.push_back( |
152 | 13.5M | for_intents ? prototypes.intents_ticker_prototypes()[i]->Instantiate(tick_entity, 0)27.4k |
153 | 13.5M | : prototypes.regular_ticker_prototypes()[i]->Instantiate(tick_entity, 0)13.5M ); |
154 | 13.5M | } |
155 | 301k | } |
156 | | |
157 | 151k | StatisticsMetricImpl::~StatisticsMetricImpl() {} |
158 | | |
159 | 5.13k | uint64_t StatisticsMetricImpl::getTickerCount(uint32_t tickerType) const { |
160 | 5.13k | if (!tickers_.empty()) { |
161 | 5.13k | assert(tickerType < tickers_.size()); |
162 | | // Return its own ticker version |
163 | 0 | return tickers_[tickerType]->value(); |
164 | 5.13k | } |
165 | | |
166 | 0 | return 0; |
167 | 5.13k | } |
168 | | |
169 | 21 | const char* StatisticsMetricImpl::GetTickerName(uint32_t ticker_type) const { |
170 | 21 | CHECK_LT(ticker_type, tickers_.size()); |
171 | 21 | return tickers_[ticker_type]->prototype()->name(); |
172 | 21 | } |
173 | | |
174 | 28 | void StatisticsMetricImpl::histogramData(uint32_t histogramType, HistogramData* const data) const { |
175 | 28 | assert(histogramType < histograms_.size()); |
176 | 0 | assert(data); |
177 | 28 | if (histograms_.empty()) { |
178 | 0 | return; |
179 | 0 | } |
180 | | |
181 | 28 | const yb::HdrHistogram* hist = histograms_[histogramType]->histogram(); |
182 | 28 | data->count = hist->CurrentCount(); |
183 | 28 | data->sum = hist->CurrentSum(); |
184 | 28 | data->min = hist->MinValue(); |
185 | 28 | data->max = hist->MaxValue(); |
186 | 28 | data->median = hist->ValueAtPercentile(50); |
187 | 28 | data->percentile95 = hist->ValueAtPercentile(95); |
188 | 28 | data->percentile99 = hist->ValueAtPercentile(99); |
189 | 28 | data->average = hist->MeanValue(); |
190 | | // Computing standard deviation is not supported by HdrHistogram. |
191 | | // We don't use it for Yugabyte anyways. |
192 | 28 | data->standard_deviation = -1; |
193 | 28 | } |
194 | | |
195 | 14.8M | void StatisticsMetricImpl::setTickerCount(uint32_t tickerType, uint64_t count) { |
196 | 14.8M | if (!tickers_.empty()) { |
197 | 10.1M | assert(tickerType < tickers_.size()); |
198 | 0 | tickers_[tickerType]->set_value(count); |
199 | 10.1M | if (tickerType == CURRENT_VERSION_SST_FILES_SIZE) { |
200 | 289k | setTickerCount(OLD_BK_COMPAT_CURRENT_VERSION_SST_FILES_SIZE, count); |
201 | 289k | } |
202 | 10.1M | } |
203 | 14.8M | } |
204 | | |
205 | 3.87G | void StatisticsMetricImpl::recordTick(uint32_t tickerType, uint64_t count) { |
206 | 3.87G | if (!tickers_.empty()) { |
207 | 2.98G | assert(tickerType < tickers_.size()); |
208 | 0 | tickers_[tickerType]->IncrementBy(count); |
209 | 2.98G | if (tickerType == CURRENT_VERSION_SST_FILES_SIZE) { |
210 | 0 | recordTick(OLD_BK_COMPAT_CURRENT_VERSION_SST_FILES_SIZE, count); |
211 | 0 | } |
212 | 2.98G | } |
213 | 3.87G | } |
214 | | |
215 | 605 | void StatisticsMetricImpl::resetTickersForTest() { |
216 | 55.0k | for (uint32_t i = 0; i < tickers_.size(); i++54.4k ) { |
217 | 54.4k | setTickerCount(i, 0); |
218 | 54.4k | } |
219 | 605 | } |
220 | | |
221 | 28.2M | void StatisticsMetricImpl::measureTime(uint32_t histogramType, uint64_t value) { |
222 | 28.2M | if (!histograms_.empty()) { |
223 | 28.2M | assert(histogramType < histograms_.size()); |
224 | 0 | histograms_[histogramType]->Increment(value); |
225 | 28.2M | } |
226 | 28.2M | } |
227 | | |
228 | | } // namespace rocksdb |