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