|
14 | 14 | // You should have received a copy of the GNU General Public License
|
15 | 15 | // along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16 | 16 |
|
17 |
| -#[cfg(feature = "monitoring_prom")] |
18 |
| -use ::prometheus::HistogramTimer; |
19 |
| -#[cfg(feature = "monitoring_prom")] |
20 |
| -use slog::slog_error; |
21 |
| -#[cfg(not(feature = "monitoring_prom"))] |
22 |
| -use slog::slog_info; |
23 |
| -#[cfg(feature = "monitoring_prom")] |
24 |
| -use stacks_common::error; |
25 |
| -#[cfg(not(feature = "monitoring_prom"))] |
26 |
| -use stacks_common::info; |
27 |
| - |
28 |
| -use crate::config::GlobalConfig; |
29 |
| - |
30 | 17 | #[cfg(feature = "monitoring_prom")]
|
31 | 18 | mod prometheus;
|
32 | 19 |
|
33 | 20 | #[cfg(feature = "monitoring_prom")]
|
34 | 21 | mod server;
|
35 | 22 |
|
36 |
| -/// Update stacks tip height gauge |
37 |
| -#[allow(unused_variables)] |
38 |
| -pub fn update_stacks_tip_height(height: i64) { |
39 |
| - #[cfg(feature = "monitoring_prom")] |
40 |
| - prometheus::STACKS_TIP_HEIGHT_GAUGE.set(height); |
41 |
| -} |
| 23 | +/// Actions for updating metrics |
| 24 | +#[cfg(feature = "monitoring_prom")] |
| 25 | +pub mod actions { |
| 26 | + use ::prometheus::HistogramTimer; |
| 27 | + use blockstack_lib::chainstate::nakamoto::NakamotoBlock; |
| 28 | + use slog::slog_error; |
| 29 | + use stacks_common::error; |
| 30 | + |
| 31 | + use crate::config::GlobalConfig; |
| 32 | + use crate::monitoring::prometheus::*; |
| 33 | + |
| 34 | + /// Update stacks tip height gauge |
| 35 | + pub fn update_stacks_tip_height(height: i64) { |
| 36 | + STACKS_TIP_HEIGHT_GAUGE.set(height); |
| 37 | + } |
42 | 38 |
|
43 |
| -/// Update the current reward cycle |
44 |
| -#[allow(unused_variables)] |
45 |
| -pub fn update_reward_cycle(reward_cycle: i64) { |
46 |
| - #[cfg(feature = "monitoring_prom")] |
47 |
| - prometheus::CURRENT_REWARD_CYCLE.set(reward_cycle); |
48 |
| -} |
| 39 | + /// Update the current reward cycle |
| 40 | + pub fn update_reward_cycle(reward_cycle: i64) { |
| 41 | + CURRENT_REWARD_CYCLE.set(reward_cycle); |
| 42 | + } |
49 | 43 |
|
50 |
| -/// Increment the block validation responses counter |
51 |
| -#[allow(unused_variables)] |
52 |
| -pub fn increment_block_validation_responses(accepted: bool) { |
53 |
| - #[cfg(feature = "monitoring_prom")] |
54 |
| - { |
| 44 | + /// Increment the block validation responses counter |
| 45 | + pub fn increment_block_validation_responses(accepted: bool) { |
55 | 46 | let label_value = if accepted { "accepted" } else { "rejected" };
|
56 |
| - prometheus::BLOCK_VALIDATION_RESPONSES |
| 47 | + BLOCK_VALIDATION_RESPONSES |
57 | 48 | .with_label_values(&[label_value])
|
58 | 49 | .inc();
|
59 | 50 | }
|
60 |
| -} |
61 | 51 |
|
62 |
| -/// Increment the block responses sent counter |
63 |
| -#[allow(unused_variables)] |
64 |
| -pub fn increment_block_responses_sent(accepted: bool) { |
65 |
| - #[cfg(feature = "monitoring_prom")] |
66 |
| - { |
| 52 | + /// Increment the block responses sent counter |
| 53 | + pub fn increment_block_responses_sent(accepted: bool) { |
67 | 54 | let label_value = if accepted { "accepted" } else { "rejected" };
|
68 |
| - prometheus::BLOCK_RESPONSES_SENT |
69 |
| - .with_label_values(&[label_value]) |
70 |
| - .inc(); |
| 55 | + BLOCK_RESPONSES_SENT.with_label_values(&[label_value]).inc(); |
71 | 56 | }
|
72 |
| -} |
73 | 57 |
|
74 |
| -/// Increment the number of block proposals received |
75 |
| -#[allow(unused_variables)] |
76 |
| -pub fn increment_block_proposals_received() { |
77 |
| - #[cfg(feature = "monitoring_prom")] |
78 |
| - prometheus::BLOCK_PROPOSALS_RECEIVED.inc(); |
79 |
| -} |
80 |
| - |
81 |
| -/// Update the stx balance of the signer |
82 |
| -#[allow(unused_variables)] |
83 |
| -pub fn update_signer_stx_balance(balance: i64) { |
84 |
| - #[cfg(feature = "monitoring_prom")] |
85 |
| - prometheus::SIGNER_STX_BALANCE.set(balance); |
86 |
| -} |
| 58 | + /// Increment the number of block proposals received |
| 59 | + pub fn increment_block_proposals_received() { |
| 60 | + BLOCK_PROPOSALS_RECEIVED.inc(); |
| 61 | + } |
87 | 62 |
|
88 |
| -/// Update the signer nonce metric |
89 |
| -#[allow(unused_variables)] |
90 |
| -pub fn update_signer_nonce(nonce: u64) { |
91 |
| - #[cfg(feature = "monitoring_prom")] |
92 |
| - prometheus::SIGNER_NONCE.set(nonce as i64); |
93 |
| -} |
| 63 | + /// Update the stx balance of the signer |
| 64 | + pub fn update_signer_stx_balance(balance: i64) { |
| 65 | + SIGNER_STX_BALANCE.set(balance); |
| 66 | + } |
94 | 67 |
|
95 |
| -// Allow dead code because this is only used in the `monitoring_prom` feature |
96 |
| -// but we want to run it in a test |
97 |
| -#[allow(dead_code)] |
98 |
| -/// Remove the origin from the full path to avoid duplicate metrics for different origins |
99 |
| -fn remove_origin_from_path(full_path: &str, origin: &str) -> String { |
100 |
| - full_path.replace(origin, "") |
101 |
| -} |
| 68 | + /// Update the signer nonce metric |
| 69 | + pub fn update_signer_nonce(nonce: u64) { |
| 70 | + SIGNER_NONCE.set(nonce as i64); |
| 71 | + } |
102 | 72 |
|
103 |
| -/// Start a new RPC call timer. |
104 |
| -/// The `origin` parameter is the base path of the RPC call, e.g. `http://node.com`. |
105 |
| -/// The `origin` parameter is removed from `full_path` when storing in prometheus. |
106 |
| -#[cfg(feature = "monitoring_prom")] |
107 |
| -pub fn new_rpc_call_timer(full_path: &str, origin: &str) -> HistogramTimer { |
108 |
| - let path = remove_origin_from_path(full_path, origin); |
109 |
| - let histogram = prometheus::SIGNER_RPC_CALL_LATENCIES_HISTOGRAM.with_label_values(&[&path]); |
110 |
| - histogram.start_timer() |
111 |
| -} |
| 73 | + /// Start a new RPC call timer. |
| 74 | + /// The `origin` parameter is the base path of the RPC call, e.g. `http://node.com`. |
| 75 | + /// The `origin` parameter is removed from `full_path` when storing in prometheus. |
| 76 | + pub fn new_rpc_call_timer(full_path: &str, origin: &str) -> HistogramTimer { |
| 77 | + let path = super::remove_origin_from_path(full_path, origin); |
| 78 | + let histogram = SIGNER_RPC_CALL_LATENCIES_HISTOGRAM.with_label_values(&[&path]); |
| 79 | + histogram.start_timer() |
| 80 | + } |
112 | 81 |
|
113 |
| -/// NoOp timer uses for monitoring when the monitoring feature is not enabled. |
114 |
| -pub struct NoOpTimer; |
115 |
| -impl NoOpTimer { |
116 |
| - /// NoOp method to stop recording when the monitoring feature is not enabled. |
117 |
| - pub fn stop_and_record(&self) {} |
118 |
| -} |
| 82 | + /// Record the time taken to issue a block response for |
| 83 | + /// a given block. The block's timestamp is used to calculate the latency. |
| 84 | + /// |
| 85 | + /// Call this right after broadcasting a BlockResponse |
| 86 | + pub fn record_block_response_latency(block: &NakamotoBlock) { |
| 87 | + use clarity::util::get_epoch_time_ms; |
| 88 | + |
| 89 | + let diff = |
| 90 | + get_epoch_time_ms().saturating_sub(block.header.timestamp.saturating_mul(1000).into()); |
| 91 | + SIGNER_BLOCK_RESPONSE_LATENCIES_HISTOGRAM |
| 92 | + .with_label_values(&[]) |
| 93 | + .observe(diff as f64 / 1000.0); |
| 94 | + } |
119 | 95 |
|
120 |
| -/// Stop and record the no-op timer. |
121 |
| -#[cfg(not(feature = "monitoring_prom"))] |
122 |
| -pub fn new_rpc_call_timer(_full_path: &str, _origin: &str) -> NoOpTimer { |
123 |
| - NoOpTimer |
124 |
| -} |
| 96 | + /// Record the time taken to validate a block, as reported by the Stacks node. |
| 97 | + pub fn record_block_validation_latency(latency_ms: u64) { |
| 98 | + SIGNER_BLOCK_VALIDATION_LATENCIES_HISTOGRAM |
| 99 | + .with_label_values(&[]) |
| 100 | + .observe(latency_ms as f64 / 1000.0); |
| 101 | + } |
125 | 102 |
|
126 |
| -/// Start serving monitoring metrics. |
127 |
| -/// This will only serve the metrics if the `monitoring_prom` feature is enabled. |
128 |
| -#[allow(unused_variables)] |
129 |
| -pub fn start_serving_monitoring_metrics(config: GlobalConfig) -> Result<(), String> { |
130 |
| - #[cfg(feature = "monitoring_prom")] |
131 |
| - { |
| 103 | + /// Start serving monitoring metrics. |
| 104 | + /// This will only serve the metrics if the `monitoring_prom` feature is enabled. |
| 105 | + pub fn start_serving_monitoring_metrics(config: GlobalConfig) -> Result<(), String> { |
132 | 106 | if config.metrics_endpoint.is_none() {
|
133 | 107 | return Ok(());
|
134 | 108 | }
|
135 |
| - let thread = std::thread::Builder::new() |
| 109 | + let _ = std::thread::Builder::new() |
136 | 110 | .name("signer_metrics".to_string())
|
137 | 111 | .spawn(move || {
|
138 |
| - if let Err(monitoring_err) = server::MonitoringServer::start(&config) { |
| 112 | + if let Err(monitoring_err) = super::server::MonitoringServer::start(&config) { |
139 | 113 | error!("Monitoring: Error in metrics server: {:?}", monitoring_err);
|
140 | 114 | }
|
141 | 115 | });
|
| 116 | + Ok(()) |
| 117 | + } |
| 118 | +} |
| 119 | + |
| 120 | +/// No-op actions for updating metrics |
| 121 | +#[cfg(not(feature = "monitoring_prom"))] |
| 122 | +pub mod actions { |
| 123 | + use blockstack_lib::chainstate::nakamoto::NakamotoBlock; |
| 124 | + use slog::slog_info; |
| 125 | + use stacks_common::info; |
| 126 | + |
| 127 | + use crate::GlobalConfig; |
| 128 | + |
| 129 | + /// Update stacks tip height gauge |
| 130 | + pub fn update_stacks_tip_height(_height: i64) {} |
| 131 | + |
| 132 | + /// Update the current reward cycle |
| 133 | + pub fn update_reward_cycle(_reward_cycle: i64) {} |
| 134 | + |
| 135 | + /// Increment the block validation responses counter |
| 136 | + pub fn increment_block_validation_responses(_accepted: bool) {} |
| 137 | + |
| 138 | + /// Increment the block responses sent counter |
| 139 | + pub fn increment_block_responses_sent(_accepted: bool) {} |
| 140 | + |
| 141 | + /// Increment the number of block proposals received |
| 142 | + pub fn increment_block_proposals_received() {} |
| 143 | + |
| 144 | + /// Update the stx balance of the signer |
| 145 | + pub fn update_signer_stx_balance(_balance: i64) {} |
| 146 | + |
| 147 | + /// Update the signer nonce metric |
| 148 | + pub fn update_signer_nonce(_nonce: u64) {} |
| 149 | + |
| 150 | + /// NoOp timer uses for monitoring when the monitoring feature is not enabled. |
| 151 | + pub struct NoOpTimer; |
| 152 | + impl NoOpTimer { |
| 153 | + /// NoOp method to stop recording when the monitoring feature is not enabled. |
| 154 | + pub fn stop_and_record(&self) {} |
| 155 | + } |
| 156 | + |
| 157 | + /// Stop and record the no-op timer. |
| 158 | + pub fn new_rpc_call_timer(_full_path: &str, _origin: &str) -> NoOpTimer { |
| 159 | + NoOpTimer |
142 | 160 | }
|
143 |
| - #[cfg(not(feature = "monitoring_prom"))] |
144 |
| - { |
| 161 | + |
| 162 | + /// Record the time taken to issue a block response for |
| 163 | + /// a given block. The block's timestamp is used to calculate the latency. |
| 164 | + /// |
| 165 | + /// Call this right after broadcasting a BlockResponse |
| 166 | + pub fn record_block_response_latency(_block: &NakamotoBlock) {} |
| 167 | + |
| 168 | + /// Record the time taken to validate a block, as reported by the Stacks node. |
| 169 | + pub fn record_block_validation_latency(_latency_ms: u64) {} |
| 170 | + |
| 171 | + /// Start serving monitoring metrics. |
| 172 | + /// This will only serve the metrics if the `monitoring_prom` feature is enabled. |
| 173 | + pub fn start_serving_monitoring_metrics(config: GlobalConfig) -> Result<(), String> { |
145 | 174 | if config.metrics_endpoint.is_some() {
|
146 | 175 | info!("`metrics_endpoint` is configured for the signer, but the monitoring_prom feature is not enabled. Not starting monitoring metrics server.");
|
147 | 176 | }
|
| 177 | + Ok(()) |
148 | 178 | }
|
149 |
| - Ok(()) |
| 179 | +} |
| 180 | + |
| 181 | +// Allow dead code because this is only used in the `monitoring_prom` feature |
| 182 | +// but we want to run it in a test |
| 183 | +#[allow(dead_code)] |
| 184 | +/// Remove the origin from the full path to avoid duplicate metrics for different origins |
| 185 | +fn remove_origin_from_path(full_path: &str, origin: &str) -> String { |
| 186 | + full_path.replace(origin, "") |
150 | 187 | }
|
151 | 188 |
|
152 | 189 | #[test]
|
|
0 commit comments