captains_log/
formatter.rs1use log::{kv::Key, *};
2use std::{fmt, thread};
3
4use crate::time::Timer;
5
6pub struct TimeFormatter<'a> {
7 pub now: &'a Timer,
8 pub fmt_str: &'a str,
9}
10
11impl<'a> TimeFormatter<'a> {
12 #[inline(always)]
13 fn time_str(&self) -> String {
14 self.now.format(self.fmt_str).to_string()
15 }
16}
17
18pub struct FormatRecord<'a> {
20 pub record: &'a Record<'a>,
21 pub time: TimeFormatter<'a>,
22}
23
24impl<'a> FormatRecord<'a> {
25 #[inline(always)]
26 pub fn file(&self) -> &str {
27 basename(self.record.file().unwrap_or("<none>"))
28 }
29
30 #[inline(always)]
31 pub fn line(&self) -> u32 {
32 self.record.line().unwrap_or(0)
33 }
34
35 #[inline(always)]
36 pub fn timestamp_nano(&self) -> i64 {
37 self.time.now.timestamp_nanos_opt().unwrap_or(0)
38 }
39
40 #[inline(always)]
41 pub fn time(&self) -> String {
42 self.time.time_str()
43 }
44
45 #[inline(always)]
46 pub fn key(&self, key: &str) -> String {
47 let source = self.record.key_values();
48 if let Some(v) = source.get(Key::from_str(key)) {
49 return format!(" ({})", v).to_string();
50 } else {
51 return "".to_string();
52 }
53 }
54
55 #[inline(always)]
56 pub fn level(&self) -> Level {
57 self.record.level()
58 }
59
60 #[inline(always)]
61 pub fn msg(&self) -> &'a fmt::Arguments<'a> {
62 self.record.args()
63 }
64
65 #[inline(always)]
66 pub fn thread_id(&self) -> thread::ThreadId {
67 thread::current().id()
68 }
69}
70
71fn basename(path: &str) -> &str {
72 let res = path.rfind('/');
73 match res {
74 Some(idx) => path.get(idx + 1..).unwrap_or(path),
75 None => path,
76 }
77}