1use std::io::Write;
25
26pub const TRACE: u32 = 5;
27pub const DEBUG: u32 = 4;
28pub const INFO: u32 = 3;
29pub const WARNING: u32 = 2;
30pub const ERROR: u32 = 1;
31pub const FATAL: u32 = 0;
32
33const LOG_PATH_VAR: &str = "SE_LOG_PATH";
34const LOG_LEVEL_VAR: &str = "SE_LOG_LEVEL";
35
36pub fn log_init(path: &str, level: u32) {
60 set_log_path(¤t_time_fmt(path));
61 set_log_level(level);
62}
63
64pub fn log(message: &str) {
66 println!("{message}");
67 let mut f = match std::fs::OpenOptions::new()
68 .append(true)
69 .create(true)
70 .open(get_log_path())
71 {
72 Ok(f) => f,
73 Err(e) => {
74 println!("Logger: Failed to open file: {e}");
75 return;
76 }
77 };
78 match f.write((message.to_string() + "\n").as_bytes()) {
79 Ok(_) => {}
80 Err(e) => {
81 println!("Logger: Failed to write to file: {e}");
82 return;
83 }
84 }
85}
86
87pub fn trace(message: &str) {
89 log_with_level(message, TRACE);
90}
91pub fn debug(message: &str) {
93 log_with_level(message, DEBUG);
94}
95pub fn info(message: &str) {
97 log_with_level(message, INFO);
98}
99pub fn warning(message: &str) {
101 log_with_level(message, WARNING);
102}
103pub fn error(message: &str) {
105 log_with_level(message, ERROR);
106}
107pub fn fatal(message: &str) {
109 log_with_level(message, FATAL);
110}
111
112fn log_with_level(message: &str, level: u32) {
113 if get_log_level() >= level {
114 log(&format!(
115 "[{}] [{}] [{}] {}",
116 current_time_fmt("%T"),
117 level_to_string(level),
118 match std::thread::current().name() {
119 Some(s) => s,
120 None => "unnamed thread",
121 },
122 message
123 ))
124 }
125}
126
127fn get_log_level() -> u32 {
128 match std::env::var(LOG_LEVEL_VAR) {
129 Ok(s) => match s.parse::<u32>() {
130 Ok(v) => v,
131 Err(_) => INFO,
132 },
133 Err(_) => INFO,
134 }
135}
136fn set_log_level(level: u32) {
137 if level >= FATAL && level <= TRACE {
138 std::env::set_var(LOG_LEVEL_VAR, level.to_string());
139 }
140}
141fn get_log_path() -> String {
142 match std::env::var(LOG_PATH_VAR) {
143 Ok(s) => s,
144 Err(_) => "unnamed.log".to_string(),
145 }
146}
147fn set_log_path(path: &str) {
148 std::env::set_var(LOG_PATH_VAR, path);
149}
150
151fn level_to_string(level: u32) -> String {
152 match level {
153 TRACE => "TRACE",
154 DEBUG => "DEBUG",
155 INFO => "INFO",
156 WARNING => "WARNING",
157 ERROR => "ERROR",
158 FATAL => "FATAL",
159 _ => "",
160 }
161 .to_string()
162}
163fn current_time_fmt(fmt: &str) -> String {
164 chrono::Local::now().format(fmt).to_string()
165}