1use std::fs;
2use std::io::{BufRead, BufReader};
3
4#[derive(PartialEq, Eq, PartialOrd, Clone, Copy, Debug)]
5pub enum LogTimeFormat {
6 TimeStamp,
7 TimeLocal,
8 TimeNone,
9}
10
11#[derive(Debug, Clone, Copy)]
12pub struct JloggerTimer {
13 time_format: LogTimeFormat,
14 system_start: i64,
15}
16
17impl JloggerTimer {
18 pub fn new(time_format: LogTimeFormat) -> Self {
19 let now = chrono::Local::now().timestamp();
20
21 let system_start = if let Ok(f) = fs::OpenOptions::new()
22 .create(false)
23 .write(false)
24 .read(true)
25 .open("/proc/stat")
26 {
27 let mut br = BufReader::new(f);
28
29 loop {
30 let mut buf = String::new();
31 if let Ok(n) = br.read_line(&mut buf) {
32 if n == 0 {
33 break now;
34 }
35
36 if buf.starts_with("btime") {
37 let v: Vec<&str> = buf.split_whitespace().into_iter().collect();
38 break v[1].parse::<i64>().unwrap();
39 }
40 }
41 }
42 } else {
43 now
44 };
45
46 Self {
47 time_format,
48 system_start,
49 }
50 }
51}
52
53impl tracing_subscriber::fmt::time::FormatTime for JloggerTimer {
54 fn format_time(&self, w: &mut tracing_subscriber::fmt::format::Writer<'_>) -> std::fmt::Result {
55 let time_str = match self.time_format {
56 LogTimeFormat::TimeNone => "".to_owned(),
57 LogTimeFormat::TimeStamp => {
58 let now = chrono::Local::now();
59 format!(
60 "{}.{:<09}",
61 now.timestamp() - self.system_start,
62 now.timestamp_nanos() % 1000000000
63 )
64 }
65 LogTimeFormat::TimeLocal => {
66 let now = chrono::Local::now();
67 format!("{}", now.format("%Y-%m-%d %H:%M:%S"))
68 }
69 };
70
71 w.write_str(time_str.as_str())
72 }
73}