From b9a1c9859b831be1e393b8b052d02bba83cb8790 Mon Sep 17 00:00:00 2001 From: Lee Smet Date: Tue, 28 May 2024 14:31:00 +0200 Subject: [PATCH] Swap myceliumd-private metrics to mycelium-metrics Signed-off-by: Lee Smet --- myceliumd-private/Cargo.lock | 13 +- myceliumd-private/Cargo.toml | 4 +- myceliumd-private/src/main.rs | 5 +- myceliumd-private/src/metrics.rs | 403 ------------------------------- 4 files changed, 15 insertions(+), 410 deletions(-) delete mode 100644 myceliumd-private/src/metrics.rs diff --git a/myceliumd-private/Cargo.lock b/myceliumd-private/Cargo.lock index 66b737e..ce9d940 100644 --- a/myceliumd-private/Cargo.lock +++ b/myceliumd-private/Cargo.lock @@ -1038,6 +1038,17 @@ dependencies = [ "x25519-dalek", ] +[[package]] +name = "mycelium-metrics" +version = "0.5.2" +dependencies = [ + "axum", + "mycelium", + "prometheus", + "tokio", + "tracing", +] + [[package]] name = "myceliumd-private" version = "0.5.2" @@ -1046,7 +1057,7 @@ dependencies = [ "base64", "clap", "mycelium", - "prometheus", + "mycelium-metrics", "reqwest", "serde", "serde_json", diff --git a/myceliumd-private/Cargo.toml b/myceliumd-private/Cargo.toml index 00acb8d..2932643 100644 --- a/myceliumd-private/Cargo.toml +++ b/myceliumd-private/Cargo.toml @@ -18,6 +18,7 @@ clap = { version = "4.5.4", features = ["derive"] } tracing = { version = "0.1.40", features = ["release_max_level_debug"] } tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } mycelium = { path = "../mycelium", features = ["private-network", "message"] } +mycelium-metrics = { path = "../mycelium-metrics", features = ["prometheus"] } serde = { version = "1.0.203", features = ["derive"] } serde_json = "1.0.117" tokio = { version = "1.37.0", features = [ @@ -34,6 +35,3 @@ axum = { version = "0.7.5", default-features = false, features = [ "tokio", ] } base64 = "0.22.1" -prometheus = { version = "0.13.4", default-features = false, features = [ - "process", -] } diff --git a/myceliumd-private/src/main.rs b/myceliumd-private/src/main.rs index 347045e..d974e76 100644 --- a/myceliumd-private/src/main.rs +++ b/myceliumd-private/src/main.rs @@ -23,7 +23,6 @@ use tracing_subscriber::{EnvFilter, Layer}; mod api; mod cli; -mod metrics; /// The default port on the underlay to listen on for incoming TCP connections. const DEFAULT_TCP_LISTEN_PORT: u16 = 9651; @@ -323,7 +322,7 @@ async fn main() -> Result<(), Box> { }; let _api = if let Some(metrics_api_addr) = cli.node_args.metrics_api_address { - let metrics = metrics::PrometheusExporter::new(); + let metrics = mycelium_metrics::PrometheusExporter::new(); let config = mycelium::Config { node_key: node_secret_key, peers: cli.node_args.static_peers, @@ -357,7 +356,7 @@ async fn main() -> Result<(), Box> { }, tun_name: cli.node_args.tun_name, private_network_config, - metrics: metrics::NoMetrics, + metrics: mycelium_metrics::NoMetrics, firewall_mark: cli.node_args.firewall_mark, }; let node = Node::new(config).await?; diff --git a/myceliumd-private/src/metrics.rs b/myceliumd-private/src/metrics.rs deleted file mode 100644 index 7b3b17b..0000000 --- a/myceliumd-private/src/metrics.rs +++ /dev/null @@ -1,403 +0,0 @@ -//! Implementations of the [`Metrics`] trait. There are 2 provided options: a NOOP, which -//! essentially disables metrics collection, and a prometheus exporter. - -use std::net::SocketAddr; - -use axum::{routing::get, Router}; -use mycelium::metrics::Metrics; -use prometheus::{ - opts, register_int_counter, register_int_counter_vec, register_int_gauge, Encoder, IntCounter, - IntCounterVec, IntGauge, TextEncoder, -}; -use tracing::{error, info}; - -#[derive(Clone)] -pub struct NoMetrics; -impl Metrics for NoMetrics {} - -/// A [`Metrics`] implementation which uses prometheus to expose the metrics to the outside world. -#[derive(Clone)] -pub struct PrometheusExporter { - router_processed_tlvs: IntCounterVec, - router_peer_added: IntCounter, - router_peer_removed: IntCounter, - router_peer_died: IntCounter, - router_route_selection_ran: IntCounter, - router_source_key_expired: IntCounter, - router_expired_routes: IntCounterVec, - router_selected_route_expired: IntCounter, - router_triggered_update: IntCounter, - router_route_packet: IntCounterVec, - router_seqno_action: IntCounterVec, - router_tlv_handling_time_spent: IntCounterVec, - router_update_dead_peer: IntCounter, - router_received_tlvs: IntCounter, - router_tlv_source_died: IntCounter, - router_propage_selected_peers_time_spent: IntCounter, - peer_manager_peer_added: IntCounterVec, - peer_manager_known_peers: IntGauge, - peer_manager_connection_attemps: IntCounterVec, -} - -impl PrometheusExporter { - /// Create a new [`PrometheusExporter`]. - pub fn new() -> Self { - Self { - router_processed_tlvs: register_int_counter_vec!( - opts!( - "mycelium_router_processed_tlvs", - "Amount of processed TLV's from peers, by type of TLV" - ), &["tlv_type"] - ).expect("Can register int counter vec in default registry"), - router_peer_added: register_int_counter!( - "mycelium_router_peer_added", - "Amount of times a peer was added to the router" - ).expect("Can register int counter in default registry"), - router_peer_removed: register_int_counter!( - "mycelium_router_peer_removed", - "Amount of times a peer was removed from the router" - ).expect("Can register int counter in default registry"), - router_peer_died: register_int_counter!( - "mycelium_router_peer_died", - "Amount of times the router noticed a peer was dead, or the peer noticed itself and informed the router", - ).expect("Can register int counter in default registry"), - router_route_selection_ran: register_int_counter!( - "mycelium_router_route_selections", - "Amount of times a route selection procedure was ran as result of routes expiring or peers being disconnected. Does not include route selection after an update", - ).expect("Can register int counte rin default registry"), - router_source_key_expired: register_int_counter!( - "mycelium_router_source_key_expired", - "Amount of source keys expired" - ) - .expect("Can register int counter in default registry"), - router_expired_routes: register_int_counter_vec!( - opts!( - "mycelium_router_expired_routes", - "Route expiration events and the action taken on the route", - ), - &["action"] - ) - .expect("Can register int counter vec in default registry"), - router_selected_route_expired: register_int_counter!( - "mycelium_router_selected_route_expired", - "Amount of times a selected route in the routing table expired" - ) - .expect("Can register int counter in default registry"), - router_triggered_update: register_int_counter!( - "mycelium_router_triggered_updates", - "Amount of triggered updates sent" - ) - .expect("Can register int counter in default registry"), - router_route_packet: register_int_counter_vec!( - opts!( - "mycelium_router_packets_routed", - "What happened to a routed data packet" - ), - &["verdict"], - ) - .expect("Can register int counter vec in default registry"), - router_seqno_action: register_int_counter_vec!( - opts!( - "mycelium_router_seqno_handling", - "What happened to a received seqno request", - ), - &["action"], - ) - .expect("Can register int counter vec in default registry"), - router_tlv_handling_time_spent: register_int_counter_vec!( - opts!( - "mycelium_router_tlv_handling_time", - "Amount of time spent handling incoming TLV packets, in nanoseconds", - ), - &["tlv_type"], - ) - .expect("Can register an int counter vec in default registry"), - router_update_dead_peer: register_int_counter!( - "mycelium_router_update_dead_peer", - "Amount of updates we tried to send to a peer, where we found the peer to be dead before actually sending" - ) - .expect("Can register an int counter in default registry"), - router_received_tlvs: register_int_counter!( - "mycelium_router_received_tlvs", - "Amount of tlv's received by peers", - ) - .expect("Can register an int counter in the default registry"), - router_tlv_source_died: register_int_counter!( - "mycelium_router_tlv_source_died", - "Dropped TLV's which have been received, but where the peer has died before they could be processed", - ) - .expect("Can register an int counter in default registry"), - router_propage_selected_peers_time_spent: register_int_counter!( - "mycelium_router_propagate_selected_route_time", - "Time spent in the propagate_selected_route task, which periodically announces selected routes to peers. Measurement is in nanoseconds", - ) - .expect("Can register an int counter in default registry"), - peer_manager_peer_added: register_int_counter_vec!( - opts!( - "mycelium_peer_manager_peers_added", - "Peers added to the peer manager at runtime, by peer type" - ), - &["peer_type"], - ) - .expect("Can register int counter vec in default registry"), - peer_manager_known_peers: register_int_gauge!( - "mycelium_peer_manager_known_peers", - "Amount of known peers in the peer manager" - ) - .expect("Can register int gauge in default registry"), - peer_manager_connection_attemps: register_int_counter_vec!( - opts!( - "mycelium_peer_manager_connection_attempts", - "Count how many connections the peer manager started to remotes, and finished" - ), - &["connection_state"] - ) - .expect("Can register int counter vec in the default registry"), - } - } - - /// Spawns a HTTP server on the provided [`SocketAddr`], to export the gathered metrics. Metrics - /// are served under the /metrics endpoint. - pub fn spawn(self, listen_addr: SocketAddr) { - info!("Enable system metrics on http://{listen_addr}/metrics"); - let app = Router::new().route("/metrics", get(serve_metrics)); - tokio::spawn(async move { - let listener = match tokio::net::TcpListener::bind(listen_addr).await { - Ok(listener) => listener, - Err(e) => { - error!("Failed to bind listener for Http metrics server: {e}"); - error!("metrics disabled"); - return; - } - }; - - let server = axum::serve(listener, app.into_make_service()); - if let Err(e) = server.await { - error!("Http API server error: {e}"); - } - }); - } -} - -/// Expose prometheus formatted metrics -async fn serve_metrics() -> String { - let mut buffer = Vec::new(); - let encoder = TextEncoder::new(); - - // Gather the metrics. - let metric_families = prometheus::gather(); - // Encode them to send. - encoder - .encode(&metric_families, &mut buffer) - .expect("Can encode metrics"); - String::from_utf8(buffer).expect("Metrics are encoded in valid prometheus format") -} - -impl Metrics for PrometheusExporter { - #[inline] - fn router_process_hello(&self) { - self.router_processed_tlvs - .with_label_values(&["hello"]) - .inc() - } - - #[inline] - fn router_process_ihu(&self) { - self.router_processed_tlvs.with_label_values(&["ihu"]).inc() - } - - #[inline] - fn router_process_seqno_request(&self) { - self.router_processed_tlvs - .with_label_values(&["seqno_request"]) - .inc() - } - - #[inline] - fn router_process_route_request(&self, wildcard: bool) { - let label = if wildcard { - "wildcard_route_request" - } else { - "route_request" - }; - self.router_processed_tlvs.with_label_values(&[label]).inc() - } - - #[inline] - fn router_process_update(&self) { - self.router_processed_tlvs - .with_label_values(&["update"]) - .inc() - } - - #[inline] - fn router_peer_added(&self) { - self.router_peer_added.inc() - } - - #[inline] - fn router_peer_removed(&self) { - self.router_peer_removed.inc() - } - - #[inline] - fn router_peer_died(&self) { - self.router_peer_died.inc() - } - - #[inline] - fn router_route_selection_ran(&self) { - self.router_route_selection_ran.inc() - } - - #[inline] - fn router_source_key_expired(&self) { - self.router_source_key_expired.inc() - } - - #[inline] - fn router_route_key_expired(&self, removed: bool) { - let label = if removed { "removed" } else { "retracted" }; - self.router_expired_routes.with_label_values(&[label]).inc() - } - - #[inline] - fn router_selected_route_expired(&self) { - self.router_selected_route_expired.inc() - } - - #[inline] - fn router_triggered_update(&self) { - self.router_triggered_update.inc() - } - - #[inline] - fn router_route_packet_local(&self) { - self.router_route_packet.with_label_values(&["local"]).inc() - } - - #[inline] - fn router_route_packet_forward(&self) { - self.router_route_packet - .with_label_values(&["forward"]) - .inc() - } - - #[inline] - fn router_route_packet_ttl_expired(&self) { - self.router_route_packet - .with_label_values(&["ttl_expired"]) - .inc() - } - - #[inline] - fn router_route_packet_no_route(&self) { - self.router_route_packet - .with_label_values(&["no_route"]) - .inc() - } - - #[inline] - fn router_seqno_request_reply_local(&self) { - self.router_seqno_action - .with_label_values(&["reply_local"]) - .inc() - } - - #[inline] - fn router_seqno_request_bump_seqno(&self) { - self.router_seqno_action - .with_label_values(&["bump_seqno"]) - .inc() - } - - #[inline] - fn router_seqno_request_dropped_ttl(&self) { - self.router_seqno_action - .with_label_values(&["ttl_expired"]) - .inc() - } - - #[inline] - fn router_seqno_request_forward_feasible(&self) { - self.router_seqno_action - .with_label_values(&["forward_feasible"]) - .inc() - } - - #[inline] - fn router_seqno_request_forward_unfeasible(&self) { - self.router_seqno_action - .with_label_values(&["forward_unfeasible"]) - .inc() - } - - #[inline] - fn router_seqno_request_unhandled(&self) { - self.router_seqno_action - .with_label_values(&["unhandled"]) - .inc() - } - - #[inline] - fn router_time_spent_handling_tlv(&self, duration: std::time::Duration, tlv_type: &str) { - self.router_tlv_handling_time_spent - .with_label_values(&[tlv_type]) - .inc_by(duration.as_nanos() as u64) - } - - #[inline] - fn router_update_dead_peer(&self) { - self.router_update_dead_peer.inc() - } - - #[inline] - fn router_received_tlv(&self) { - self.router_received_tlvs.inc() - } - - #[inline] - fn router_tlv_source_died(&self) { - self.router_tlv_source_died.inc() - } - - #[inline] - fn router_time_spent_periodic_propagating_selected_routes( - &self, - duration: std::time::Duration, - ) { - self.router_propage_selected_peers_time_spent - .inc_by(duration.as_nanos() as u64) - } - - #[inline] - fn peer_manager_peer_added(&self, pt: mycelium::peer_manager::PeerType) { - let label = match pt { - mycelium::peer_manager::PeerType::Static => "static", - mycelium::peer_manager::PeerType::Inbound => "inbound", - mycelium::peer_manager::PeerType::LinkLocalDiscovery => "link_local", - }; - self.peer_manager_peer_added - .with_label_values(&[label]) - .inc() - } - - #[inline] - fn peer_manager_known_peers(&self, amount: usize) { - self.peer_manager_known_peers.set(amount as i64) - } - - #[inline] - fn peer_manager_connection_attempted(&self) { - self.peer_manager_connection_attemps - .with_label_values(&["started"]) - .inc() - } - - #[inline] - fn peer_manager_connection_finished(&self) { - self.peer_manager_connection_attemps - .with_label_values(&["finished"]) - .inc() - } -}