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) -> impl
15 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,
22 key : log::kv::Key <'kvs>, value : log::kv::Value <'kvs>
23 ) -> Result <(), log::kv::Error> {
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()
32 .map (|name| format!(",\"thread\":\"{}\"", name))
33 .unwrap_or_else (||
34 format!(",\"thread\":\"{:?}\"",
35 std::thread::current().id()).replace ("ThreadId", "unnamed"))
36 } else {
37 "".to_string()
38 };
39 let target_string = if config.target {
40 format!(",\"target\":\"{}\"", record.target())
41 } else {
42 "".to_string()
43 };
44 let file_string = if config.file {
45 format!(",\"file\":\"{}:{}\"",
46 record.file().unwrap(), record.line().unwrap())
47 } else {
48 "".to_string()
49 };
50 let mut kvv = KVVisitor::default();
51 record.key_values().visit (&mut kvv).unwrap();
52 writeln!(buf,
53 "{{\"ts\":\"{}\",\"level\":\"{}\"{}{}{},\"msg\":\"{}\"{}}}",
54 buf.timestamp(), record.level(), thread_string, target_string,
55 file_string, record.args(), kvv.0
56 )
57 }
58}
59
60pub fn env_logger_custom_formatter (config : EnvLoggerFormatConfig) -> impl
65 Fn(&mut env_logger::fmt::Formatter, &log::Record<'_>) -> std::io::Result<()>
66{
67 use std::io::Write;
68 #[derive(Default)]
69 struct KVVisitor(pub String);
70 impl <'kvs> log::kv::VisitSource <'kvs> for KVVisitor {
71 fn visit_pair (&mut self,
72 key : log::kv::Key <'kvs>, value : log::kv::Value <'kvs>
73 ) -> Result <(), log::kv::Error> {
74 let mut value_string = serde_json::to_string (&value).unwrap();
75 let mut value_str = value_string.as_str();
76 if !value_str.contains (char::is_whitespace) {
77 value_string = value_str.replace("\\\"", "\"");
80 value_str = if value_string.chars().next() == Some('"') {
81 &value_string[1..value_string.len()-1]
82 } else {
83 &value_string[..]
84 };
85 }
86 self.0 += format!(" {}={}", key, value_str).as_str();
87 Ok(())
88 }
89 }
90 move |buf : &mut env_logger::fmt::Formatter, record : &log::Record|{
91 let mut kvv = KVVisitor::default();
92 record.key_values().visit (&mut kvv).unwrap();
93 let kvs = if kvv.0.is_empty() {
94 "".to_string()
95 } else {
96 format!(" {}", kvv.0)
97 };
98 if !config.file && !config.thread && !config.target {
99 let level_string = format!("{}:", record.level());
100 writeln!(buf,
101 "{} {:6} {}{}", buf.timestamp(), level_string, record.args(), kvs)
102 } else {
103 let thread_string = if config.thread {
104 std::thread::current().name().map (|name| format!(" {}", name))
105 .unwrap_or_else (||
106 format!(" {:?}",
107 std::thread::current().id()).replace ("ThreadId", "unnamed"))
108 } else {
109 "".to_string()
110 };
111 let target_string = if config.target {
112 format!(" {}", record.target())
113 } else {
114 "".to_string()
115 };
116 let file_string = if config.file {
117 format!(" {}:{}", record.file().unwrap(), record.line().unwrap())
118 } else {
119 "".to_string()
120 };
121 writeln!(buf,
122 "{} {:5}{}{}{}: {}{}",
123 buf.timestamp(), record.level(), thread_string, target_string,
124 file_string, record.args(), kvs)
125 }
126 }
127}
128
129impl Default for EnvLoggerFormatConfig {
130 fn default() -> Self {
131 EnvLoggerFormatConfig {
132 thread: true,
133 target: true,
134 file: true
135 }
136 }
137}