systemprompt_models/events/
analytics_event.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5#[serde(tag = "type", rename_all = "SCREAMING_SNAKE_CASE")]
6pub enum AnalyticsEvent {
7    SessionStarted {
8        timestamp: DateTime<Utc>,
9        #[serde(flatten)]
10        payload: SessionStartedPayload,
11    },
12    SessionEnded {
13        timestamp: DateTime<Utc>,
14        #[serde(flatten)]
15        payload: SessionEndedPayload,
16    },
17    PageView {
18        timestamp: DateTime<Utc>,
19        #[serde(flatten)]
20        payload: PageViewPayload,
21    },
22    EngagementUpdate {
23        timestamp: DateTime<Utc>,
24        #[serde(flatten)]
25        payload: EngagementUpdatePayload,
26    },
27    RealTimeStats {
28        timestamp: DateTime<Utc>,
29        #[serde(flatten)]
30        payload: RealTimeStatsPayload,
31    },
32    Heartbeat {
33        timestamp: DateTime<Utc>,
34    },
35}
36
37impl AnalyticsEvent {
38    pub const fn timestamp(&self) -> DateTime<Utc> {
39        match self {
40            Self::SessionStarted { timestamp, .. }
41            | Self::SessionEnded { timestamp, .. }
42            | Self::PageView { timestamp, .. }
43            | Self::EngagementUpdate { timestamp, .. }
44            | Self::RealTimeStats { timestamp, .. }
45            | Self::Heartbeat { timestamp } => *timestamp,
46        }
47    }
48
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize)]
52pub struct SessionStartedPayload {
53    pub session_id: String,
54    pub device_type: Option<String>,
55    pub browser: Option<String>,
56    pub os: Option<String>,
57    pub country: Option<String>,
58    pub referrer_source: Option<String>,
59    pub is_bot: bool,
60}
61
62#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct SessionEndedPayload {
64    pub session_id: String,
65    pub duration_ms: i64,
66    pub page_count: i64,
67    pub request_count: i64,
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct PageViewPayload {
72    pub session_id: String,
73    pub user_id: Option<String>,
74    pub page_url: String,
75    pub content_id: Option<String>,
76    pub referrer: Option<String>,
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize)]
80pub struct EngagementUpdatePayload {
81    pub session_id: String,
82    pub page_url: String,
83    pub scroll_depth: i32,
84    pub time_on_page_ms: i64,
85    pub click_count: i32,
86}
87
88#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
89pub struct RealTimeStatsPayload {
90    pub active_sessions: i64,
91    pub active_users: i64,
92    pub requests_per_minute: i64,
93    pub page_views_last_5m: i64,
94    pub bot_requests_last_5m: i64,
95}
96
97#[derive(Debug, Clone, Copy)]
98pub struct AnalyticsEventBuilder;
99
100impl AnalyticsEventBuilder {
101    pub fn session_started(payload: SessionStartedPayload) -> AnalyticsEvent {
102        AnalyticsEvent::SessionStarted {
103            timestamp: Utc::now(),
104            payload,
105        }
106    }
107
108    pub fn session_ended(
109        session_id: String,
110        duration_ms: i64,
111        page_count: i64,
112        request_count: i64,
113    ) -> AnalyticsEvent {
114        AnalyticsEvent::SessionEnded {
115            timestamp: Utc::now(),
116            payload: SessionEndedPayload {
117                session_id,
118                duration_ms,
119                page_count,
120                request_count,
121            },
122        }
123    }
124
125    pub fn page_view(
126        session_id: String,
127        user_id: Option<String>,
128        page_url: String,
129        content_id: Option<String>,
130        referrer: Option<String>,
131    ) -> AnalyticsEvent {
132        AnalyticsEvent::PageView {
133            timestamp: Utc::now(),
134            payload: PageViewPayload {
135                session_id,
136                user_id,
137                page_url,
138                content_id,
139                referrer,
140            },
141        }
142    }
143
144    pub fn engagement_update(
145        session_id: String,
146        page_url: String,
147        scroll_depth: i32,
148        time_on_page_ms: i64,
149        click_count: i32,
150    ) -> AnalyticsEvent {
151        AnalyticsEvent::EngagementUpdate {
152            timestamp: Utc::now(),
153            payload: EngagementUpdatePayload {
154                session_id,
155                page_url,
156                scroll_depth,
157                time_on_page_ms,
158                click_count,
159            },
160        }
161    }
162
163    pub fn realtime_stats(
164        active_sessions: i64,
165        active_users: i64,
166        requests_per_minute: i64,
167        page_views_last_5m: i64,
168        bot_requests_last_5m: i64,
169    ) -> AnalyticsEvent {
170        AnalyticsEvent::RealTimeStats {
171            timestamp: Utc::now(),
172            payload: RealTimeStatsPayload {
173                active_sessions,
174                active_users,
175                requests_per_minute,
176                page_views_last_5m,
177                bot_requests_last_5m,
178            },
179        }
180    }
181
182    pub fn heartbeat() -> AnalyticsEvent {
183        AnalyticsEvent::Heartbeat {
184            timestamp: Utc::now(),
185        }
186    }
187}