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