1#[derive(Copy, Clone, Eq, PartialEq, Debug)]
17pub enum StatsMetricType {
18 Counter,
20 Gauge,
22 Timestamp,
24}
25
26#[derive(Copy, Clone, Eq, PartialEq, Debug)]
37pub struct MetricSpec {
38 pub name: &'static str,
40 pub kind: StatsMetricType,
42 pub description: &'static str,
44}
45
46macro_rules! define_codec {
47 (
48 $enum_name:ident, $codec_const:ident,
49 $codec_doc:literal,
50 $variant_doc:literal,
51 { $( $variant:ident, $name:literal, $kind:ident, $desc:literal );* $(;)? }
52 ) => {
53 #[doc = $variant_doc]
54 #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
59 #[repr(usize)]
60 pub enum $enum_name {
61 $(
62 #[doc = $desc]
63 $variant
64 ),*
65 }
66
67 impl $enum_name {
68 #[doc = concat!(
73 "```\nuse dynomite::stats::", stringify!($enum_name),
74 ";\nassert!(!", stringify!($enum_name), "::ALL.is_empty());\n```"
75 )]
76 pub const ALL: &'static [$enum_name] = &[ $( Self::$variant ),* ];
77
78 #[doc = concat!(
83 "```\nuse dynomite::stats::", stringify!($enum_name),
84 ";\nlet name = ", stringify!($enum_name),
85 "::ALL[0].name();\nassert!(!name.is_empty());\n```"
86 )]
87 pub fn name(self) -> &'static str {
88 match self { $( Self::$variant => $name ),* }
89 }
90
91 #[doc = concat!(
96 "```\nuse dynomite::stats::{", stringify!($enum_name),
97 ", StatsMetricType};\nlet k = ", stringify!($enum_name),
98 "::ALL[0].kind();\nassert!(matches!(k, StatsMetricType::Counter | StatsMetricType::Gauge | StatsMetricType::Timestamp));\n```"
99 )]
100 pub fn kind(self) -> StatsMetricType {
101 match self { $( Self::$variant => StatsMetricType::$kind ),* }
102 }
103
104 #[doc = concat!(
109 "```\nuse dynomite::stats::", stringify!($enum_name),
110 ";\nlet d = ", stringify!($enum_name),
111 "::ALL[0].description();\nassert!(!d.is_empty());\n```"
112 )]
113 pub fn description(self) -> &'static str {
114 match self { $( Self::$variant => $desc ),* }
115 }
116
117 #[doc = concat!(
122 "```\nuse dynomite::stats::", stringify!($enum_name),
123 ";\nassert_eq!(", stringify!($enum_name),
124 "::ALL[0].index(), 0);\n```"
125 )]
126 pub fn index(self) -> usize {
127 self as usize
128 }
129 }
130
131 #[doc = $codec_doc]
132 #[doc = concat!(
136 "```\nuse dynomite::stats::", stringify!($codec_const),
137 ";\nassert!(!", stringify!($codec_const), ".is_empty());\n```"
138 )]
139 pub const $codec_const: &[MetricSpec] = &[
140 $(
141 MetricSpec {
142 name: $name,
143 kind: StatsMetricType::$kind,
144 description: $desc,
145 }
146 ),*
147 ];
148 };
149}
150
151define_codec!(
152 PoolField, POOL_CODEC,
153 "Const slice of every pool metric descriptor in declaration order.",
154 "Typed handle for a pool metric.",
155 {
156 ClientEof, "client_eof", Counter, "# eof on client connections";
157 ClientErr, "client_err", Counter, "# errors on client connections";
158 ClientConnections, "client_connections", Gauge, "# active client connections";
159 ClientReadRequests, "client_read_requests", Counter, "# client read requests";
160 ClientWriteRequests, "client_write_requests", Counter, "# client write responses";
161 ClientDroppedRequests, "client_dropped_requests", Counter, "# client dropped requests";
162 ClientNonQuorumWResponses, "client_non_quorum_w_responses", Counter, "# client non quorum write responses";
163 ClientNonQuorumRResponses, "client_non_quorum_r_responses", Counter, "# client non quorum read responses";
164 ServerEjects, "server_ejects", Counter, "# times backend server was ejected";
165 DnodeClientEof, "dnode_client_eof", Counter, "# eof on dnode client connections";
166 DnodeClientErr, "dnode_client_err", Counter, "# errors on dnode client connections";
167 DnodeClientConnections, "dnode_client_connections", Gauge, "# active dnode client connections";
168 DnodeClientInQueue, "dnode_client_in_queue", Gauge, "# dnode client requests in incoming queue";
169 DnodeClientInQueueBytes, "dnode_client_in_queue_bytes", Gauge, "current dnode client request bytes in incoming queue";
170 DnodeClientOutQueue, "dnode_client_out_queue", Gauge, "# dnode client requests in outgoing queue";
171 DnodeClientOutQueueBytes, "dnode_client_out_queue_bytes", Gauge, "current dnode client request bytes in outgoing queue";
172 PeerDroppedRequests, "peer_dropped_requests", Counter, "# local dc peer dropped requests";
173 PeerTimedoutRequests, "peer_timedout_requests", Counter, "# local dc peer timedout requests";
174 RemotePeerDroppedRequests,"remote_peer_dropped_requests", Counter, "# remote dc peer dropped requests";
175 RemotePeerTimedoutRequests,"remote_peer_timedout_requests", Counter, "# remote dc peer timedout requests";
176 RemotePeerFailoverRequests,"remote_peer_failover_requests", Counter, "# remote dc peer failover requests";
177 PeerEof, "peer_eof", Counter, "# eof on peer connections";
178 PeerErr, "peer_err", Counter, "# errors on peer connections";
179 PeerTimedout, "peer_timedout", Counter, "# timeouts on local dc peer connections";
180 RemotePeerTimedout, "remote_peer_timedout", Counter, "# timeouts on remote dc peer connections";
181 PeerConnections, "peer_connections", Gauge, "# active peer connections";
182 PeerForwardError, "peer_forward_error", Gauge, "# times we encountered a peer forwarding error";
183 PeerRequests, "peer_requests", Counter, "# peer requests";
184 PeerRequestBytes, "peer_request_bytes", Counter, "total peer request bytes";
185 PeerResponses, "peer_responses", Counter, "# peer respones";
186 PeerResponseBytes, "peer_response_bytes", Counter, "total peer response bytes";
187 PeerEjectedAt, "peer_ejected_at", Timestamp, "timestamp when peer was ejected";
188 PeerEjects, "peer_ejects", Counter, "# times a peer was ejected";
189 PeerInQueue, "peer_in_queue", Gauge, "# local dc peer requests in incoming queue";
190 RemotePeerInQueue, "remote_peer_in_queue", Gauge, "# remote dc peer requests in incoming queue";
191 PeerInQueueBytes, "peer_in_queue_bytes", Gauge, "current peer request bytes in incoming queue";
192 RemotePeerInQueueBytes, "remote_peer_in_queue_bytes", Gauge, "current peer request bytes in incoming queue to remote DC";
193 PeerOutQueue, "peer_out_queue", Gauge, "# local dc peer requests in outgoing queue";
194 RemotePeerOutQueue, "remote_peer_out_queue", Gauge, "# remote dc peer requests in outgoing queue";
195 PeerOutQueueBytes, "peer_out_queue_bytes", Gauge, "current peer request bytes in outgoing queue";
196 RemotePeerOutQueueBytes, "remote_peer_out_queue_bytes", Gauge, "current peer request bytes in outgoing queue to remote DC";
197 PeerMismatchRequests, "peer_mismatch_requests", Counter, "current dnode peer mismatched messages";
198 ForwardError, "forward_error", Counter, "# times we encountered a forwarding error";
199 Fragments, "fragments", Counter, "# fragments created from a multi-vector request";
200 StatsCount, "stats_count", Counter, "# stats request";
201});
202
203define_codec!(
204 ServerField, SERVER_CODEC,
205 "Const slice of every server metric descriptor in declaration order.",
206 "Typed handle for a server metric.",
207 {
208 ServerEof, "server_eof", Counter, "# eof on server connections";
209 ServerErr, "server_err", Counter, "# errors on server connections";
210 ServerTimedout, "server_timedout", Counter, "# timeouts on server connections";
211 ServerEjectedAt, "server_ejected_at", Timestamp, "timestamp when server was ejected in usec since epoch";
212 ServerDroppedRequests, "server_dropped_requests", Counter, "# server dropped requests";
213 ServerTimedoutRequests, "server_timedout_requests", Counter, "# server timedout requests";
214 ReadRequests, "read_requests", Counter, "# read requests";
215 ReadRequestBytes, "read_request_bytes", Counter, "total read request bytes";
216 WriteRequests, "write_requests", Counter, "# write requests";
217 WriteRequestBytes, "write_request_bytes", Counter, "total write request bytes";
218 ReadResponses, "read_responses", Counter, "# read respones";
219 ReadResponseBytes, "read_response_bytes", Counter, "total read response bytes";
220 WriteResponses, "write_responses", Counter, "# write respones";
221 WriteResponseBytes, "write_response_bytes", Counter, "total write response bytes";
222 InQueue, "in_queue", Gauge, "# requests in incoming queue";
223 InQueueBytes, "in_queue_bytes", Gauge, "current request bytes in incoming queue";
224 OutQueue, "out_queue", Gauge, "# requests in outgoing queue";
225 OutQueueBytes, "out_queue_bytes", Gauge, "current request bytes in outgoing queue";
226 RedisReqGet, "redis_req_get", Counter, "# Redis get";
227 RedisReqSet, "redis_req_set", Counter, "# Redis set";
228 RedisReqDel, "redis_req_del", Counter, "# Redis del";
229 RedisReqIncrDecr, "redis_req_incr_decr", Counter, "# Redis incr or decr";
230 RedisReqKeys, "redis_req_keys", Counter, "# Redis keys";
231 RedisReqMget, "redis_req_mget", Counter, "# Redis mget";
232 RedisReqScan, "redis_req_scan", Counter, "# Redis scan";
233 RedisReqSort, "redis_req_sort", Counter, "# Redis sort";
234 RedisReqLreqm, "redis_req_lreqm", Counter, "# Redis lreqm";
235 RedisReqSunion, "redis_req_sunion", Counter, "# Redis sunion";
236 RedisReqPing, "redis_req_ping", Counter, "# Redis ping";
237 RedisReqLists, "redis_req_lists", Counter, "# Redis lists";
238 RedisReqSets, "redis_req_sets", Counter, "# Redis sets";
239 RedisReqHashes, "redis_req_hashes", Counter, "# Redis hashes";
240 RedisReqSortedsets, "redis_req_sortedsets", Counter, "# Redis sortedsets";
241 RedisReqOther, "redis_req_other", Counter, "# Redis other";
242});
243
244#[cfg(test)]
245mod tests {
246 use super::*;
247
248 #[test]
249 fn pool_codec_indexes_align_with_variants() {
250 for (i, variant) in PoolField::ALL.iter().copied().enumerate() {
251 assert_eq!(variant.index(), i);
252 assert_eq!(variant.name(), POOL_CODEC[i].name);
253 assert_eq!(variant.kind(), POOL_CODEC[i].kind);
254 assert_eq!(variant.description(), POOL_CODEC[i].description);
255 }
256 }
257
258 #[test]
259 fn server_codec_indexes_align_with_variants() {
260 for (i, variant) in ServerField::ALL.iter().copied().enumerate() {
261 assert_eq!(variant.index(), i);
262 assert_eq!(variant.name(), SERVER_CODEC[i].name);
263 assert_eq!(variant.kind(), SERVER_CODEC[i].kind);
264 assert_eq!(variant.description(), SERVER_CODEC[i].description);
265 }
266 }
267
268 #[test]
269 fn pool_kinds_match_c_codec() {
270 assert_eq!(PoolField::ClientConnections.kind(), StatsMetricType::Gauge);
271 assert_eq!(PoolField::ClientEof.kind(), StatsMetricType::Counter);
272 assert_eq!(PoolField::PeerEjectedAt.kind(), StatsMetricType::Timestamp);
273 }
274
275 #[test]
276 fn pool_codec_has_expected_count() {
277 assert_eq!(POOL_CODEC.len(), PoolField::ALL.len());
278 }
279
280 #[test]
281 fn server_codec_has_expected_count() {
282 assert_eq!(SERVER_CODEC.len(), ServerField::ALL.len());
283 }
284}