Skip to main content

systemprompt_analytics/repository/session/
behavioral.rs

1//! Behavioral analysis across typed owner contracts.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use super::{SessionBehavioralData, SessionRepository, behavioral_queries};
7use crate::Result;
8use chrono::{DateTime, Utc};
9use systemprompt_identifiers::SessionId;
10impl SessionRepository {
11    pub async fn count_sessions_by_fingerprint(
12        &self,
13        fingerprint_hash: &str,
14        window_hours: i64,
15    ) -> Result<i64> {
16        systemprompt_traits::SessionStore::count_sessions_by_fingerprint(
17            &*self.owner,
18            fingerprint_hash,
19            window_hours,
20        )
21        .await
22        .map_err(crate::AnalyticsError::from)
23    }
24
25    pub async fn get_endpoint_sequence(&self, session_id: &SessionId) -> Result<Vec<String>> {
26        self.events
27            .get_endpoint_sequence(session_id)
28            .await
29            .map_err(crate::AnalyticsError::from)
30    }
31
32    pub async fn get_request_timestamps(
33        &self,
34        session_id: &SessionId,
35    ) -> Result<Vec<DateTime<Utc>>> {
36        self.events
37            .get_request_timestamps(session_id)
38            .await
39            .map_err(crate::AnalyticsError::from)
40    }
41
42    pub async fn get_total_content_pages(&self) -> Result<i64> {
43        self.content.count_public_pages().await.map_err(Into::into)
44    }
45
46    pub async fn get_session_for_behavioral_analysis(
47        &self,
48        session_id: &SessionId,
49    ) -> Result<Option<SessionBehavioralData>> {
50        systemprompt_traits::SessionStore::get_session_for_behavioral_analysis(
51            &*self.owner,
52            session_id,
53        )
54        .await
55        .map_err(crate::AnalyticsError::from)
56    }
57
58    pub async fn has_analytics_events(&self, session_id: &SessionId) -> Result<bool> {
59        self.events
60            .has_analytics_events(session_id)
61            .await
62            .map_err(crate::AnalyticsError::from)
63    }
64
65    pub async fn count_unique_ips_by_fingerprint(
66        &self,
67        fingerprint_hash: &str,
68        window_days: i64,
69    ) -> Result<i64> {
70        systemprompt_traits::SessionStore::count_unique_ips_by_fingerprint(
71            &*self.owner,
72            fingerprint_hash,
73            window_days,
74        )
75        .await
76        .map_err(crate::AnalyticsError::from)
77    }
78
79    pub async fn count_engagement_events_by_fingerprint(
80        &self,
81        fingerprint_hash: &str,
82        window_days: i64,
83    ) -> Result<i64> {
84        let session_ids = self
85            .owner
86            .fingerprint_session_ids(fingerprint_hash, window_days)
87            .await
88            .map_err(crate::AnalyticsError::from)?
89            .into_iter()
90            .map(|id| id.to_string())
91            .collect::<Vec<_>>();
92        behavioral_queries::count_engagement_events_for_sessions(&self.write_pool, &session_ids)
93            .await
94    }
95
96    pub async fn get_session_starts_by_fingerprint(
97        &self,
98        fingerprint_hash: &str,
99        window_days: i64,
100    ) -> Result<Vec<DateTime<Utc>>> {
101        systemprompt_traits::SessionStore::get_session_starts_by_fingerprint(
102            &*self.owner,
103            fingerprint_hash,
104            window_days,
105        )
106        .await
107        .map_err(crate::AnalyticsError::from)
108    }
109
110    pub async fn get_session_velocity(
111        &self,
112        session_id: &SessionId,
113    ) -> Result<(Option<i64>, Option<i64>)> {
114        systemprompt_traits::SessionStore::get_session_velocity(&*self.owner, session_id)
115            .await
116            .map_err(crate::AnalyticsError::from)
117    }
118}