1use std::{fs::OpenOptions, io::Write, process};
2
3use chrono::Local;
4
5#[derive(Debug)]
15enum LogView {
16 Info,
18 Warning,
20 Stop,
22 Error,
24 Critical,
26}
27
28#[derive(Debug)]
36struct LogText {
37 view: LogView,
39 number: u16,
41 text: Option<String>,
43}
44
45static mut LOG_FILE: String = String::new();
47
48pub struct Log;
50
51impl Log {
52 pub fn info(number: u16, text: Option<String>) -> String {
59 Log::save(LogText { view: LogView::Info, number, text })
60 }
61
62 pub fn warning(number: u16, text: Option<String>) -> String {
69 Log::save(LogText { view: LogView::Warning, number, text })
70 }
71
72 pub fn stop(number: u16, text: Option<String>) -> String {
79 Log::save(LogText { view: LogView::Stop, number, text })
80 }
81
82 pub fn error(number: u16, text: Option<String>) -> ! {
93 Log::save(LogText { view: LogView::Error, number, text });
94 process::exit(number as i32);
95 }
96
97 pub fn set_path(path: String) {
103 unsafe { LOG_FILE = path };
104 }
105
106 fn save(log: LogText) -> String {
112 let time = Local::now().format("%Y.%m.%d %H:%M:%S%.9f").to_string();
113 let text = match log.text {
114 Some(s) => format!("Text: {} -> {}", Log::number_to_text(log.number), s),
115 None => format!("Text: {}", Log::number_to_text(log.number)),
116 };
117 let str = format!("ID: {} Time: {} Type: {:?}. Number: {} {}\n", process::id(), time, log.view, log.number, text);
118
119 #[cfg(debug_assertions)]
120 eprintln!("{}", str.trim_end());
121
122 let mut file = unsafe { LOG_FILE.as_str() };
123 if file.is_empty() {
124 file = "tiny.log";
125 }
126 match OpenOptions::new().create(true).append(true).open(file) {
127 Ok(mut file) => match file.write_all(str.as_bytes()) {
128 Ok(f) => f,
129 Err(e) => Log::panic(&e.to_string()),
130 },
131 Err(e) => Log::panic(&format!("Can't save data to log file {} -> {}", file, e)),
132 };
133 text
134 }
135
136 fn panic(text: &str) -> ! {
142 let time = Local::now().format("%Y.%m.%d %H:%M:%S%.9f").to_string();
143 let str = format!("ID: {} Time: {} Type: {:?}. Number: Text: Panic error -> {}\n", process::id(), time, LogView::Critical, text);
144 let file = unsafe { LOG_FILE.as_str() };
145 match OpenOptions::new().create(true).append(true).open(file) {
146 Ok(mut f) => {
147 if let Err(e) = f.write_all(str.as_bytes()) {
148 let str = format!(
149 r#"ID: {} Time: {} Type: {:?}. Number111: Text: Can't write log file "{}" - {}"#,
150 process::id(),
151 time,
152 LogView::Critical,
153 file,
154 e
155 );
156 eprintln!("{}", &str);
157 }
158 }
159 Err(e) => {
160 let str = format!(
161 r#"ID: {} Time: {} Type: {:?}. Number: Text: Can't open log file "{}" - {}"#,
162 process::id(),
163 time,
164 LogView::Critical,
165 file,
166 e
167 );
168 eprintln!("{}", &str);
169 }
170 };
171 process::exit(1);
172 }
173
174 fn number_to_text(number: u16) -> &'static str {
184 match number {
185 1 => "Can't create runtime for async server",
186 2 => "Mutex can't lock cache",
187 3 => "Implementation of this protocol later",
188
189 10 => "Unable to get the app path",
190 11 => "The app path contains invalid characters",
191 12 => "The app must be on a local computer",
192 13 => "There is no path to the config file specified after the -r option",
193 14 => "Can't read the config file",
194 15 => "The config file is not found",
195 16 => "Can't detect the app path",
196 17 => "Init mode",
197 18 => "The config file 'tine.toml' is not a TOML https://toml.io/ format",
198 19 => "The lang file is not a TOML https://toml.io/ format",
199
200 50 => "The 'salt' parameter in the configuration file must be set",
201 51 => "The 'lang' parameter in the configuration file must be a string and consist of two characters according to ISO 639-1",
202 52 => "The 'max' parameter in the configuration file must be usize and greater than 0 or \"auto\"",
203 53 => "The 'bind_from' parameter in the configuration file must be IP address in format xxx.xxx.xxx.xxx or \"any\" or empty for Unix domain socket",
204 54 => "The 'bind' parameter in the configuration file must be IP:PORT address in format xxx.xxx.xxx.xxx:yyyy or Unix domain socket",
205 55 => "The 'rpc_from' parameter in the configuration file must be IP address in format xxx.xxx.xxx.xxx or \"any\" or empty for Unix domain socket",
206 56 => "The 'rpc' parameter in the configuration file must be IP:PORT address in format xxx.xxx.xxx.xxx:yyyy or Unix domain socket",
207 57 => "The 'db_port' parameter in the configuration file must be bool. If true sslmode is requeres",
208 58 => "The 'db_max' parameter in the configuration file must be usize and greater than 0 or \"auto\"",
209 59 => "The 'db_host' parameter in the configuration file can't be empty",
210 61 => "The 'log' parameter in the configuration file must be a string",
211 62 => "The 'salt' parameter in the configuration file must be a string",
212 63 => "The 'db_host' parameter in the configuration file must be a string",
213 64 => "The 'db_name' parameter in the configuration file must be a string",
214 65 => "The 'db_user' parameter in the configuration file must be a string",
215 66 => "The 'db_pwd' parameter in the configuration file must be a string",
216 67 => "The 'sslmode' parameter in the configuration file can be a bool",
217 71 => "The 'session' parameter in the configuration file must be a string",
218 74 => "The 'action_index' parameter in the configuration file must be a string",
219 75 => "The 'action_index' parameter in the configuration file must start with the character '/' and consist of 3 or 4 non-empty parts separated by the character '/'",
220 76 => "The 'action_not_found' parameter in the configuration file must be a string",
221 77 => "The 'action_not_found' parameter in the configuration file must start with the character '/' and consist of 3 or 4 non-empty parts separated by the character '/'",
222 78 => "The 'action_err' parameter in the configuration file must be a string",
223 79 => "The 'action_err' parameter in the configuration file must start with the character '/' and consist of 3 or 4 non-empty parts separated by the character '/'",
224 81 => "The 'lang' parameter in the command line must consist of two characters according to ISO 639-1",
225
226 100 => "Error sending message",
227 101 => "Error write message to the tcp stream",
228 102 => "Error wait join handle",
229
230 200 => "Start",
231 201 => "Stop",
232 202 => "Unable to open rpc port",
233 203 => "IP address for rpc control is not allowed",
234 204 => "Reading from the rpc stream timed out",
235 205 => "Error reading from the rpc",
236 206 => "Received signal is not the stop or status signals",
237 207 => "Stop signal received successfully",
238 211 => "The app start successfully",
239 212 => "Can't start the app",
240 213 => "Can't connect to the server",
241 214 => "Can't send 'stop' signal to the server",
242 215 => "Can't write 'stop' signal to the stream",
243 216 => "Can't set read_timeout",
244 217 => "Can't read signal from stream",
245 218 => "Stop signal sent successfully",
246 219 => "Can't set TCP_NODELAY",
247 220 => "An error occurred while waiting for the main thread to stop",
248 221 => "Unable to connect to server due to timeout",
249 222 => "Can't connect to server",
250 223 => "Can't set write_timeout",
251 224 => "Can't send 'status' signal to the server",
252 225 => "Can't read answer from stream",
253 226 => "Can't recognize answer from stream",
254 227 => "Status signal received successfully",
255 #[cfg(debug_assertions)]
256 228 => "Get request",
257 #[cfg(debug_assertions)]
258 229 => "Load lang file",
259 #[cfg(debug_assertions)]
260 230 => "Load html template file",
261 231 => "Couldn't get client",
262
263 400 => "Unsupported HTTP protocol",
264
265 500 => "Unable to open server port",
266 501 => "IP address from which to accept connections is not allowed",
267 502 => "Failed to send completion signal",
268 503 => "An error occurred while waiting for the main thread to stop",
269 504 => "Critical socket operation error",
270 505 => "An error occurred while waiting for the threads to abort",
271 506 => "Can't set TCP_NODELAY",
272 507 => "Can't load SSL certicertificate or private key files",
273
274 600 => "Can't create tlsconnector to database",
275 601 => "Can't connect to database",
276 602 => "Can't execute query",
277 603 => "Connection to database is lost",
278 604 => "Database is not initialized",
279 605 => "Database is closed. Reconnect is disabled.",
280 606 => "Can't receive free permit from pool database.",
281 607 => "Can't find free database, but semaphore says that can free.",
282 609 => "Can't parse connection string",
283 610 => "Can't create pool of connections",
284 611 => "Error close connection task in connection with database",
285 612 => "Error close connection with database",
286 613 => "Can't prepare statement",
287 614 => "Unknown database type",
288 615 => "Key not found",
289 616 => "Connection with database is wrong",
290
291 700 => "Error parse html template",
292
293 1100 => "Can't open root_dir/app",
294 1101 => "Can't get dir entry",
295 1102 => "Can't open dir",
296 1103 => "Can't delete input file",
297
298 1200 => "Unable to specify node type",
299 1201 => r#"Unable to specify "if" node type"#,
300 1202 => r#"Unable to specify "loop" node type"#,
301
302 1150 => "Can't load languages from database",
303 1151 => "Language list is empty",
304
305 2000 => "Unable to read from stream",
306 2001 => "It is not possible to read the first time from the stream, due to a timeout",
307 2002 => "Can't create temp file",
308 2003 => "Can't write temp file",
309 2004 => "The temporary file is partially written",
310 2005 => "Clock may have gone backwards",
311 2006 => "System error with buffer",
312 #[cfg(feature = "https")]
313 2007 => "A wrapper around a rustls::ServerConfig, providing an async accept method cannot accept an https stream",
314
315 3000 => "Wrong cache type key of Redirect",
317 3001 => "Wrong cache type key of Route",
318 3002 => "Cannot serialize Mail Message",
319 3003 => "Cannot get Message-ID",
320 3004 => r#"Unable to read "from" mail"#,
321 3005 => r#"Unable to read "reply-to" mail"#,
322 3006 => r#"Unable to read "to" mail"#,
323 3007 => r#"Unable to read "cc" mail"#,
324 3008 => r#"Unable to read "bcc" mail"#,
325 3009 => "Unable to create mail message",
326 3010 => "Unable to get content type from filename",
327 3011 => "Cannot read parameter for Mail config",
328 3012 => "Cannot send email via sendmail transport",
329 3013 => "Cannot send email via file transport",
330 3014 => "Cannot send email via smtp transport",
331 3015 => "Cannot create dir for file transport",
332
333 _ => "Unknown error"
334 }
335 }
336}