userver: userver/storages/postgres/statistics.hpp Source File
Loading...
Searching...
No Matches
statistics.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/storages/postgres/statistics.hpp
4/// @brief Statistics helpers
5
6#include <string>
7#include <unordered_map>
8#include <vector>
9
10#include <userver/storages/postgres/detail/time_types.hpp>
11
12#include <userver/congestion_control/controllers/linear.hpp>
13#include <userver/utils/statistics/min_max_avg.hpp>
14#include <userver/utils/statistics/percentile.hpp>
15#include <userver/utils/statistics/rate.hpp>
16#include <userver/utils/statistics/rate_counter.hpp>
17#include <userver/utils/statistics/recentperiod.hpp>
18#include <userver/utils/statistics/relaxed_counter.hpp>
19#include <userver/utils/statistics/writer.hpp>
20
21USERVER_NAMESPACE_BEGIN
22
23namespace storages::postgres {
24
25/// @brief Template transaction statistics storage
26template <typename GaugeCounter, typename RateCounter, typename PercentileAccumulator>
28 /// Number of transactions started
29 RateCounter total{};
30 /// Number of transactions committed
31 RateCounter commit_total{};
32 /// Number of transactions rolled back
33 RateCounter rollback_total{};
34 /// Number of out-of-transaction executions
35 RateCounter out_of_trx_total{};
36 /// Number of parsed queries
37 RateCounter parse_total{};
38 /// Number of query executions
39 RateCounter execute_total{};
40 /// Total number of replies
41 RateCounter reply_total{};
42 /// Number of portal bind operations
43 RateCounter portal_bind_total{};
44 /// Error during query execution
45 RateCounter error_execute_total{};
46 /// Timeout while executing query
47 RateCounter execute_timeout{};
48 /// Duplicate prepared statements
49 /// This is not a hard error, the prepared statements are quite reusable due
50 /// to pretty uniqueness of names. Nevertheless we would like to see them to
51 /// diagnose certain kinds of problems
53
54 // TODO pick reasonable resolution for transaction
55 // execution times
56 /// Transaction overall execution time distribution
57 PercentileAccumulator total_percentile;
58 /// Transaction aggregated query execution time distribution
59 PercentileAccumulator busy_percentile;
60 /// Transaction wait for pool time (difference between trx_start_time and
61 /// work_start_time)
62 PercentileAccumulator wait_start_percentile;
63 /// Transaction wait for pool time (difference between last_execute_finish and
64 /// trx_end_time)
65 PercentileAccumulator wait_end_percentile;
66 /// Return to pool percentile (difference between trx_end_time and time the
67 /// connection has been returned to the pool)
68 PercentileAccumulator return_to_pool_percentile;
69};
70
71/// @brief Template connection statistics storage
72template <typename GaugeCounter, typename RateCounter, typename MmaAccumulator>
74 /// Number of connections opened
75 RateCounter open_total{};
76 /// Number of connections dropped
77 RateCounter drop_total{};
78 /// Number of active connections
79 GaugeCounter active = 0;
80 /// Number of connections in use
81 GaugeCounter used = 0;
82 /// Number of maximum allowed connections
83 GaugeCounter maximum = 0;
84 /// Number of waiting requests
85 GaugeCounter waiting = 0;
86 /// Error during connection
87 RateCounter error_total{};
88 /// Connection timeouts (timeouts while connecting)
89 RateCounter error_timeout{};
90 /// Number of rejected connection attempts due to rate limiting
91 RateCounter rate_limit_throttled{};
92 /// Number of maximum allowed waiting requests
93 GaugeCounter max_queue_size = 0;
94
95 /// Prepared statements count min-max-avg
96 MmaAccumulator prepared_statements;
97};
98
99/// @brief Template instance topology statistics storage
100template <typename MmaAccumulator>
102 /// Roundtrip time min-max-avg
103 MmaAccumulator roundtrip_time;
104 /// Replication lag min-max-avg
105 MmaAccumulator replication_lag;
106};
107
108/// @brief Template instance statistics storage
109template <typename GaugeCounter, typename RateCounter, typename PercentileAccumulator, typename MmaAccumulator>
111 /// Connection statistics
112 ConnectionStatistics<GaugeCounter, RateCounter, MmaAccumulator> connection;
113 /// Transaction statistics
114 TransactionStatistics<GaugeCounter, RateCounter, PercentileAccumulator> transaction;
115 /// Topology statistics
117 /// Error caused by pool exhaustion
118 RateCounter pool_exhaust_errors{};
119 /// Error caused by queue size overflow
120 RateCounter queue_size_errors{};
121 /// Connect time percentile
122 PercentileAccumulator connection_percentile;
123 /// Acquire connection percentile
124 PercentileAccumulator acquire_percentile;
125 /// Congestion control statistics
126 std::conditional_t<std::is_same_v<GaugeCounter, uint32_t>, std::byte /* NOOP */, congestion_control::v2::Stats>
128};
129
130using RateCounter = USERVER_NAMESPACE::utils::statistics::RateCounter;
131using Rate = USERVER_NAMESPACE::utils::statistics::Rate;
132using Percentile = USERVER_NAMESPACE::utils::statistics::Percentile<2048>;
133using MinMaxAvg = USERVER_NAMESPACE::utils::statistics::MinMaxAvg<uint32_t>;
134using InstanceStatistics = InstanceStatisticsTemplate<
135 USERVER_NAMESPACE::utils::statistics::RelaxedCounter<uint32_t>,
136 RateCounter,
137 USERVER_NAMESPACE::utils::statistics::RecentPeriod<Percentile, Percentile, detail::SteadyCoarseClock>,
138 USERVER_NAMESPACE::utils::statistics::RecentPeriod<MinMaxAvg, MinMaxAvg, detail::SteadyCoarseClock>>;
139
140struct StatementStatistics final {
141 Percentile timings{};
142 RateCounter executed{};
143 RateCounter errors{};
144
145 void Add(const StatementStatistics& other) {
146 timings.Add(other.timings);
147 executed.Add(other.executed.Load());
148 errors.Add(other.errors.Load());
149 }
150};
151
152using InstanceStatisticsNonatomicBase = InstanceStatisticsTemplate<uint32_t, Rate, Percentile, MinMaxAvg>;
153
154struct InstanceStatisticsNonatomic : InstanceStatisticsNonatomicBase {
155 InstanceStatisticsNonatomic() = default;
156
157 template <typename Statistics>
158 InstanceStatisticsNonatomic(const Statistics& stats) {
159 *this = stats;
160 }
161 InstanceStatisticsNonatomic(InstanceStatisticsNonatomic&&) = default;
163
165 const InstanceStatistics& stats,
166 const decltype(InstanceStatistics::topology)& topology_stats
167 ) {
168 connection.open_total = stats.connection.open_total.Load();
169 connection.drop_total = stats.connection.drop_total.Load();
170 connection.active = stats.connection.active;
171 connection.used = stats.connection.used;
172 connection.maximum = stats.connection.maximum;
173 connection.waiting = stats.connection.waiting;
174 connection.error_total = stats.connection.error_total.Load();
175 connection.error_timeout = stats.connection.error_timeout.Load();
176 connection.rate_limit_throttled = stats.connection.rate_limit_throttled.Load();
177 connection.prepared_statements = stats.connection.prepared_statements.GetStatsForPeriod();
178 connection.max_queue_size = stats.connection.max_queue_size;
179
180 transaction.total = stats.transaction.total.Load();
181 transaction.commit_total = stats.transaction.commit_total.Load();
182 transaction.rollback_total = stats.transaction.rollback_total.Load();
183 transaction.out_of_trx_total = stats.transaction.out_of_trx_total.Load();
184 transaction.parse_total = stats.transaction.parse_total.Load();
185 transaction.execute_total = stats.transaction.execute_total.Load();
186 transaction.reply_total = stats.transaction.reply_total.Load();
187 transaction.portal_bind_total = stats.transaction.portal_bind_total.Load();
188 transaction.error_execute_total = stats.transaction.error_execute_total.Load();
189 transaction.execute_timeout = stats.transaction.execute_timeout.Load();
190 transaction.duplicate_prepared_statements = stats.transaction.duplicate_prepared_statements.Load();
191 transaction.total_percentile = stats.transaction.total_percentile.GetStatsForPeriod();
192 transaction.busy_percentile = stats.transaction.busy_percentile.GetStatsForPeriod();
193 transaction.wait_start_percentile = stats.transaction.wait_start_percentile.GetStatsForPeriod();
194 transaction.wait_end_percentile = stats.transaction.wait_end_percentile.GetStatsForPeriod();
195 transaction.return_to_pool_percentile = stats.transaction.return_to_pool_percentile.GetStatsForPeriod();
196
197 topology.roundtrip_time = topology_stats.roundtrip_time.GetStatsForPeriod();
198 topology.replication_lag = topology_stats.replication_lag.GetStatsForPeriod();
199
200 pool_exhaust_errors = stats.pool_exhaust_errors.Load();
201 queue_size_errors = stats.queue_size_errors.Load();
202 connection_percentile = stats.connection_percentile.GetStatsForPeriod();
203 acquire_percentile = stats.acquire_percentile.GetStatsForPeriod();
204
205 return *this;
206 }
207
208 InstanceStatisticsNonatomic& Add(const std::unordered_map<std::string, StatementStatistics>& stats) {
209 for (const auto& [statement_name, statement_stats] : stats) {
210 const auto [it, inserted] = per_statement_stats.try_emplace(statement_name, statement_stats);
211 if (!inserted) {
212 it->second.Add(statement_stats);
213 }
214 }
215
216 return *this;
217 }
218
219 std::unordered_map<std::string, StatementStatistics> per_statement_stats;
220};
221
222/// @brief Instance statistics with description
224 /// host[:port] of an instance
225 std::string host_port;
226 /// Statistics of an instance
228};
229
230/// @brief Cluster statistics storage
232 /// Connlimit mode auto is on
234 /// Master instance statistics
236 /// Sync slave instance statistics
238 /// Slave instances statistics
240 /// Unknown/unreachable instances statistics
242};
243
244// InstanceStatisticsNonatomic values support for utils::statistics::Writer
245void DumpMetric(USERVER_NAMESPACE::utils::statistics::Writer& writer, const InstanceStatisticsNonatomic& stats);
246
247/// @brief InstanceStatsDescriptor values support for utils::statistics::Writer
248void DumpMetric(USERVER_NAMESPACE::utils::statistics::Writer& writer, const InstanceStatsDescriptor& value);
249
250/// @brief ClusterStatistics values support for utils::statistics::Writer
251void DumpMetric(USERVER_NAMESPACE::utils::statistics::Writer& writer, const ClusterStatistics& value);
252
253using ClusterStatisticsPtr = std::unique_ptr<ClusterStatistics>;
254
255} // namespace storages::postgres
256
257USERVER_NAMESPACE_END