prettylogger/
config.rs

1//! Implements various types used to customize `Logger`, `LogFormatter` and
2//! output streams' behavior.
3
4/// Implements various types used to customize `Logger`, `LogFormatter` and
5/// output streams' behavior.
6use serde::{
7    Serialize,
8    Deserialize
9};
10use std::fmt::{
11    Display,
12    Formatter
13};
14use chrono::{
15    Local,
16    DateTime
17};
18
19use crate::Error;
20
21/// Used to set the verbosity of a `Logger`.
22///
23/// # Examples
24///
25/// Setting `Logger` verbosity:
26/// ```
27/// # use prettylogger::{Logger, config::Verbosity};
28/// # let mut logger = Logger::default();
29/// logger.set_verbosity(Verbosity::Quiet);
30/// ```
31#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Debug, Default,
32    Serialize, Deserialize)]
33pub enum Verbosity {
34    /// Display all logs
35    All = 0,
36    #[default]
37    /// Only filter debug logs
38    Standard = 1,
39    /// Only display errors and warnings
40    Quiet = 2,
41    /// Only display errors
42    ErrorsOnly = 3,
43}
44
45/// Defines the policy for handling log file flushing when a `FileStream`
46/// instance is dropped.
47///
48/// # Examples
49///
50/// Setting on drop policy:
51/// ```rust
52/// # use prettylogger::{
53/// #     output::FileStream,
54/// #     config::OnDropPolicy,
55/// # };
56/// let mut file_stream = FileStream::default();
57/// file_stream.set_on_drop_policy(OnDropPolicy::IgnoreLogFileLock);
58/// ```
59#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default,
60    Serialize, Deserialize)]
61pub enum OnDropPolicy {
62    /// Ignore the log file lock and write to the file anyway. This may cause
63    /// race conditions
64    IgnoreLogFileLock,
65    #[default]
66    /// Respect the log file lock and don't write to the log file. This may
67    /// cause data loss
68    DiscardLogBuffer,
69}
70
71
72/// Represents different types of log messages.
73///
74/// Used internally by `LogStruct`, `LogFormatter`, `Logger` and various log
75/// streams.
76///
77/// # Examples
78///
79/// Setting log type of a `LogStruct`:
80/// ```rust
81/// # use prettylogger::config::{
82/// #     LogStruct,
83/// #     LogType,
84/// # };
85/// let mut log = LogStruct::debug("This is going to be an error message");
86/// log.log_type = LogType::Err;
87/// ```
88#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default,
89    Serialize, Deserialize)]
90pub enum LogType {
91    /// A debug log
92    Debug = 0,
93    #[default]
94    /// A standard, informative message
95    Info = 1,
96    /// A warning
97    Warning = 2,
98    /// An error
99    Err = 3,
100    /// A critical error
101    FatalError = 4,
102}
103
104/// Represents a single log entry.
105///
106/// Used internally by `LogFormatter`, `Logger` and various log streams.
107///
108/// # Examples
109///
110/// Print a formatted log message:
111/// ```
112/// # use prettylogger::{Logger, config::LogStruct};
113/// # let mut logger = Logger::default();
114/// // Get a formatted log message from a `LogStruct` instance
115/// let log = logger.formatter.lock().unwrap()
116///     .format_log(&LogStruct::error("Much bad!"));
117/// print!("{}", &log);
118/// ```
119#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
120pub struct LogStruct {
121    /// The log message
122    pub message: String,
123    /// The type of the log (e.g., `Debug`, `Info`, `Warning`, etc.)
124    pub log_type: LogType,
125    /// The date and time at which the log struct was instantiated
126    pub datetime: DateTime<Local>,
127}
128
129impl LogStruct {
130    /// Returns a `LogStruct` with **debug** preset applied.
131    ///
132    /// # Examples
133    ///
134    /// Creating a debug log:
135    /// ```
136    /// # use prettylogger::config::LogStruct;
137    /// let debug_log = LogStruct::debug("This is a debug log!");
138    /// ```
139    pub fn debug(message: &str) -> LogStruct {
140        LogStruct {
141            message: message.to_string(),
142            log_type: LogType::Debug,
143            datetime: Local::now(),
144        }
145    }
146
147    /// Returns a `LogStruct` with **info** preset applied.
148    ///
149    /// # Examples
150    ///
151    /// Creating an informative log:
152    /// ```
153    /// # use prettylogger::config::LogStruct;
154    /// let info_log = LogStruct::info("This is an info log!");
155    /// ```
156    pub fn info(message: &str) -> LogStruct {
157        LogStruct {
158            message: message.to_string(),
159            log_type: LogType::Info,
160            datetime: Local::now(),
161        }
162    }
163
164    /// Returns a `LogStruct` with **warning** preset applied.
165    ///
166    /// # Examples
167    ///
168    /// Creating a warning log:
169    /// ```
170    /// # use prettylogger::config::LogStruct;
171    /// let warning_log = LogStruct::warning("This is a warning!");
172    /// ```
173    pub fn warning(message: &str) -> LogStruct {
174        LogStruct {
175            message: message.to_string(),
176            log_type: LogType::Warning,
177            datetime: Local::now(),
178        }
179    }
180
181    /// Returns a `LogStruct` with **error** preset applied.
182    ///
183    /// # Examples
184    ///
185    /// Creating an error log:
186    /// ```
187    /// # use prettylogger::config::LogStruct;
188    /// let error_log = LogStruct::error("This is an error!");
189    /// ```
190    pub fn error(message: &str) -> LogStruct {
191        LogStruct {
192            message: message.to_string(),
193            log_type: LogType::Err,
194            datetime: Local::now(),
195        }
196    }
197
198    /// Returns a `LogStruct` with **fatal error** preset applied.
199    ///
200    /// # Examples
201    ///
202    /// Creating a fatal error log:
203    /// ```
204    /// # use prettylogger::config::LogStruct;
205    /// let fatal_log = LogStruct::fatal_error("This is a fatal error!");
206    /// ```
207    pub fn fatal_error(message: &str) -> LogStruct {
208        LogStruct {
209            message: message.to_string(),
210            log_type: LogType::FatalError,
211            datetime: Local::now(),
212        }
213    }
214}
215
216impl Display for LogStruct {
217    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
218        write!(
219            f,
220            "Log: {}\nType: {:?}\nDateTime: {}",
221            self.message,
222            self.log_type,
223            self.datetime
224        )
225    }
226}
227
228
229impl std::fmt::Display for Verbosity {
230    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
231        let level_str = match *self {
232            Verbosity::All => "All",
233            Verbosity::Standard => "Standard",
234            Verbosity::Quiet => "Quiet",
235            Verbosity::ErrorsOnly => "ErrorsOnly",
236        };
237        write!(f, "{level_str}")
238    }
239}
240
241impl TryFrom<i32> for Verbosity {
242    type Error = Error;
243    fn try_from(value: i32) -> Result<Self, Self::Error> {
244        match value {
245            0 => Ok(Verbosity::All),
246            1 => Ok(Verbosity::Standard),
247            2 => Ok(Verbosity::Quiet),
248            3 => Ok(Verbosity::ErrorsOnly),
249            _ => Err(Error::new("Invalid value. Please provide a value in range from 0 to 3.")),
250        }
251    }
252}
253
254impl AsRef<str> for Verbosity {
255    fn as_ref(&self) -> &str {
256        match self {
257            Verbosity::All => "All",
258            Verbosity::Standard => "Standard",
259            Verbosity::Quiet => "Quiet",
260            Verbosity::ErrorsOnly => "ErrorsOnly",
261        }
262    }
263}
264
265
266impl Display for OnDropPolicy {
267    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
268        let level_str = match *self {
269            OnDropPolicy::IgnoreLogFileLock => "IgnoreLogFileLock",
270            OnDropPolicy::DiscardLogBuffer => "DiscardLogBuffer",
271        };
272        write!(f, "{level_str}")
273    }
274}
275
276
277impl TryFrom<i32> for LogType {
278    type Error = Error;
279    fn try_from(value: i32) -> Result<Self, Self::Error> {
280        match value {
281            0 => Ok(LogType::Debug),
282            1 => Ok(LogType::Info),
283            2 => Ok(LogType::Warning),
284            3 => Ok(LogType::Err),
285            4 => Ok(LogType::FatalError),
286            _ => Err(Error::new("Invalid value. Please provide a value in range from 0 to 4.")),
287        }
288    }
289}
290
291impl Display for LogType {
292    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
293        let level_str = match *self {
294            LogType::Debug => "Debug",
295            LogType::Info => "Info",
296            LogType::Warning => "Warning",
297            LogType::Err => "Error",
298            LogType::FatalError => "FatalError",
299        };
300        write!(f, "{level_str}")
301    }
302}
303
304impl AsRef<str> for LogType {
305    fn as_ref(&self) -> &str {
306        match self {
307            LogType::Debug => "Debug",
308            LogType::Info => "Info",
309            LogType::Warning => "Warning",
310            LogType::Err => "Err",
311            LogType::FatalError => "FatalError",
312        }
313    }
314}