tlog/
lib.rs

1/*!
2A dumb debug tool which writes logs into file. Timestamp & pid will be
3added to the logs.
4
5# Usage
6
7```rust
8use tlog::tlog;
9
10tlog!("{} = {}", "5 x 7", 5 * 7);
11```
12
13Logs will be written to file `/tmp/t.log` unless changed with env `TMP_LOG_FILE`.
14
15```
16$ cat /tmp/t.log
17[2022-09-05 11:10:31.763][15235] 5 x 7 = 35
18```
19*/
20
21use std::fmt;
22use time::OffsetDateTime;
23
24#[derive(Debug, PartialEq, Eq)]
25pub struct DateTime {
26    odt: OffsetDateTime,
27}
28
29impl DateTime {
30    pub fn now() -> Self {
31        let odt: OffsetDateTime;
32        match OffsetDateTime::now_local() {
33            Ok(dt) => {
34                odt = dt;
35            }
36            Err(_) => {
37                odt = OffsetDateTime::now_utc();
38            }
39        }
40        DateTime { odt }
41    }
42}
43
44impl fmt::Display for DateTime {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        write!(f, "{:04}-{:02}-{:02} {:02}:{:02}:{:02}.{:03}",
47            self.odt.year(),
48            self.odt.month() as u8,
49            self.odt.day(),
50            self.odt.hour(),
51            self.odt.minute(),
52            self.odt.second(),
53            self.odt.millisecond(),
54        )
55    }
56}
57
58pub fn getpid() -> i32 {
59    unsafe { libc::getpid() }
60}
61
62#[macro_export]
63macro_rules! tlog {
64    ($fmt:expr) => (
65        use std::io::Write as _;
66
67        let msg = $fmt;
68        let default_log_file = String::from("/tmp/t.log");
69        let log_file = if let Ok(x) = std::env::var("TMP_LOG_FILE") {
70            if x.is_empty() { default_log_file } else { x.clone() }
71        } else {
72            default_log_file
73        };
74
75        let mut cfile;
76        match std::fs::OpenOptions::new().append(true).create(true).open(&log_file) {
77            Ok(x) => cfile = x,
78            Err(_) => panic!("tlog: open file error"),
79        }
80        let pid = tlog::getpid();
81        let now = tlog::DateTime::now();
82        let msg = format!("[{}][{}] {}", now, pid, msg);
83        let msg = if msg.ends_with('\n') { msg } else { format!("{}\n", msg) };
84        match cfile.write_all(msg.as_bytes()) {
85            Ok(_) => {}
86            Err(_) => panic!("tlog: write_all error")
87        }
88    );
89
90    ($fmt:expr, $($arg:tt)*) => (
91        let msg = format!($fmt, $($arg)*);
92        tlog!(&msg);
93    );
94}
95
96pub fn type_name<T>(_: &T) -> String {
97    format!("{}", std::any::type_name::<T>())
98}