From a85ed3bb4c739e80708198a341249e847fa1239a Mon Sep 17 00:00:00 2001 From: Oleh Fomenko Date: Thu, 23 Jul 2026 01:17:10 +0300 Subject: [PATCH 1/4] [metrics] Bump cln_rpc crate to 0.7. Using ForwardEventNotification from cln_rpc, instead of defining the custom one. Co-authored-by: Oleg Fomenko --- Cargo.lock | 4 ++-- metrics-plugin/Cargo.toml | 2 +- metrics-plugin/src/events.rs | 16 ++++++---------- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 87388d3..29d8e3a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -526,9 +526,9 @@ dependencies = [ [[package]] name = "cln-rpc" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8c63eb175d58f0212e35e427237cf3e4f856f47ec7b8ad95110484d292fc819" +checksum = "5d9f5e26f0a2713ea1393eb3117c148295fa4c5f7db529713b20323ca7cc37aa" dependencies = [ "anyhow", "bitcoin", diff --git a/metrics-plugin/Cargo.toml b/metrics-plugin/Cargo.toml index c4a79f0..2ba1cc4 100644 --- a/metrics-plugin/Cargo.toml +++ b/metrics-plugin/Cargo.toml @@ -11,7 +11,7 @@ path = "src/main.rs" [dependencies] cln-plugin = { version = "0.7" } -cln-rpc = { version = "0.6" } +cln-rpc = { version = "0.7" } prometheus = { version = "0.14" } axum = { version = "0.8" } tokio = { version = "1", features = ["full"] } diff --git a/metrics-plugin/src/events.rs b/metrics-plugin/src/events.rs index c55c81f..5546cbf 100644 --- a/metrics-plugin/src/events.rs +++ b/metrics-plugin/src/events.rs @@ -1,19 +1,14 @@ use anyhow::Result; use cln_plugin::Plugin; -use cln_rpc::notifications::ChannelStateChangedNotification; +use cln_rpc::notifications::{ChannelStateChangedNotification, ForwardEventNotification}; use serde::Deserialize; use serde_json::{Value, json}; use crate::PluginState; #[derive(Deserialize)] -struct ForwardEventNotification { - forward_event: ForwardEvent, -} - -#[derive(Deserialize)] -struct ForwardEvent { - status: String, +struct ForwardEventNotificationWrapper { + forward_event: ForwardEventNotification, } #[derive(Deserialize)] @@ -27,12 +22,13 @@ pub async fn on_channel_opened(plugin: Plugin, _v: Value) -> Result } pub async fn on_forward_event(plugin: Plugin, v: Value) -> Result<()> { - let n: ForwardEventNotification = serde_json::from_value(v)?; + let n: ForwardEventNotificationWrapper = serde_json::from_value(v)?; + plugin .state() .counters .forward_events_total - .with_label_values(&[&n.forward_event.status]) + .with_label_values(&[serde_json::to_string(&n.forward_event.status)?]) .inc(); Ok(()) } From 9b5820826b6f6f43e053f51fe22e0a5152131a0a Mon Sep 17 00:00:00 2001 From: Oleh Fomenko Date: Thu, 23 Jul 2026 01:20:31 +0300 Subject: [PATCH 2/4] [metrics] Move the logic for incrementing the counter into the counter itself, instead of executing it in hook handlers. Co-authored-by: Oleg Fomenko --- metrics-plugin/src/events.rs | 31 ++++--------------------------- metrics-plugin/src/metrics.rs | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/metrics-plugin/src/events.rs b/metrics-plugin/src/events.rs index 5546cbf..dcf07a3 100644 --- a/metrics-plugin/src/events.rs +++ b/metrics-plugin/src/events.rs @@ -17,50 +17,27 @@ struct ChannelStateChangedWrapper { } pub async fn on_channel_opened(plugin: Plugin, _v: Value) -> Result<()> { - plugin.state().counters.channel_opened_total.inc(); + plugin.state().counters.on_channel_opened(); Ok(()) } pub async fn on_forward_event(plugin: Plugin, v: Value) -> Result<()> { let n: ForwardEventNotificationWrapper = serde_json::from_value(v)?; - - plugin - .state() - .counters - .forward_events_total - .with_label_values(&[serde_json::to_string(&n.forward_event.status)?]) - .inc(); + plugin.state().counters.on_forward_event(&n.forward_event); Ok(()) } // CLN hook - must return {"result": "continue"} or the HTLC will be rejected by the node pub async fn hook_htlc_accepted(plugin: Plugin, _v: Value) -> Result { - plugin.state().counters.htlc_accepted_total.inc(); + plugin.state().counters.on_htlc_accepted(); Ok(json!({ "result": "continue" })) } pub async fn on_channel_state_changed(plugin: Plugin, v: Value) -> Result<()> { let n: ChannelStateChangedWrapper = serde_json::from_value(v)?; - let c = n.channel_state_changed; - - let old = c - .old_state - .map(|s| s.to_string()) - .unwrap_or_else(|| "unknown".to_string()); - let new = c.new_state.to_string(); - plugin .state() .counters - .channel_state_changes_total - .with_label_values(&[&old, &new]) - .inc(); - - tracing::info!( - peer = %c.peer_id, - old_state = old, - new_state = new, - "channel_state_changed" - ); + .on_channel_state_changed(&n.channel_state_changed); Ok(()) } diff --git a/metrics-plugin/src/metrics.rs b/metrics-plugin/src/metrics.rs index e1bc7ee..ba713ae 100644 --- a/metrics-plugin/src/metrics.rs +++ b/metrics-plugin/src/metrics.rs @@ -11,6 +11,7 @@ use prometheus::{ proto::MetricFamily, }; use std::sync::{Arc, RwLock}; +use cln_rpc::notifications::{ChannelStateChangedNotification, ForwardEventNotification}; use tokio::net::TcpListener; use tracing::error; @@ -85,6 +86,39 @@ impl EventCounters { )?)?, }) } + + pub fn on_forward_event(&self, event: &ForwardEventNotification) { + self.forward_events_total + .with_label_values(&[event.status.to_string()]) + .inc(); + } + + pub fn on_channel_opened(&self) { + self.channel_opened_total.inc() + } + + pub fn on_channel_state_changed(&self, event: &ChannelStateChangedNotification) { + let old = event + .old_state + .map(|s| s.to_string()) + .unwrap_or_else(|| "unknown".to_string()); + let new = event.new_state.to_string(); + + self.channel_state_changes_total + .with_label_values(&[&old, &new]) + .inc(); + + tracing::info!( + peer = %event.peer_id, + old_state = old, + new_state = new, + "channel_state_changed" + ); + } + + pub fn on_htlc_accepted(&self) { + self.htlc_accepted_total.inc(); + } } /// Registers the build_info gauge with the global registry and pins it to 1.0. From 4f214bc20e1e0ab1b268ee81f4e98ebd3f8da47e Mon Sep 17 00:00:00 2001 From: Oleh Fomenko Date: Thu, 23 Jul 2026 01:20:48 +0300 Subject: [PATCH 3/4] [metrics] Small ref Co-authored-by: Oleg Fomenko --- metrics-plugin/src/events.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metrics-plugin/src/events.rs b/metrics-plugin/src/events.rs index dcf07a3..5a5d3f3 100644 --- a/metrics-plugin/src/events.rs +++ b/metrics-plugin/src/events.rs @@ -27,9 +27,9 @@ pub async fn on_forward_event(plugin: Plugin, v: Value) -> Result<( Ok(()) } -// CLN hook - must return {"result": "continue"} or the HTLC will be rejected by the node pub async fn hook_htlc_accepted(plugin: Plugin, _v: Value) -> Result { plugin.state().counters.on_htlc_accepted(); + // CLN hook - must return {"result": "continue"} or the HTLC will be rejected by the node Ok(json!({ "result": "continue" })) } From a042b7938d335a053c8bc4ed124f4c28d0a5a701 Mon Sep 17 00:00:00 2001 From: Oleh Fomenko Date: Thu, 23 Jul 2026 15:10:14 +0300 Subject: [PATCH 4/4] [events] cargo fmt Co-authored-by: Oleg Fomenko --- metrics-plugin/src/main.rs | 6 +----- metrics-plugin/src/metrics.rs | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/metrics-plugin/src/main.rs b/metrics-plugin/src/main.rs index 61d11bb..98d126f 100644 --- a/metrics-plugin/src/main.rs +++ b/metrics-plugin/src/main.rs @@ -55,11 +55,7 @@ async fn main() -> Result<()> { .subscribe("forward_event", events::on_forward_event) .subscribe("channel_state_changed", events::on_channel_state_changed) .hook("htlc_accepted", events::hook_htlc_accepted) - .rpcmethod( - "metrics-status", - "Get metrics plugin status", - rpc_status, - ) + .rpcmethod("metrics-status", "Get metrics plugin status", rpc_status) .dynamic() .configure() .await?; diff --git a/metrics-plugin/src/metrics.rs b/metrics-plugin/src/metrics.rs index ba713ae..ba1b50f 100644 --- a/metrics-plugin/src/metrics.rs +++ b/metrics-plugin/src/metrics.rs @@ -5,13 +5,13 @@ use axum::{ response::{IntoResponse, Response}, routing::get, }; +use cln_rpc::notifications::{ChannelStateChangedNotification, ForwardEventNotification}; use prometheus::{ Encoder, Gauge, GaugeVec, IntCounter, IntCounterVec, Opts, TextEncoder, core::{Collector, Desc}, proto::MetricFamily, }; use std::sync::{Arc, RwLock}; -use cln_rpc::notifications::{ChannelStateChangedNotification, ForwardEventNotification}; use tokio::net::TcpListener; use tracing::error;