forked from StellarRouter/StellarRouter
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmetrics.rs
More file actions
339 lines (282 loc) · 14 KB
/
Copy pathmetrics.rs
File metadata and controls
339 lines (282 loc) · 14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
//! Prometheus metric definitions for the stellar-router exporter.
//!
//! All metrics are registered against a caller-supplied [`prometheus::Registry`]
//! so that tests can use an isolated registry without polluting the global one.
use anyhow::Result;
use prometheus::{
register_counter_vec_with_registry, register_gauge_vec_with_registry,
register_gauge_with_registry, register_histogram_vec_with_registry, CounterVec, Gauge,
GaugeVec, HistogramVec, Registry,
};
/// Bucket boundaries (seconds) for the scrape-duration histogram.
///
/// Chosen to cover the typical Soroban RPC latency range (1 ms – 10 s).
const SCRAPE_DURATION_BUCKETS: &[f64] = &[
0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0,
];
/// All Prometheus metrics exposed by the exporter.
///
/// Clone is cheap — each field is an `Arc`-backed Prometheus metric handle.
#[derive(Clone)]
pub struct RouterMetrics {
// ── router-core ───────────────────────────────────────────────────────────
/// Cumulative number of successful `resolve` calls since contract init.
pub core_total_routed: GaugeVec,
/// 1 if the router is globally paused, 0 otherwise.
pub core_paused: GaugeVec,
/// 1 if a specific named route is paused, 0 otherwise.
pub core_route_paused: GaugeVec,
// ── router-middleware ─────────────────────────────────────────────────────
/// Cumulative number of `pre_call` invocations since contract init.
pub middleware_total_calls: GaugeVec,
/// Cumulative number of calls per route (from post_call events).
pub middleware_route_calls_total: CounterVec,
/// Cumulative number of failures per route (from post_call events).
pub middleware_route_failures_total: CounterVec,
/// 1 if the circuit breaker for a route is currently open, 0 otherwise.
pub middleware_circuit_open: GaugeVec,
/// Current consecutive failure count tracked by the circuit breaker.
pub middleware_failure_count: GaugeVec,
// ── router-registry ───────────────────────────────────────────────────────
/// Total number of contract names registered in the registry.
pub registry_total_names: GaugeVec,
/// Total number of versions registered under each contract name.
pub registry_version_count: GaugeVec,
// ── router-quote ──────────────────────────────────────────────────────────
/// Running total of `quote_generated` events observed.
pub quote_total_generated: CounterVec,
/// Running total of `fee_estimated` events observed.
pub quote_total_fee_estimated: CounterVec,
// ── router-execution ──────────────────────────────────────────────────────
/// Cumulative number of executions recorded in on-chain storage.
pub execution_total_executions: CounterVec,
/// Cumulative number of execution errors recorded in on-chain storage.
pub execution_total_errors: CounterVec,
/// Configured maximum retries read from on-chain storage.
pub execution_max_retries: GaugeVec,
// ── router-access ──────────────────────────────────────────────────────────
/// Number of indexed members ever added for a given role (`get_role_count`).
pub access_role_member_count: GaugeVec,
/// Number of distinct addresses currently stored on the blacklist.
pub access_blacklist_size: GaugeVec,
// ── router-timelock ─────────────────────────────────────────────────────────
/// Number of pending time-locked operations currently queued.
pub timelock_pending_operations: GaugeVec,
// ── router-multicall ────────────────────────────────────────────────────────
/// Total number of batches submitted to the multicall contract (`total_batches`).
pub multicall_total_batches: GaugeVec,
/// Cumulative number of successful calls observed in `call_result` events.
pub multicall_batch_success_total: CounterVec,
/// Cumulative number of failed calls observed in `call_result` events.
pub multicall_batch_failure_total: CounterVec,
// ── exporter health ───────────────────────────────────────────────────────
/// Time (seconds) spent scraping a single contract during the last cycle.
pub scrape_duration_seconds: HistogramVec,
/// Total number of failed scrape attempts per contract.
pub scrape_errors_total: CounterVec,
/// 1 if the most recent full scrape cycle completed without errors.
pub up: Gauge,
// ── SSE health ────────────────────────────────────────────────────────────
/// 1 if the SSE connection for a contract is currently established, 0 otherwise.
pub sse_connected: GaugeVec,
/// Total number of SSE reconnect attempts per contract since process start.
pub sse_reconnects_total: CounterVec,
/// Total number of SSE events received per contract since process start.
pub sse_events_total: CounterVec,
}
impl RouterMetrics {
/// Create and register all metrics against `registry`.
pub fn new(registry: &Registry) -> Result<Self> {
let core_total_routed = register_gauge_vec_with_registry!(
"router_core_total_routed",
"Cumulative number of successful route resolutions since contract initialization",
&["contract"],
registry
)?;
let core_paused = register_gauge_vec_with_registry!(
"router_core_paused",
"1 if the router-core contract is globally paused, 0 otherwise",
&["contract"],
registry
)?;
let core_route_paused = register_gauge_vec_with_registry!(
"router_core_route_paused",
"1 if a specific named route is paused, 0 otherwise",
&["contract", "route"],
registry
)?;
let middleware_total_calls = register_gauge_vec_with_registry!(
"router_middleware_total_calls",
"Cumulative number of pre_call invocations since contract initialization",
&["contract"],
registry
)?;
let middleware_route_calls_total = register_counter_vec_with_registry!(
"router_middleware_route_calls_total",
"Cumulative number of calls per route from post_call events",
&["contract", "route"],
registry
)?;
let middleware_route_failures_total = register_counter_vec_with_registry!(
"router_middleware_route_failures_total",
"Cumulative number of failures per route from post_call events",
&["contract", "route"],
registry
)?;
let middleware_circuit_open = register_gauge_vec_with_registry!(
"router_middleware_circuit_open",
"1 if the circuit breaker for a route is currently open, 0 otherwise",
&["contract", "route"],
registry
)?;
let middleware_failure_count = register_gauge_vec_with_registry!(
"router_middleware_failure_count",
"Current consecutive failure count tracked by the circuit breaker for a route",
&["contract", "route"],
registry
)?;
let registry_total_names = register_gauge_vec_with_registry!(
"router_registry_total_names",
"Total number of contract names registered in the router-registry",
&["contract"],
registry
)?;
let registry_version_count = register_gauge_vec_with_registry!(
"router_registry_version_count",
"Total number of versions registered under a contract name in the router-registry",
&["contract", "name"],
registry
)?;
let quote_total_generated = register_counter_vec_with_registry!(
"router_quote_total_generated",
"Running total of quote_generated events observed from router-quote",
&["contract"],
registry
)?;
let quote_total_fee_estimated = register_counter_vec_with_registry!(
"router_quote_total_fee_estimated",
"Running total of fee_estimated events observed from router-quote",
&["contract"],
registry
)?;
let execution_total_executions = register_counter_vec_with_registry!(
"router_execution_total_executions",
"Cumulative number of executions recorded in router-execution on-chain storage",
&["contract"],
registry
)?;
let execution_total_errors = register_counter_vec_with_registry!(
"router_execution_total_errors",
"Cumulative number of execution errors recorded in router-execution on-chain storage",
&["contract"],
registry
)?;
let execution_max_retries = register_gauge_vec_with_registry!(
"router_execution_max_retries",
"Configured maximum retries read from router-execution on-chain storage",
&["contract"],
registry
)?;
let access_role_member_count = register_gauge_vec_with_registry!(
"router_access_role_member_count",
"Number of indexed members ever added for a role in router-access (get_role_count)",
&["contract", "role"],
registry
)?;
let access_blacklist_size = register_gauge_vec_with_registry!(
"router_access_blacklist_size",
"Number of distinct addresses currently stored on the router-access blacklist",
&["contract"],
registry
)?;
let timelock_pending_operations = register_gauge_vec_with_registry!(
"router_timelock_pending_operations",
"Number of pending time-locked operations currently queued in router-timelock",
&["contract"],
registry
)?;
let multicall_total_batches = register_gauge_vec_with_registry!(
"router_multicall_total_batches",
"Total number of batches submitted to router-multicall (total_batches)",
&["contract"],
registry
)?;
let multicall_batch_success_total = register_counter_vec_with_registry!(
"router_multicall_batch_success_total",
"Cumulative number of successful calls observed in router-multicall call_result events",
&["contract"],
registry
)?;
let multicall_batch_failure_total = register_counter_vec_with_registry!(
"router_multicall_batch_failure_total",
"Cumulative number of failed calls observed in router-multicall call_result events",
&["contract"],
registry
)?;
let scrape_duration_seconds = register_histogram_vec_with_registry!(
"router_scrape_duration_seconds",
"Time in seconds spent scraping a single router contract",
&["contract"],
SCRAPE_DURATION_BUCKETS.to_vec(),
registry
)?;
let scrape_errors_total = register_counter_vec_with_registry!(
"router_scrape_errors_total",
"Total number of failed scrape attempts per contract",
&["contract"],
registry
)?;
let up = register_gauge_with_registry!(
"router_up",
"1 if the most recent full scrape cycle completed without errors, 0 otherwise",
registry
)?;
let sse_connected = register_gauge_vec_with_registry!(
"router_sse_connected",
"1 if the SSE connection for a contract is currently established, 0 otherwise",
&["contract"],
registry
)?;
let sse_reconnects_total = register_counter_vec_with_registry!(
"router_sse_reconnects_total",
"Total number of SSE reconnect attempts per contract since process start",
&["contract"],
registry
)?;
let sse_events_total = register_counter_vec_with_registry!(
"router_sse_events_total",
"Total number of SSE events received per contract since process start",
&["contract"],
registry
)?;
Ok(Self {
core_total_routed,
core_paused,
core_route_paused,
middleware_total_calls,
middleware_route_calls_total,
middleware_route_failures_total,
middleware_circuit_open,
middleware_failure_count,
registry_total_names,
registry_version_count,
quote_total_generated,
quote_total_fee_estimated,
execution_total_executions,
execution_total_errors,
execution_max_retries,
access_role_member_count,
access_blacklist_size,
timelock_pending_operations,
multicall_total_batches,
multicall_batch_success_total,
multicall_batch_failure_total,
scrape_duration_seconds,
scrape_errors_total,
up,
sse_connected,
sse_reconnects_total,
sse_events_total,
})
}
}