shared_framework/logging/
logger.rs1use async_trait::async_trait;
15use std::time::Instant;
16
17#[async_trait]
19pub trait ILogger: Send + Sync {
20 async fn info(&self, msg: &str);
22 async fn debug(&self, msg: &str);
24 async fn warn(&self, msg: &str);
26 async fn error(&self, msg: &str);
28 async fn exec(&self, msg: &str);
30 fn time(&self, msg: &str) -> TimeEvent;
32}
33
34pub struct TimeEvent {
36 start: Instant,
37 message: String,
38 on_end: Option<Box<dyn FnOnce(std::time::Duration) + Send>>,
40}
41
42impl TimeEvent {
43 pub fn new(message: impl Into<String>, on_end: Option<Box<dyn FnOnce(std::time::Duration) + Send>>) -> Self {
45 Self { start: Instant::now(), message: message.into(), on_end }
46 }
47
48 pub fn stop(self) -> std::time::Duration {
50 self.start.elapsed()
51 }
52
53 pub fn end(self) -> std::time::Duration {
55 let d = self.start.elapsed();
56 if let Some(cb) = self.on_end {
57 cb(d);
58 }
59 d
60 }
61
62 pub fn elapsed(&self) -> std::time::Duration {
64 self.start.elapsed()
65 }
66
67 pub fn message(&self) -> &str {
69 &self.message
70 }
71}
72
73#[derive(Clone)]
75pub struct ConsoleLogger {
76 is_production: bool,
78}
79
80impl ConsoleLogger {
81 pub fn new(is_production: bool) -> Self {
83 Self { is_production }
84 }
85
86 pub fn global() -> Self {
89 let prod = crate::env::AppEnvironment::try_get().map(|e| e.is_production()).unwrap_or(false);
91 Self::new(prod)
92 }
93
94 fn prefix() -> String {
95 "framework".to_string()
97 }
98}
99
100#[async_trait]
101impl ILogger for ConsoleLogger {
102 async fn info(&self, msg: &str) {
103 tracing::info!(target: "console", executor = %Self::prefix(), "{}", msg);
104 }
105 async fn debug(&self, msg: &str) {
106 if self.is_production {
107 return;
108 }
109 tracing::debug!(target: "console", executor = %Self::prefix(), "{}", msg);
110 }
111 async fn warn(&self, msg: &str) {
112 tracing::warn!(target: "console", executor = %Self::prefix(), "{}", msg);
113 }
114 async fn error(&self, msg: &str) {
115 tracing::error!(target: "console", executor = %Self::prefix(), "{}", msg);
116 }
117 async fn exec(&self, msg: &str) {
118 tracing::info!(target: "console", executor = %Self::prefix(), exec = true, "{}", msg);
119 }
120 fn time(&self, msg: &str) -> TimeEvent {
121 let msg_owned = msg.to_string();
122 let label = msg_owned.clone();
123 TimeEvent::new(msg_owned, Some(Box::new(move |d| {
124 tracing::info!(target: "console", operation = %label, duration_ms = d.as_millis() as u64, "Operation completed");
125 })))
126 }
127}
128
129pub struct MonitorLogger {
131 inner: ConsoleLogger,
132 }
134
135impl MonitorLogger {
136 pub fn new(is_production: bool) -> Self {
138 Self { inner: ConsoleLogger::new(is_production) }
139 }
140}
141
142#[async_trait]
143impl ILogger for MonitorLogger {
144 async fn info(&self, msg: &str) { self.inner.info(msg).await }
145 async fn debug(&self, msg: &str) { self.inner.debug(msg).await }
146 async fn warn(&self, msg: &str) { self.inner.warn(msg).await }
147 async fn error(&self, msg: &str) { self.inner.error(msg).await }
148 async fn exec(&self, msg: &str) { self.inner.exec(msg).await }
149 fn time(&self, msg: &str) -> TimeEvent { self.inner.time(msg) }
150}