prettylogger/
setters.rs

1use crate::{
2    colors::*, fileio::*, filtering::*, logging::*
3};
4use std::io::{Error, ErrorKind};
5
6impl Logger {
7    /// Sets logger `verbosity`.
8    /// * `All` -> Don't filter any logs
9    /// * `Standard` -> Just filter debug logs
10    /// * `Quiet` -> Only let warnings and errors to be displayed
11    /// * `ErrorsOnly` -> I'm not gonna explain this one
12    pub fn set_verbosity<I: Into<Verbosity>>(&mut self, verbosity: I) {
13        self.verbosity = verbosity.into();
14    }
15
16
17    /// Toggles log filtering.
18    /// * **true**  -> logs will get filtered based on verbosity
19    /// * **false** -> log filtering will be disabled globally
20    pub fn toggle_log_filtering<I: Into<bool>>(&mut self, enabled: I) {
21        self.filtering_enabled = enabled.into();
22    }
23
24    /// Toggles colored log headers.
25    /// * `true`  -> Log headers will have colors 
26    /// * `false` -> No colors :(
27    pub fn toggle_log_header_color<I: Into<bool>>(&mut self, enabled: I) {
28        self.log_header_color_enabled = enabled.into();
29    }
30
31    /// Sets **debug log header** color.
32    pub fn set_debug_color<I: Into<Color>>(&mut self, color: I) {
33        self.debug_color = color.into();
34    }
35
36    /// Sets **info log header** color.
37    pub fn set_info_color<I: Into<Color>>(&mut self, color: I) {
38        self.info_color = color.into();
39    }
40
41    /// Sets **warning header** color.
42    pub fn set_warning_color<I: Into<Color>>(&mut self, color: I) {
43        self. warning_color = color.into();
44    }
45
46    /// Sets **error header** color.
47    pub fn set_error_color<I: Into<Color>>(&mut self, color: I) {
48        self.error_color = color.into();
49    }
50
51    /// Sets **fatal error header** color.
52    pub fn set_fatal_color<I: Into<Color>>(&mut self, color: I) {
53        self.fatal_color = color.into();
54    }
55
56    /// Sets **debug log header** format.
57    pub fn set_debug_header(&mut self, header: &str) {
58        self.debug_header = header.to_string();
59    }
60
61    /// Sets **info log header** format.
62    pub fn set_info_header(&mut self, header: &str) {
63        self.info_header = header.to_string();
64    }
65
66    /// Sets **warning header** format.
67    pub fn set_warning_header(&mut self, header: &str) {
68        self.warning_header = header.to_string();
69    }
70
71    /// Sets **error header** format.
72    pub fn set_error_header(&mut self, header: &str) {
73        self.error_header = header.to_string();
74    }
75
76    /// Sets **fatal error header** format.
77    pub fn set_fatal_header(&mut self, header: &str) {
78        self.fatal_header = header.to_string();
79    }
80
81    /// Sets datetime format.
82    pub fn set_datetime_format(&mut self, format: &str) {
83        self.datetime_format = String::from(format);
84    }
85
86    /// Sets the log format.
87    ///
88    /// There are three placeholders in a log format string (you can place
89    /// multiple placeholders of the same type in a format string):
90    /// * `%m` -> The log message (this placeholder is mandatory, you format
91    /// will get rejected if it doesn't contain this placeholder)
92    /// * `%h` -> The log type header (debug, error, etc.)
93    /// * `%d` -> The datetime
94    ///
95    /// # Set an XML-like log format;
96    /// ```
97    /// # use prettylogger::logging::Logger;
98    /// # let mut l = Logger::default();
99    /// l.set_log_format("<l> <h>%h</h> <m>%m</m> </l>");
100    /// l.error("A nice debug log!");
101    /// ```
102    ///
103    /// Returns an error when the `%m` placeholder is missing.
104    pub fn set_log_format(&mut self, format: &str) -> Result<(), &'static str> {
105        if format.contains("%m") {
106            self.log_format = String::from(format);
107            self.show_datetime = format.contains("%d");
108            Ok(())
109        }
110        else {
111            Err("Expected a message placeholder ('%m')!")
112        }
113    }
114
115    /// Sets log file path.
116    ///
117    /// Returns an error if the path is inaccessible.
118    ///
119    /// # Make sure to actually enable file logging:
120    /// ```ignore
121    /// # use prettylogger::logging::Logger;
122    /// # let mut logger = Logger::default();
123    /// // Set the log file path first:
124    /// logger.set_log_file_path("/path/to/file.log");
125    /// // Then enable file logging:
126    /// logger.toggle_file_logging(true);
127    /// ```
128    pub fn set_log_file_path(&mut self, path: &str) -> Result<(), Error> {
129        if is_file_writable(path) {
130            self.log_file_path = path.to_string();
131            overwrite_file(path, "")
132            .map_err(|e| {
133                    self.error(&format!("Failed to open file '{}' for writing!",
134                        self.log_file_path));
135                    Error::new(ErrorKind::Other,
136                        format!("Failed to overwrite file: {}", e))
137                })?;
138            Ok(())
139        } 
140        else {
141            self.error(&format!("Failed to open file '{}' for writing!",
142                self.log_file_path));
143            Err(Error::new(ErrorKind::PermissionDenied,
144                "File is not writable!"))
145        }
146    }
147
148    /// Toggles file logging.
149    ///
150    /// Before enabling file logging, ensure that the log file path is set. 
151    /// This is because the method checks if the log file is writable. If the
152    /// log  file path is not set, or the file is not writable, enabling file
153    /// logging will result in an error.
154    ///
155    /// # Enabling file logging:
156    /// ```ignore
157    /// # use prettylogger::logging::Logger;
158    /// # let mut logger = Logger::default();
159    /// // Set the log file path first:
160    /// logger.set_log_file_path("/path/to/file.log");
161    /// // Then enable file logging:
162    /// logger.toggle_file_logging(true);
163    /// ```
164    pub fn toggle_file_logging<I: Into<bool>>(&mut self, enabled: I)
165    -> Result<(), Error> {
166        if !enabled.into() {
167            self.file_logging_enabled = false;
168            Ok(())
169        }
170        else {
171            if is_file_writable(&self.log_file_path) {
172                self.file_logging_enabled = true;
173                Ok(())
174            }
175            else {
176                self.error(&format!("Failed to open file '{}' for writing!",
177                    self.log_file_path));
178                Err(Error::new(ErrorKind::PermissionDenied,
179                    "File is not writable!"))
180            }
181        }
182    }
183
184    /// Sets the maximum size of the log buffer.
185    ///
186    /// This method sets the maximum allowed size for the log buffer. When the
187    /// buffer exceeds this size, it will be automatically flushed to the log
188    /// file. If the buffer size is set to `0`, automatic flushing is disabled,
189    /// and the buffer can only be flushed manually.
190    ///
191    /// If a log file lock is active, the log buffer will not be flushed
192    /// automatically, regardless of the size limit.
193    ///
194    /// # Setting a custom log buffer size:
195    /// ```ignore
196    /// let mut logger = Logger::default();
197    /// logger.set_log_file_path("/path/to/file.log");
198    /// logger.toggle_file_logging(true);
199    ///
200    /// // This will force `Logger` to flush the log buffer every 16 logs:
201    /// logger.set_max_log_buffer_size(16);
202    ///
203    /// let mut i = 0;
204    /// loop {
205    ///     logger.info("Yay!");
206    ///     i += 1;
207    ///     if i >= 16 {
208    ///         break;
209    ///     }
210    /// }
211    /// ```
212    pub fn set_max_log_buffer_size<I: Into<usize>>(&mut self, size: I) {
213        self.log_buffer_max_size = size.into();
214    }
215
216    /// Log file lock can be used to prevent race conditions when there is one
217    /// thread reading from the log file and another thread writing to the log
218    /// file.
219    ///
220    /// # WARNING: LEAVING THIS OPTION ON FOR A LONG PERIOD OF TIME CAN CAUSE
221    /// HIGH MEMORY USAGE AND STUTTERING!
222    ///
223    /// `true`  -> When log file lock is enabled, logger won't flush into the
224    /// log file. Instead, it will wait until the lock is disabled. You will
225    /// not loose any logs, they will be stored in the log buffer even when it
226    /// exceeds its size limit.
227    /// `false` -> Logger will write to the log file normally.
228    pub fn toggle_log_file_lock<I: Into<bool>>(&mut self, enabled: I) {
229        self.log_file_lock = enabled.into();
230    }
231
232    /// Sets `Logger`'s on drop log file policy.
233    ///
234    /// ```
235    /// # use prettylogger::logging::{Logger, OnDropPolicy};
236    /// # let mut logger = Logger::default();
237    /// logger.set_on_drop_file_policy(OnDropPolicy::IgnoreLogFileLock);
238    /// ```
239    pub fn set_on_drop_file_policy<I: Into<OnDropPolicy>>(&mut self, policy: I) {
240        self.on_drop_policy = policy.into();
241    }
242}