1use std::sync::Arc;
2
3use crate::{
4 Result,
5 storage::stats_db::{NetworkEventRecord, StatsDatabase, SyncSessionRecord},
6};
7
8#[derive(Clone, Copy, Debug)]
10#[non_exhaustive]
11pub enum NetworkEventType {
12 PeerJoined,
13 PeerLeft,
14 SyncStarted,
15 SyncFinished,
16 RelayConnected,
17 RelayDisconnected,
18 RelayFailed,
19 TopicSubscribed,
20 TopicUnsubscribed,
21 MemberAdded,
22 MemberRemoved,
23 FolderAdded,
24 FolderRemoved,
25 TicketCreated,
26 TicketAccepted,
27 Kicked,
28}
29
30impl NetworkEventType {
31 #[must_use]
32 pub const fn as_str(&self) -> &'static str {
33 match self {
34 Self::PeerJoined => "peer_joined",
35 Self::PeerLeft => "peer_left",
36 Self::SyncStarted => "sync_started",
37 Self::SyncFinished => "sync_finished",
38 Self::RelayConnected => "relay_connected",
39 Self::RelayDisconnected => "relay_disconnected",
40 Self::RelayFailed => "relay_failed",
41 Self::TopicSubscribed => "topic_subscribed",
42 Self::TopicUnsubscribed => "topic_unsubscribed",
43 Self::MemberAdded => "member_added",
44 Self::MemberRemoved => "member_removed",
45 Self::FolderAdded => "folder_added",
46 Self::FolderRemoved => "folder_removed",
47 Self::TicketCreated => "ticket_created",
48 Self::TicketAccepted => "ticket_accepted",
49 Self::Kicked => "kicked",
50 }
51 }
52}
53
54#[derive(Clone, Debug)]
58pub struct NetworkLogger {
59 database: Arc<StatsDatabase>,
60}
61
62impl NetworkLogger {
63 #[must_use]
65 pub fn new(database: StatsDatabase) -> Self {
66 Self {
67 database: Arc::new(database),
68 }
69 }
70
71 #[must_use]
73 pub const fn from_arc(database: Arc<StatsDatabase>) -> Self {
74 Self { database }
75 }
76
77 pub fn record_event(
83 &self,
84 network_id: &str,
85 event: NetworkEventType,
86 peer: Option<&str>,
87 details: Option<&str>,
88 ) -> Result<()> {
89 self.database
90 .record_network_event(network_id, event.as_str(), peer, details, None)
91 }
92
93 pub fn record_event_with_metadata(
99 &self,
100 network_id: &str,
101 event: NetworkEventType,
102 peer: Option<&str>,
103 details: Option<&str>,
104 metadata_json: Option<&str>,
105 ) -> Result<()> {
106 self.database
107 .record_network_event(network_id, event.as_str(), peer, details, metadata_json)
108 }
109
110 pub fn record_sync_start(&self, network_id: &str, folder_namespace: &str) -> Result<i64> {
116 self.database.record_sync_session_start(network_id, folder_namespace)
117 }
118
119 pub fn record_sync_finish(&self, session_id: i64, files: u64, bytes: u64, errors: u64, status: &str) -> Result<()> {
125 self.database
126 .record_sync_session_finish(session_id, files, bytes, errors, status)
127 }
128
129 pub fn record_relay_check(
135 &self,
136 relay_url: &str,
137 connected: bool,
138 latency_ms: Option<i64>,
139 error_message: Option<&str>,
140 ) -> Result<()> {
141 self.database
142 .record_relay_check(relay_url, connected, latency_ms, error_message)
143 }
144
145 pub fn recent_events(&self, network_id: &str, limit: usize) -> Result<Vec<NetworkEventRecord>> {
151 self.database.recent_network_events(network_id, limit)
152 }
153
154 pub fn recent_sessions(&self, network_id: &str, limit: usize) -> Result<Vec<SyncSessionRecord>> {
160 self.database.recent_sync_sessions(network_id, limit)
161 }
162
163 pub fn relay_uptime(&self, relay_url: &str, window_secs: i64) -> Result<f64> {
169 self.database.relay_uptime(relay_url, window_secs)
170 }
171}