rs_utils/log/kv/
format.rs1use std;
4use env_logger;
5use log;
6
7pub struct EnvLoggerFormatConfig {
8 pub thread : bool,
9 pub target : bool,
10 pub file : bool
11}
12
13pub fn env_logger_json_formatter (config : EnvLoggerFormatConfig)
15 -> impl Fn(&mut env_logger::fmt::Formatter, &log::Record<'_>) -> std::io::Result<()>
16{
17 use std::io::Write;
18 #[derive(Default)]
19 struct KVVisitor(pub String);
20 impl <'kvs> log::kv::VisitSource <'kvs> for KVVisitor {
21 fn visit_pair (&mut self, key : log::kv::Key <'kvs>, value : log::kv::Value <'kvs>)
22 -> Result <(), log::kv::Error>
23 {
24 self.0 += format!(",\"{}\":{}", key, serde_json::to_string(&value).unwrap())
25 .as_str();
26 Ok(())
27 }
28 }
29 move |buf : &mut env_logger::fmt::Formatter, record : &log::Record|{
30 let thread_string = if config.thread {
31 std::thread::current().name().map_or_else (
32 || format!(",\"thread\":\"{:?}\"", std::thread::current().id())
33 .replace ("ThreadId", "unnamed"),
34 |name| format!(",\"thread\":\"{name}\""))
35 } else {
36 "".to_string()
37 };
38 let target_string = if config.target {
39 format!(",\"target\":\"{}\"", record.target())
40 } else {
41 "".to_string()
42 };
43 let file_string = if config.file {
44 format!(",\"file\":\"{}:{}\"", record.file().unwrap(), record.line().unwrap())
45 } else {
46 "".to_string()
47 };
48 let mut kvv = KVVisitor::default();
49 record.key_values().visit (&mut kvv).unwrap();
50 writeln!(buf, "{{\"ts\":\"{}\",\"level\":\"{}\"{}{}{},\"msg\":\"{}\"{}}}",
51 buf.timestamp(), record.level(), thread_string, target_string,
52 file_string, record.args(), kvv.0
53 )
54 }
55}
56
57pub fn env_logger_custom_formatter (config : EnvLoggerFormatConfig)
62 -> impl Fn(&mut env_logger::fmt::Formatter, &log::Record<'_>) -> std::io::Result<()>
63{
64 use std::io::Write;
65 #[derive(Default)]
66 struct KVVisitor(pub String);
67 impl <'kvs> log::kv::VisitSource <'kvs> for KVVisitor {
68 fn visit_pair (&mut self, key : log::kv::Key <'kvs>, value : log::kv::Value <'kvs>)
69 -> Result <(), log::kv::Error>
70 {
71 let mut value_string = serde_json::to_string (&value).unwrap();
72 let mut value_str = value_string.as_str();
73 if !value_str.contains (char::is_whitespace) {
74 value_string = value_str.replace ("\\\"", "\"");
77 value_str = if value_string.starts_with ('"') {
78 &value_string[1..value_string.len()-1]
79 } else {
80 &value_string[..]
81 };
82 }
83 self.0 += format!(" {key}={value_str}").as_str();
84 Ok(())
85 }
86 }
87 move |buf : &mut env_logger::fmt::Formatter, record : &log::Record|{
88 let mut kvv = KVVisitor::default();
89 record.key_values().visit (&mut kvv).unwrap();
90 let kvs = if kvv.0.is_empty() {
91 "".to_string()
92 } else {
93 format!(" {}", kvv.0)
94 };
95 if !config.file && !config.thread && !config.target {
96 let level_string = format!("{}:", record.level());
97 writeln!(buf, "{} {:6} {}{}", buf.timestamp(), level_string, record.args(), kvs)
98 } else {
99 let thread_string = if config.thread {
100 std::thread::current().name().map_or_else (
101 || format!(" {:?}", std::thread::current().id())
102 .replace ("ThreadId", "unnamed"),
103 |name| format!(" {name}"))
104 } else {
105 "".to_string()
106 };
107 let target_string = if config.target {
108 format!(" {}", record.target())
109 } else {
110 "".to_string()
111 };
112 let file_string = if config.file {
113 format!(" {}:{}", record.file().unwrap(), record.line().unwrap())
114 } else {
115 "".to_string()
116 };
117 writeln!(buf, "{} {:5}{}{}{}: {}{}",
118 buf.timestamp(), record.level(), thread_string, target_string, file_string,
119 record.args(), kvs)
120 }
121 }
122}
123
124impl Default for EnvLoggerFormatConfig {
125 fn default() -> Self {
126 EnvLoggerFormatConfig {
127 thread: true,
128 target: true,
129 file: true
130 }
131 }
132}