galacta_logger/
lib.rs

1//! Simple logger crate
2//!
3//! # Usage
4//!
5//! You can use logger without any initialization.
6//! You may set "G_LOG_LEVEL" environment variable by [`LevelFilter`] value.
7//! ```
8//! /// These are logs without specified target or initializations(recommended)
9//! use galacta_logger::{self,prelude::*};
10//! gerror!("This is errror");
11//! gwarn!("This is warning");
12//! ginfo!("This is info");
13//! gdebug!("This is debug");
14//! gtrace!("This is trace");
15//! ```
16//!
17//! You also can use logger with initialization.
18//! ```
19//! use galacta_logger::{self,GalactaLogger,LevelFilter,prelude::*};
20//! /// First initialize logger.
21//! /// You may set "G_LOG_LEVEL" environment variable by [`LevelFilter`] value.
22//! /// If environment variable is set, argument of init function will be ignored
23//! GalactaLogger::init(LevelFilter::Trace);
24//!
25//! /// These are logs with specified target(unrecommended)
26//! error!("This is errror");
27//! warn!(target: "target","This is warning");
28//! info!("This is info");
29//! debug!("This is debug");
30//! trace!("This is trace");
31//! ```
32//!
33#![warn(missing_docs)]
34#![warn(rustdoc::missing_crate_level_docs)]
35#![allow(unused_imports)]
36#[macro_use]
37extern crate log;
38extern crate chrono;
39use log::{Metadata, Record, SetLoggerError};
40
41/// Enum for setting max level of log
42pub use log::LevelFilter;
43
44use std::env;
45use std::str::FromStr;
46
47/// prerule include macros.
48///
49/// # RECCOMENDATION
50/// "use galacta_logger::prelude::*" is strongly reccomended
51pub mod prelude {
52    /// Structure of Logger
53    pub use super::GalactaLogger;
54    /// macro for invoke debug level log with specified target
55    pub use log::debug;
56    /// macro for invoke error level log with specified target
57    pub use log::error;
58    /// macro for invoke info level log with specified target
59    pub use log::info;
60    /// macro for invoke trace level log with specified target
61    pub use log::trace;
62    /// macro for invoke warn level log with specified target
63    pub use log::warn;
64    /// enum for initialize logger for [`super::GalactaLogger::init()`] function
65    pub use log::LevelFilter;
66    /// macro for invoke debug level log without initialization and target
67    pub use super::gdebug;
68    /// macro for invoke error level log without initialization and target
69    pub use super::gerror;
70    /// macro for invoke info level log without initialization and target
71    pub use super::ginfo;
72    /// macro for invoke trace level log without initialization and target
73    pub use super::gtrace;
74    /// macro for invoke warn level log without initialization and target
75    pub use super::gwarn;
76}
77
78/// macro for invoke debug level log without initialization and target
79#[macro_export]
80macro_rules! gdebug {
81    ( $($x:expr),* ) => {{
82        let _result = GalactaLogger::init(LevelFilter::Trace);
83        struct Dummy {}
84        let tmp = std::any::type_name::<Dummy>();
85        let target: &str = &tmp[..tmp.len()-7];
86        debug!(target: target,$($x),*)
87    }}
88}
89
90/// macro for invoke debug error log without initialization and target
91#[macro_export]
92macro_rules! gerror {
93    ( $($x:expr),* ) => {{
94        let _result = GalactaLogger::init(LevelFilter::Trace);
95        struct Dummy {}
96        let tmp = std::any::type_name::<Dummy>();
97        let target: &str = &tmp[..tmp.len()-7];
98        error!(target: target,$($x),*)
99    }}
100}
101
102/// macro for invoke info level log without initialization and target
103#[macro_export]
104macro_rules! ginfo {
105    ( $($x:expr),* ) => {{
106        let _result = GalactaLogger::init(LevelFilter::Trace);
107        struct Dummy {}
108        let tmp = std::any::type_name::<Dummy>();
109        let target: &str = &tmp[..tmp.len()-7];
110        info!(target: target,$($x),*)
111    }}
112}
113
114/// macro for invoke trace level log without initialization and target
115#[macro_export]
116macro_rules! gtrace {
117    ( $($x:expr),* ) => {{
118        let _result = GalactaLogger::init(LevelFilter::Trace);
119        struct Dummy {}
120        let tmp = std::any::type_name::<Dummy>();
121        let target: &str = &tmp[..tmp.len()-7];
122        trace!(target: target,$($x),*)
123    }}
124}
125
126/// macro for invoke warn level log without initialization and target
127#[macro_export]
128macro_rules! gwarn {
129    ( $($x:expr),* ) => {{
130        let _result = GalactaLogger::init(LevelFilter::Trace);
131        struct Dummy {}
132        let tmp = std::any::type_name::<Dummy>();
133        let target: &str = &tmp[..tmp.len()-7];
134        warn!(target: target,$($x),*)
135    }}
136}
137
138/// Logger structure
139pub struct GalactaLogger;
140
141impl GalactaLogger {
142    /// Initialize logger.
143    /// You MUST initialize logger before any log messages.
144    ///
145    /// # NOTE
146    /// You can use either environment variable "GALACTA_LOG_LEVEL" or variable
147    /// "default_max_level" for setting max level of logging.
148    /// Environment variable overrides inline variable.
149    pub fn init(default_max_level: LevelFilter) -> Result<(), SetLoggerError> {
150        match env::var("G_LOG_LEVEL") {
151            Ok(val) => {
152                let env_max_level =
153                    LevelFilter::from_str(val.as_str()).unwrap_or_else(|_| LevelFilter::max());
154                log::set_max_level(env_max_level);
155                log::set_boxed_logger(Box::new(GalactaLogger))
156            }
157            Err(_) => {
158                log::set_max_level(default_max_level);
159                log::set_boxed_logger(Box::new(GalactaLogger))
160            }
161        }
162    }
163}
164
165/// Needed implementation of Log trait for logger
166impl log::Log for GalactaLogger {
167    fn enabled(&self, metadata: &Metadata) -> bool {
168        metadata.level() <= log::STATIC_MAX_LEVEL
169    }
170
171    fn log(&self, record: &Record) {
172        if self.enabled(record.metadata()) {
173            let timedate: String = chrono::Local::now().format("%F %T").to_string();
174            let module_path: String = record.module_path().unwrap_or("Unknown module").to_string();
175            let level: String = record.level().to_string();
176            let message = record.args();
177            let file_path: String = record.file().unwrap_or("Unknown file").to_string();
178            let line: String = record.line().unwrap_or(0).to_string();
179            let target:String = record.target().to_string();
180            //let log_massage: String = format!("[{}] {} {} {} {} {} {}",timedate,level,target,module_path,message,file_path,line);
181            let log_massage: String = format!(
182                "\n[{}] [{}] {}\n{}\n{} ({}:{})\n",
183                timedate, level,target, message, module_path, file_path, line,
184            );
185            eprintln!("{}", log_massage);
186        }
187    }
188
189    fn flush(&self) {}
190}
191
192#[cfg(test)]
193mod tests {
194    use super::*;
195
196    mod another_module {
197        pub fn another_function() {
198            info!("This is from another function");
199        }
200    }
201    #[test]
202    fn test_log_first_use() {
203        let _result = GalactaLogger::init(LevelFilter::Trace);
204        info!("This is first log test");
205        another_module::another_function();
206        info!("This is info");
207        warn!("This is warn");
208    }
209
210    #[test]
211    fn test_log_env_level_max() {
212        let _result = GalactaLogger::init(LevelFilter::Trace);
213        error!(target: "test_log_env_level_max()","This is error");
214        warn!(target: "test_log_env_level_max()","This is warning");
215        info!(target: "test_log_env_level_max()","This is information");
216        debug!(target: "test_log_env_level_max()","This is debug information");
217        trace!(target: "test_log_env_level_max()","This is trace information");
218    }
219
220    #[test]
221    fn test_gdebug() {
222        fn errfunc() {
223            gerror!("This is gerror");
224        }
225        errfunc();
226        gdebug!("This is gdebug");
227        gwarn!("This is gwarn");
228        ginfo!("This is ginfo");
229        gtrace!("This is gtrace");
230
231    }
232}