systemprompt_logging/repository/
mod.rs1#![allow(clippy::print_stdout)]
2
3use chrono::{DateTime, Utc};
4use systemprompt_database::DbPool;
5use systemprompt_identifiers::LogId;
6
7use crate::models::{LogEntry, LogFilter, LogLevel, LoggingError};
8
9pub mod analytics;
10mod operations;
11
12pub use analytics::{AnalyticsEvent, AnalyticsRepository};
13
14#[derive(Clone, Debug)]
15pub struct LoggingRepository {
16 db_pool: DbPool,
17 terminal_output: bool,
18 db_output: bool,
19}
20
21impl LoggingRepository {
22 #[must_use]
23 pub const fn new(db_pool: DbPool) -> Self {
24 Self {
25 db_pool,
26 terminal_output: true,
27 db_output: false,
28 }
29 }
30
31 #[must_use]
32 pub const fn with_terminal(mut self, enabled: bool) -> Self {
33 self.terminal_output = enabled;
34 self
35 }
36
37 #[must_use]
38 pub const fn with_database(mut self, enabled: bool) -> Self {
39 self.db_output = enabled;
40 self
41 }
42
43 pub async fn log(&self, entry: LogEntry) -> Result<(), LoggingError> {
44 entry.validate()?;
45
46 if self.terminal_output {
47 println!("{entry}");
48 }
49
50 if self.db_output {
51 operations::create_log(&self.db_pool, &entry).await?;
52 }
53
54 Ok(())
55 }
56
57 pub async fn log_message(
58 &self,
59 level: LogLevel,
60 module: &str,
61 message: &str,
62 ) -> Result<(), LoggingError> {
63 let entry = LogEntry::new(level, module, message);
64 self.log(entry).await
65 }
66
67 pub async fn log_message_with_metadata(
68 &self,
69 level: LogLevel,
70 module: &str,
71 message: &str,
72 metadata: serde_json::Value,
73 ) -> Result<(), LoggingError> {
74 let entry = LogEntry::new(level, module, message).with_metadata(metadata);
75 self.log(entry).await
76 }
77
78 pub async fn error(&self, module: &str, message: &str) -> Result<(), LoggingError> {
79 self.log_message(LogLevel::Error, module, message).await
80 }
81
82 pub async fn warn(&self, module: &str, message: &str) -> Result<(), LoggingError> {
83 self.log_message(LogLevel::Warn, module, message).await
84 }
85
86 pub async fn info(&self, module: &str, message: &str) -> Result<(), LoggingError> {
87 self.log_message(LogLevel::Info, module, message).await
88 }
89
90 pub async fn debug(&self, module: &str, message: &str) -> Result<(), LoggingError> {
91 self.log_message(LogLevel::Debug, module, message).await
92 }
93
94 pub async fn trace(&self, module: &str, message: &str) -> Result<(), LoggingError> {
95 self.log_message(LogLevel::Trace, module, message).await
96 }
97
98 pub async fn get_recent_logs(&self, limit: i64) -> Result<Vec<LogEntry>, LoggingError> {
99 operations::list_logs(&self.db_pool, limit).await
100 }
101
102 pub async fn get_logs_by_module_patterns(
103 &self,
104 patterns: &[String],
105 limit: i64,
106 ) -> Result<Vec<LogEntry>, LoggingError> {
107 operations::list_logs_by_module_patterns(&self.db_pool, patterns, limit).await
108 }
109
110 pub async fn cleanup_old_logs(&self, older_than: DateTime<Utc>) -> Result<u64, LoggingError> {
111 operations::cleanup_logs_before(&self.db_pool, older_than).await
112 }
113
114 pub async fn count_logs_before(&self, cutoff: DateTime<Utc>) -> Result<u64, LoggingError> {
115 operations::count_logs_before(&self.db_pool, cutoff).await
116 }
117
118 pub async fn clear_all_logs(&self) -> Result<u64, LoggingError> {
119 operations::clear_all_logs(&self.db_pool).await
120 }
121
122 pub async fn get_logs_paginated(
123 &self,
124 filter: &LogFilter,
125 ) -> Result<(Vec<LogEntry>, i64), LoggingError> {
126 operations::list_logs_paginated(&self.db_pool, filter).await
127 }
128
129 pub async fn get_by_id(&self, id: &LogId) -> Result<Option<LogEntry>, LoggingError> {
130 operations::get_log(&self.db_pool, id).await
131 }
132
133 pub async fn update_log_entry(
134 &self,
135 id: &LogId,
136 entry: &LogEntry,
137 ) -> Result<bool, LoggingError> {
138 operations::update_log(&self.db_pool, id, entry).await
139 }
140
141 pub async fn delete_log_entry(&self, id: &LogId) -> Result<bool, LoggingError> {
142 operations::delete_log(&self.db_pool, id).await
143 }
144
145 pub async fn delete_log_entries(&self, ids: &[LogId]) -> Result<u64, LoggingError> {
146 operations::delete_logs_multiple(&self.db_pool, ids).await
147 }
148}