diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2025-12-10 22:26:42 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2025-12-10 22:26:42 +0000 |
| commit | 82cc74ade1524edc096608795b4e13c3cb19c5eb (patch) | |
| tree | f3ca7be2104e934b23e05acd9827992b022cb257 /src/sync/mod.rs | |
| parent | 46b306dcfa4850a688367c04e9e06e8d9c2883dc (diff) | |
feat: create sync metrics module (Phase 1)
Diffstat (limited to 'src/sync/mod.rs')
| -rw-r--r-- | src/sync/mod.rs | 167 |
1 files changed, 4 insertions, 163 deletions
diff --git a/src/sync/mod.rs b/src/sync/mod.rs index 1e60e4a..dd0479c 100644 --- a/src/sync/mod.rs +++ b/src/sync/mod.rs | |||
| @@ -15,12 +15,16 @@ | |||
| 15 | pub mod algorithms; | 15 | pub mod algorithms; |
| 16 | pub mod filters; | 16 | pub mod filters; |
| 17 | pub mod health; | 17 | pub mod health; |
| 18 | pub mod metrics; | ||
| 18 | pub mod relay_connection; | 19 | pub mod relay_connection; |
| 19 | pub mod self_subscriber; | 20 | pub mod self_subscriber; |
| 20 | 21 | ||
| 21 | // Re-export core algorithm types | 22 | // Re-export core algorithm types |
| 22 | pub use algorithms::{AddFilters, RelaySyncNeeds}; | 23 | pub use algorithms::{AddFilters, RelaySyncNeeds}; |
| 23 | 24 | ||
| 25 | // Re-export metrics types | ||
| 26 | pub use metrics::{event_source, SyncMetrics}; | ||
| 27 | |||
| 24 | // Re-export relay connection types | 28 | // Re-export relay connection types |
| 25 | pub use relay_connection::{RelayConnection, RelayEvent}; | 29 | pub use relay_connection::{RelayConnection, RelayEvent}; |
| 26 | 30 | ||
| @@ -35,7 +39,6 @@ use std::sync::Arc; | |||
| 35 | use std::time::Duration; | 39 | use std::time::Duration; |
| 36 | 40 | ||
| 37 | use nostr_sdk::prelude::*; | 41 | use nostr_sdk::prelude::*; |
| 38 | use prometheus::{IntCounterVec, IntGauge, IntGaugeVec, Opts, Registry}; | ||
| 39 | use tokio::sync::{broadcast, Mutex, RwLock}; | 42 | use tokio::sync::{broadcast, Mutex, RwLock}; |
| 40 | 43 | ||
| 41 | use crate::config::Config; | 44 | use crate::config::Config; |
| @@ -157,168 +160,6 @@ pub struct PendingItems { | |||
| 157 | } | 160 | } |
| 158 | 161 | ||
| 159 | // ============================================================================= | 162 | // ============================================================================= |
| 160 | // SyncMetrics - Prometheus Metrics for Sync System | ||
| 161 | // ============================================================================= | ||
| 162 | |||
| 163 | /// Prometheus metrics for the proactive sync system. | ||
| 164 | /// | ||
| 165 | /// Tracks relay connections, sync progress, and operational statistics. | ||
| 166 | /// Following the comprehensive v3 metrics design. | ||
| 167 | #[derive(Clone)] | ||
| 168 | pub struct SyncMetrics { | ||
| 169 | // === Connection metrics === | ||
| 170 | /// Per-relay connection status (1=connected, 0=disconnected) | ||
| 171 | relay_connected: IntGaugeVec, | ||
| 172 | /// Connection attempts by relay and result (success/failure) | ||
| 173 | connection_attempts_total: IntCounterVec, | ||
| 174 | |||
| 175 | // === Event metrics === | ||
| 176 | /// Events synced by source (live/startup/reconnect/daily) | ||
| 177 | events_total: IntCounterVec, | ||
| 178 | |||
| 179 | // === Summary metrics === | ||
| 180 | /// Total relays discovered and tracked | ||
| 181 | relays_tracked_total: IntGauge, | ||
| 182 | /// Currently connected relay count | ||
| 183 | relays_connected_total: IntGauge, | ||
| 184 | } | ||
| 185 | |||
| 186 | impl SyncMetrics { | ||
| 187 | /// Register sync metrics with a Prometheus registry. | ||
| 188 | /// | ||
| 189 | /// Returns an error if metrics are already registered (e.g., in tests). | ||
| 190 | pub fn register(registry: &Registry) -> Result<Self, prometheus::Error> { | ||
| 191 | // Connection metrics | ||
| 192 | let relay_connected = IntGaugeVec::new( | ||
| 193 | Opts::new( | ||
| 194 | "ngit_sync_relay_connected", | ||
| 195 | "Relay connection status (1=connected, 0=disconnected)", | ||
| 196 | ), | ||
| 197 | &["relay"], | ||
| 198 | )?; | ||
| 199 | registry.register(Box::new(relay_connected.clone()))?; | ||
| 200 | |||
| 201 | let connection_attempts_total = IntCounterVec::new( | ||
| 202 | Opts::new( | ||
| 203 | "ngit_sync_connection_attempts_total", | ||
| 204 | "Total connection attempts by relay and result", | ||
| 205 | ), | ||
| 206 | &["relay", "result"], | ||
| 207 | )?; | ||
| 208 | registry.register(Box::new(connection_attempts_total.clone()))?; | ||
| 209 | |||
| 210 | // Event metrics | ||
| 211 | let events_total = IntCounterVec::new( | ||
| 212 | Opts::new( | ||
| 213 | "ngit_sync_events_total", | ||
| 214 | "Total events synced by source type", | ||
| 215 | ), | ||
| 216 | &["source"], | ||
| 217 | )?; | ||
| 218 | registry.register(Box::new(events_total.clone()))?; | ||
| 219 | |||
| 220 | // Summary metrics | ||
| 221 | let relays_tracked_total = IntGauge::with_opts(Opts::new( | ||
| 222 | "ngit_sync_relays_tracked_total", | ||
| 223 | "Total number of relays discovered and tracked", | ||
| 224 | ))?; | ||
| 225 | registry.register(Box::new(relays_tracked_total.clone()))?; | ||
| 226 | |||
| 227 | let relays_connected_total = IntGauge::with_opts(Opts::new( | ||
| 228 | "ngit_sync_relays_connected_total", | ||
| 229 | "Number of currently connected relays", | ||
| 230 | ))?; | ||
| 231 | registry.register(Box::new(relays_connected_total.clone()))?; | ||
| 232 | |||
| 233 | Ok(Self { | ||
| 234 | relay_connected, | ||
| 235 | connection_attempts_total, | ||
| 236 | events_total, | ||
| 237 | relays_tracked_total, | ||
| 238 | relays_connected_total, | ||
| 239 | }) | ||
| 240 | } | ||
| 241 | |||
| 242 | // === Connection Recording Methods === | ||
| 243 | |||
| 244 | /// Record a connection attempt (success or failure) | ||
| 245 | pub fn record_connection_attempt(&self, relay: &str, success: bool) { | ||
| 246 | let result = if success { "success" } else { "failure" }; | ||
| 247 | self.connection_attempts_total | ||
| 248 | .with_label_values(&[relay, result]) | ||
| 249 | .inc(); | ||
| 250 | } | ||
| 251 | |||
| 252 | /// Set relay connection status | ||
| 253 | pub fn set_relay_connected(&self, relay: &str, connected: bool) { | ||
| 254 | self.relay_connected | ||
| 255 | .with_label_values(&[relay]) | ||
| 256 | .set(if connected { 1 } else { 0 }); | ||
| 257 | } | ||
| 258 | |||
| 259 | /// Increment connected count | ||
| 260 | pub fn inc_connected_count(&self) { | ||
| 261 | self.relays_connected_total.inc(); | ||
| 262 | } | ||
| 263 | |||
| 264 | /// Decrement connected count | ||
| 265 | pub fn dec_connected_count(&self) { | ||
| 266 | self.relays_connected_total.dec(); | ||
| 267 | } | ||
| 268 | |||
| 269 | // === Event Recording Methods === | ||
| 270 | |||
| 271 | /// Record a synced event by source type | ||
| 272 | /// | ||
| 273 | /// Source types: | ||
| 274 | /// - "live" - Real-time subscription events | ||
| 275 | /// - "startup" - Events from startup catchup | ||
| 276 | /// - "reconnect" - Events from reconnection catchup | ||
| 277 | pub fn record_event(&self, source: &str) { | ||
| 278 | self.events_total.with_label_values(&[source]).inc(); | ||
| 279 | } | ||
| 280 | |||
| 281 | /// Record multiple events synced by source type | ||
| 282 | pub fn record_events(&self, source: &str, count: u64) { | ||
| 283 | self.events_total | ||
| 284 | .with_label_values(&[source]) | ||
| 285 | .inc_by(count); | ||
| 286 | } | ||
| 287 | |||
| 288 | // === Summary Recording Methods === | ||
| 289 | |||
| 290 | /// Set the total tracked relay count | ||
| 291 | pub fn set_tracked_count(&self, count: i64) { | ||
| 292 | self.relays_tracked_total.set(count); | ||
| 293 | } | ||
| 294 | |||
| 295 | /// Increment tracked relay count | ||
| 296 | pub fn inc_tracked_count(&self) { | ||
| 297 | self.relays_tracked_total.inc(); | ||
| 298 | } | ||
| 299 | |||
| 300 | /// Get current tracked relay count | ||
| 301 | pub fn get_tracked_count(&self) -> i64 { | ||
| 302 | self.relays_tracked_total.get() | ||
| 303 | } | ||
| 304 | |||
| 305 | /// Get current connected relay count | ||
| 306 | pub fn get_connected_count(&self) -> i64 { | ||
| 307 | self.relays_connected_total.get() | ||
| 308 | } | ||
| 309 | } | ||
| 310 | |||
| 311 | /// Event source types for metrics tracking | ||
| 312 | pub mod event_source { | ||
| 313 | /// Real-time subscription events | ||
| 314 | pub const LIVE: &str = "live"; | ||
| 315 | /// Events from startup catchup | ||
| 316 | pub const STARTUP: &str = "startup"; | ||
| 317 | /// Events from reconnection catchup | ||
| 318 | pub const RECONNECT: &str = "reconnect"; | ||
| 319 | } | ||
| 320 | |||
| 321 | // ============================================================================= | ||
| 322 | // SyncManager - Main Entry Point | 163 | // SyncManager - Main Entry Point |
| 323 | // ============================================================================= | 164 | // ============================================================================= |
| 324 | 165 | ||