sc_rpc_spec_v2/transaction/
metrics.rs1use std::{collections::HashSet, time::Instant};
22
23use prometheus_endpoint::{
24 exponential_buckets, linear_buckets, register, Histogram, HistogramOpts, PrometheusError,
25 Registry,
26};
27
28use super::TransactionEvent;
29
30#[derive(Debug, Clone)]
32pub struct Metrics {
33 validated: Histogram,
34 in_block: Histogram,
35 finalized: Histogram,
36 dropped: Histogram,
37 invalid: Histogram,
38 error: Histogram,
39}
40
41impl Metrics {
42 pub fn new(registry: &Registry) -> Result<Self, PrometheusError> {
44 let validated = register(
45 Histogram::with_opts(
46 HistogramOpts::new(
47 "rpc_transaction_validation_time",
48 "RPC Transaction validation time in seconds",
49 )
50 .buckets(exponential_buckets(0.01, 2.0, 16).expect("Valid buckets; qed")),
51 )?,
52 registry,
53 )?;
54
55 let in_block = register(
56 Histogram::with_opts(
57 HistogramOpts::new(
58 "rpc_transaction_in_block_time",
59 "RPC Transaction in block time in seconds",
60 )
61 .buckets(linear_buckets(0.0, 3.0, 20).expect("Valid buckets; qed")),
62 )?,
63 registry,
64 )?;
65
66 let finalized = register(
67 Histogram::with_opts(
68 HistogramOpts::new(
69 "rpc_transaction_finalized_time",
70 "RPC Transaction finalized time in seconds",
71 )
72 .buckets(linear_buckets(0.01, 40.0, 20).expect("Valid buckets; qed")),
73 )?,
74 registry,
75 )?;
76
77 let dropped = register(
78 Histogram::with_opts(
79 HistogramOpts::new(
80 "rpc_transaction_dropped_time",
81 "RPC Transaction dropped time in seconds",
82 )
83 .buckets(linear_buckets(0.01, 3.0, 20).expect("Valid buckets; qed")),
84 )?,
85 registry,
86 )?;
87
88 let invalid = register(
89 Histogram::with_opts(
90 HistogramOpts::new(
91 "rpc_transaction_invalid_time",
92 "RPC Transaction invalid time in seconds",
93 )
94 .buckets(linear_buckets(0.01, 3.0, 20).expect("Valid buckets; qed")),
95 )?,
96 registry,
97 )?;
98
99 let error = register(
100 Histogram::with_opts(
101 HistogramOpts::new(
102 "rpc_transaction_error_time",
103 "RPC Transaction error time in seconds",
104 )
105 .buckets(linear_buckets(0.01, 3.0, 20).expect("Valid buckets; qed")),
106 )?,
107 registry,
108 )?;
109
110 Ok(Metrics { validated, in_block, finalized, dropped, invalid, error })
111 }
112}
113
114pub struct InstanceMetrics {
116 metrics: Option<Metrics>,
118 submitted_at: Instant,
120 reported_states: HashSet<&'static str>,
122}
123
124impl InstanceMetrics {
125 pub fn new(metrics: Option<Metrics>) -> Self {
127 Self { metrics, submitted_at: Instant::now(), reported_states: HashSet::new() }
128 }
129
130 pub fn register_event<Hash>(&mut self, event: &TransactionEvent<Hash>) {
136 let Some(ref metrics) = self.metrics else {
137 return;
138 };
139
140 let (histogram, target_state) = match event {
141 TransactionEvent::Validated => (&metrics.validated, "validated"),
142 TransactionEvent::BestChainBlockIncluded(Some(_)) => (&metrics.in_block, "in_block"),
143 TransactionEvent::BestChainBlockIncluded(None) => (&metrics.in_block, "retracted"),
144 TransactionEvent::Finalized(..) => (&metrics.finalized, "finalized"),
145 TransactionEvent::Error(..) => (&metrics.error, "error"),
146 TransactionEvent::Dropped(..) => (&metrics.dropped, "dropped"),
147 TransactionEvent::Invalid(..) => (&metrics.invalid, "invalid"),
148 };
149
150 if self.reported_states.insert(target_state) {
152 histogram.observe(self.submitted_at.elapsed().as_secs_f64());
153 }
154 }
155}