1use crate::catalog::{Catalog, db_err};
8use orbok_core::{EventId, OrbokResult, now_iso8601};
9use rusqlite::params;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum Severity {
14 Debug,
15 Info,
16 Warning,
17 Error,
18}
19
20impl Severity {
21 pub fn as_str(&self) -> &'static str {
22 match self {
23 Severity::Debug => "debug",
24 Severity::Info => "info",
25 Severity::Warning => "warning",
26 Severity::Error => "error",
27 }
28 }
29}
30
31pub struct EventRepository<'a> {
32 catalog: &'a Catalog,
33}
34
35impl<'a> EventRepository<'a> {
36 pub fn new(catalog: &'a Catalog) -> Self {
37 Self { catalog }
38 }
39
40 pub fn append(
43 &self,
44 event_type: &str,
45 severity: Severity,
46 message: &str,
47 redacted_details_json: Option<&str>,
48 ) -> OrbokResult<()> {
49 let conn = self.catalog.lock();
50 conn.execute(
51 "INSERT INTO app_events (event_id, event_type, severity, message, \
52 redacted_details_json, created_at) VALUES (?1,?2,?3,?4,?5,?6)",
53 params![
54 EventId::generate().as_str(),
55 event_type,
56 severity.as_str(),
57 message,
58 redacted_details_json,
59 now_iso8601(),
60 ],
61 )
62 .map_err(db_err)?;
63 Ok(())
64 }
65
66 pub fn recent(&self, limit: u32) -> OrbokResult<Vec<(String, String, String)>> {
68 let conn = self.catalog.lock();
69 let mut stmt = conn
70 .prepare(
71 "SELECT event_type, severity, message FROM app_events \
72 ORDER BY created_at DESC LIMIT ?1",
73 )
74 .map_err(db_err)?;
75 let rows = stmt
76 .query_map(params![limit], |row| {
77 Ok((row.get(0)?, row.get(1)?, row.get(2)?))
78 })
79 .map_err(db_err)?;
80 let mut out = Vec::new();
81 for row in rows {
82 out.push(row.map_err(db_err)?);
83 }
84 Ok(out)
85 }
86}