From 2a9160836bb87fdea3ae891563b0169c68d1c2ab Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Thu, 11 Dec 2025 16:53:03 +0000 Subject: fix: resolve all fmt and clippy warnings Main lib (src/): - Add #[allow(dead_code)] for build_info field (stored to prevent Prometheus unregistration) - Add #[allow(dead_code)] for first_seen field (reserved for future rate limiting) - Replace .or_insert_with(RelaySyncNeeds::default) with .or_default() - Replace manual div_ceil implementations with .div_ceil(100) Test code (tests/): - Replace .expect(&format!(...)) with .unwrap_or_else(|_| panic!(...)) - Remove needless borrows in fetch_metrics() calls - Add #[allow(dead_code)] and #[allow(unused_imports)] to test helpers module grasp-audit: - Apply cargo fmt to fix formatting --- src/metrics/bandwidth.rs | 13 +++-- src/metrics/connection.rs | 58 +++++++++++---------- src/metrics/mod.rs | 127 ++++++++++++++++++++++++++++++---------------- 3 files changed, 122 insertions(+), 76 deletions(-) (limited to 'src/metrics') diff --git a/src/metrics/bandwidth.rs b/src/metrics/bandwidth.rs index d2c53e8..d51af12 100644 --- a/src/metrics/bandwidth.rs +++ b/src/metrics/bandwidth.rs @@ -80,7 +80,9 @@ impl BandwidthTracker { &["repo"], ) .unwrap(); - registry.register(Box::new(top_repos_gauge.clone())).unwrap(); + registry + .register(Box::new(top_repos_gauge.clone())) + .unwrap(); Self { all_repos: DashMap::new(), @@ -120,7 +122,12 @@ impl BandwidthTracker { // Try to update the timestamp atomically to prevent concurrent refreshes if self .last_refresh_nanos - .compare_exchange(last_refresh, elapsed_nanos, Ordering::SeqCst, Ordering::Relaxed) + .compare_exchange( + last_refresh, + elapsed_nanos, + Ordering::SeqCst, + Ordering::Relaxed, + ) .is_ok() { self.refresh_top_n(); @@ -298,4 +305,4 @@ mod tests { // Refresh should not panic on empty data tracker.refresh_top_n(); } -} \ No newline at end of file +} diff --git a/src/metrics/connection.rs b/src/metrics/connection.rs index 6a7f406..2d42081 100644 --- a/src/metrics/connection.rs +++ b/src/metrics/connection.rs @@ -25,7 +25,8 @@ use tracing::warn; struct ConnectionInfo { /// Number of active connections from this IP count: u32, - /// When the first connection from this IP was established + /// When the first connection from this IP was established (for future rate limiting) + #[allow(dead_code)] first_seen: Instant, /// Whether this IP has been flagged as potentially abusive flagged_as_abuse: bool, @@ -48,16 +49,16 @@ struct ConnectionInfo { pub struct ConnectionTracker { /// Active connections per IP (INTERNAL ONLY - never exposed to metrics) connections: DashMap, - + /// Threshold for abuse flagging (connections per IP) abuse_threshold: u32, - + /// Prometheus gauge: total active connections active_connections: IntGauge, - + /// Prometheus gauge: number of unique IPs connected unique_ips: IntGauge, - + /// Prometheus gauge: number of IPs flagged as potential abusers flagged_abusers: IntGauge, } @@ -70,29 +71,30 @@ impl ConnectionTracker { /// * `abuse_threshold` - Number of connections from a single IP before flagging /// * `registry` - Prometheus registry to register metrics with pub fn new(abuse_threshold: u32, registry: &Registry) -> Self { - let active_connections = IntGauge::with_opts( - Opts::new( - "ngit_websocket_connections_active", - "Current active WebSocket connections", - ) - ).unwrap(); - registry.register(Box::new(active_connections.clone())).unwrap(); - - let unique_ips = IntGauge::with_opts( - Opts::new( - "ngit_websocket_unique_ips", - "Number of unique IP addresses connected (NOT the IPs themselves)", - ) - ).unwrap(); + let active_connections = IntGauge::with_opts(Opts::new( + "ngit_websocket_connections_active", + "Current active WebSocket connections", + )) + .unwrap(); + registry + .register(Box::new(active_connections.clone())) + .unwrap(); + + let unique_ips = IntGauge::with_opts(Opts::new( + "ngit_websocket_unique_ips", + "Number of unique IP addresses connected (NOT the IPs themselves)", + )) + .unwrap(); registry.register(Box::new(unique_ips.clone())).unwrap(); - let flagged_abusers = IntGauge::with_opts( - Opts::new( - "ngit_websocket_flagged_abusers", - "Number of IPs exceeding connection threshold", - ) - ).unwrap(); - registry.register(Box::new(flagged_abusers.clone())).unwrap(); + let flagged_abusers = IntGauge::with_opts(Opts::new( + "ngit_websocket_flagged_abusers", + "Number of IPs exceeding connection threshold", + )) + .unwrap(); + registry + .register(Box::new(flagged_abusers.clone())) + .unwrap(); Self { connections: DashMap::new(), @@ -140,7 +142,7 @@ impl ConnectionTracker { // Update Prometheus metrics (aggregate counts only) self.active_connections.inc(); - + if is_new_ip { self.unique_ips.inc(); } @@ -334,4 +336,4 @@ mod tests { assert_eq!(tracker.active_connections(), 0); assert_eq!(tracker.unique_ip_count(), 0); } -} \ No newline at end of file +} diff --git a/src/metrics/mod.rs b/src/metrics/mod.rs index 736414f..5420dfd 100644 --- a/src/metrics/mod.rs +++ b/src/metrics/mod.rs @@ -87,7 +87,8 @@ struct MetricsInner { // === System Health Metrics === /// Server start time for uptime calculation pub start_time: Instant, - /// Build information gauge + /// Build information gauge (stored to prevent unregistration from Prometheus) + #[allow(dead_code)] pub build_info: GaugeVec, } @@ -158,7 +159,10 @@ impl Metrics { /// Start timing a git operation, returns a timer pub fn start_git_operation_timer(&self, operation: &str) -> GitOperationTimer { - GitOperationTimer::new(self.inner.git_operation_duration.clone(), operation.to_string()) + GitOperationTimer::new( + self.inner.git_operation_duration.clone(), + operation.to_string(), + ) } /// Record bytes transferred for a git operation @@ -266,13 +270,14 @@ impl MetricsInner { } // WebSocket metrics - let websocket_connections_total = Counter::with_opts( - Opts::new( - "ngit_websocket_connections_total", - "Total WebSocket connections since startup", - ) - ).unwrap(); - REGISTRY.register(Box::new(websocket_connections_total.clone())).unwrap(); + let websocket_connections_total = Counter::with_opts(Opts::new( + "ngit_websocket_connections_total", + "Total WebSocket connections since startup", + )) + .unwrap(); + REGISTRY + .register(Box::new(websocket_connections_total.clone())) + .unwrap(); let websocket_connection_duration = Histogram::with_opts( HistogramOpts::new( @@ -280,8 +285,11 @@ impl MetricsInner { "Duration of WebSocket connections", ) .buckets(vec![1.0, 5.0, 15.0, 30.0, 60.0, 300.0, 900.0, 3600.0]), - ).unwrap(); - REGISTRY.register(Box::new(websocket_connection_duration.clone())).unwrap(); + ) + .unwrap(); + REGISTRY + .register(Box::new(websocket_connection_duration.clone())) + .unwrap(); let websocket_messages_received = CounterVec::new( Opts::new( @@ -289,8 +297,11 @@ impl MetricsInner { "WebSocket messages received by type", ), &["type"], - ).unwrap(); - REGISTRY.register(Box::new(websocket_messages_received.clone())).unwrap(); + ) + .unwrap(); + REGISTRY + .register(Box::new(websocket_messages_received.clone())) + .unwrap(); let websocket_messages_sent = CounterVec::new( Opts::new( @@ -298,8 +309,11 @@ impl MetricsInner { "WebSocket messages sent by type", ), &["type"], - ).unwrap(); - REGISTRY.register(Box::new(websocket_messages_sent.clone())).unwrap(); + ) + .unwrap(); + REGISTRY + .register(Box::new(websocket_messages_sent.clone())) + .unwrap(); // Git operation metrics let git_operations_total = CounterVec::new( @@ -308,8 +322,11 @@ impl MetricsInner { "Git operations by type and status", ), &["operation", "status"], - ).unwrap(); - REGISTRY.register(Box::new(git_operations_total.clone())).unwrap(); + ) + .unwrap(); + REGISTRY + .register(Box::new(git_operations_total.clone())) + .unwrap(); let git_operation_duration = HistogramVec::new( HistogramOpts::new( @@ -318,8 +335,11 @@ impl MetricsInner { ) .buckets(vec![0.1, 0.5, 1.0, 2.5, 5.0, 10.0, 30.0, 60.0]), &["operation"], - ).unwrap(); - REGISTRY.register(Box::new(git_operation_duration.clone())).unwrap(); + ) + .unwrap(); + REGISTRY + .register(Box::new(git_operation_duration.clone())) + .unwrap(); let git_bytes_total = CounterVec::new( Opts::new( @@ -327,8 +347,11 @@ impl MetricsInner { "Total bytes transferred for git operations", ), &["direction"], - ).unwrap(); - REGISTRY.register(Box::new(git_bytes_total.clone())).unwrap(); + ) + .unwrap(); + REGISTRY + .register(Box::new(git_bytes_total.clone())) + .unwrap(); let git_push_authorization = CounterVec::new( Opts::new( @@ -336,8 +359,11 @@ impl MetricsInner { "Push authorization results", ), &["result"], - ).unwrap(); - REGISTRY.register(Box::new(git_push_authorization.clone())).unwrap(); + ) + .unwrap(); + REGISTRY + .register(Box::new(git_push_authorization.clone())) + .unwrap(); // Nostr event metrics let events_received_total = CounterVec::new( @@ -346,8 +372,11 @@ impl MetricsInner { "Nostr events received by kind", ), &["kind"], - ).unwrap(); - REGISTRY.register(Box::new(events_received_total.clone())).unwrap(); + ) + .unwrap(); + REGISTRY + .register(Box::new(events_received_total.clone())) + .unwrap(); let events_stored_total = CounterVec::new( Opts::new( @@ -355,8 +384,11 @@ impl MetricsInner { "Nostr events successfully stored by kind", ), &["kind"], - ).unwrap(); - REGISTRY.register(Box::new(events_stored_total.clone())).unwrap(); + ) + .unwrap(); + REGISTRY + .register(Box::new(events_stored_total.clone())) + .unwrap(); let events_rejected_total = CounterVec::new( Opts::new( @@ -364,31 +396,36 @@ impl MetricsInner { "Nostr events rejected by kind and reason", ), &["kind", "reason"], - ).unwrap(); - REGISTRY.register(Box::new(events_rejected_total.clone())).unwrap(); + ) + .unwrap(); + REGISTRY + .register(Box::new(events_rejected_total.clone())) + .unwrap(); // Repository metrics - let repositories_total = Gauge::with_opts( - Opts::new( - "ngit_repositories_total", - "Total repositories hosted", - ) - ).unwrap(); - REGISTRY.register(Box::new(repositories_total.clone())).unwrap(); + let repositories_total = Gauge::with_opts(Opts::new( + "ngit_repositories_total", + "Total repositories hosted", + )) + .unwrap(); + REGISTRY + .register(Box::new(repositories_total.clone())) + .unwrap(); // Build info let build_info = GaugeVec::new( - Opts::new( - "ngit_build_info", - "Build information", - ), + Opts::new("ngit_build_info", "Build information"), &["version", "commit"], - ).unwrap(); + ) + .unwrap(); REGISTRY.register(Box::new(build_info.clone())).unwrap(); - + // Set build info gauge to 1 (it's just for labels) build_info - .with_label_values(&[env!("CARGO_PKG_VERSION"), option_env!("GIT_HASH").unwrap_or("unknown")]) + .with_label_values(&[ + env!("CARGO_PKG_VERSION"), + option_env!("GIT_HASH").unwrap_or("unknown"), + ]) .set(1.0); Self { @@ -472,7 +509,7 @@ mod tests { // Note: This test may fail if run with other tests due to global registry // In production, consider using a test-specific registry let metrics = Metrics::new(10); - + // Test that we can record metrics without panicking metrics.record_websocket_connection(); metrics.record_message_received("REQ"); @@ -484,4 +521,4 @@ mod tests { metrics.record_event_rejected(1, "invalid_signature"); metrics.set_repositories_total(5); } -} \ No newline at end of file +} -- cgit v1.2.3