logforth_bridge_log/
lib.rs1#![cfg_attr(docsrs, feature(doc_cfg))]
18
19use log::Metadata;
20use log::Record;
21use logforth_core::Logger;
22use logforth_core::default_logger;
23use logforth_core::kv::Key;
24use logforth_core::kv::Value;
25use logforth_core::record::FilterCriteria;
26
27fn level_to_level(level: log::Level) -> logforth_core::record::Level {
28 match level {
29 log::Level::Error => logforth_core::record::Level::Error,
30 log::Level::Warn => logforth_core::record::Level::Warn,
31 log::Level::Info => logforth_core::record::Level::Info,
32 log::Level::Debug => logforth_core::record::Level::Debug,
33 log::Level::Trace => logforth_core::record::Level::Trace,
34 }
35}
36
37struct LogCrateLogger(());
38
39impl log::Log for LogCrateLogger {
40 fn enabled(&self, metadata: &Metadata) -> bool {
41 forward_enabled(default_logger(), metadata)
42 }
43
44 fn log(&self, record: &Record) {
45 forward_log(default_logger(), record);
46 }
47
48 fn flush(&self) {
49 default_logger().flush();
50 }
51}
52
53pub struct LogProxy<'a>(&'a Logger);
55
56impl<'a> LogProxy<'a> {
57 pub fn new(logger: &'a Logger) -> Self {
59 Self(logger)
60 }
61}
62
63impl<'a> log::Log for LogProxy<'a> {
64 fn enabled(&self, metadata: &Metadata) -> bool {
65 forward_enabled(self.0, metadata)
66 }
67
68 fn log(&self, record: &Record) {
69 forward_log(self.0, record);
70 }
71
72 fn flush(&self) {
73 self.0.flush();
74 }
75}
76
77pub struct OwnedLogProxy(Logger);
79
80impl OwnedLogProxy {
81 pub fn new(logger: Logger) -> Self {
83 Self(logger)
84 }
85}
86
87impl log::Log for OwnedLogProxy {
88 fn enabled(&self, metadata: &Metadata) -> bool {
89 forward_enabled(&self.0, metadata)
90 }
91
92 fn log(&self, record: &Record) {
93 forward_log(&self.0, record);
94 }
95
96 fn flush(&self) {
97 self.0.flush();
98 }
99}
100
101fn forward_enabled(logger: &Logger, metadata: &Metadata) -> bool {
102 let criteria = FilterCriteria::builder()
103 .target(metadata.target())
104 .level(level_to_level(metadata.level()))
105 .build();
106
107 Logger::enabled(logger, &criteria)
108}
109
110fn forward_log(logger: &Logger, record: &Record) {
111 if !forward_enabled(logger, record.metadata()) {
112 return;
113 }
114
115 let mut builder = logforth_core::record::Record::builder()
117 .level(level_to_level(record.level()))
118 .target(record.target())
119 .line(record.line());
120
121 builder = if let Some(module_path) = record.module_path_static() {
123 builder.module_path_static(module_path)
124 } else {
125 builder.module_path(record.module_path())
126 };
127 builder = if let Some(file) = record.file_static() {
128 builder.file_static(file)
129 } else {
130 builder.file(record.file())
131 };
132
133 builder = if let Some(payload) = record.args().as_str() {
135 builder.payload(payload)
136 } else {
137 builder.payload(record.args().to_string())
138 };
139
140 let mut kvs = Vec::new();
142
143 struct KeyValueVisitor<'a, 'b> {
144 kvs: &'b mut Vec<(log::kv::Key<'a>, log::kv::Value<'a>)>,
145 }
146
147 impl<'a, 'b> log::kv::VisitSource<'a> for KeyValueVisitor<'a, 'b> {
148 fn visit_pair(
149 &mut self,
150 key: log::kv::Key<'a>,
151 value: log::kv::Value<'a>,
152 ) -> Result<(), log::kv::Error> {
153 self.kvs.push((key, value));
154 Ok(())
155 }
156 }
157
158 let mut visitor = KeyValueVisitor { kvs: &mut kvs };
159 record.key_values().visit(&mut visitor).unwrap();
160
161 let mut new_kvs = Vec::with_capacity(kvs.len());
162 for (k, v) in kvs.iter() {
163 new_kvs.push((Key::new_ref(k.as_str()), Value::from_sval2(v)));
164 }
165 builder = builder.key_values(new_kvs.as_slice());
166
167 Logger::log(logger, &builder.build());
168}
169
170pub fn try_setup() -> Result<(), log::SetLoggerError> {
193 static LOGGER: LogCrateLogger = LogCrateLogger(());
194 log::set_logger(&LOGGER)?;
195 log::set_max_level(log::LevelFilter::Trace);
196 Ok(())
197}
198
199pub fn setup() {
224 try_setup().expect(
225 "logforth_bridge_log::setup must be called before the log crate global logger initialized",
226 )
227}