-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathlogging.rs
124 lines (111 loc) · 2.72 KB
/
logging.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use log::{Metadata, Record};
use std::fmt::Write;
extern "C" {
fn px4_log_modulename(level: i32, module: *const u8, fmt: *const u8, ...);
fn px4_log_raw(level: i32, fmt: *const u8, ...);
}
#[doc(hidden)]
pub enum LogLevel {
Debug = 0,
Info = 1,
Warn = 2,
Error = 3,
Panic = 4,
}
#[doc(hidden)]
pub fn log_raw(level: LogLevel, message: &str) {
unsafe {
px4_log_raw(
level as i32,
"%.*s\0".as_ptr(),
message.len() as i32,
message.as_ptr(),
);
}
}
/// Print output without any decoration.
///
/// The equivalent of `PX4_INFO_RAW` in C and C++.
///
/// ## Example
///
/// ```
/// # #[macro_use] extern crate px4;
/// # #[no_mangle] fn px4_log_raw() {}
/// # fn main() {
/// info_raw!("Hello World!\n");
/// info_raw!("Hello {}!\n", "World");
/// # }
/// ```
#[macro_export]
macro_rules! info_raw {
($arg:expr) => (
$crate::log_raw($crate::LogLevel::Info, $arg)
);
($($arg:tt)+) => (
$crate::log_raw($crate::LogLevel::Info, &format!($($arg)+))
);
}
struct Px4Logger;
impl log::Log for Px4Logger {
fn enabled(&self, metadata: &Metadata) -> bool {
metadata.level() <= log::Level::Info
}
fn log(&self, record: &Record) {
if !self.enabled(record.metadata()) {
return;
}
let level = match record.level() {
log::Level::Error => LogLevel::Error,
log::Level::Warn => LogLevel::Warn,
log::Level::Info => LogLevel::Info,
log::Level::Debug => LogLevel::Debug,
log::Level::Trace => LogLevel::Debug,
};
// We allocate both nul-terminated strings as one single String, to
// save on heap allocations.
let target = record.target();
let s = format!("{}\0{}\0", target, record.args());
let (module, message) = s.as_bytes().split_at(target.len() + 1);
unsafe {
px4_log_modulename(
level as i32,
module.as_ptr(),
"%s\0".as_ptr(),
message.as_ptr(),
);
}
}
fn flush(&self) {}
}
static LOGGER: Px4Logger = Px4Logger;
pub unsafe fn init(modulename: &'static [u8]) {
if log::set_logger(&LOGGER).is_ok() {
log::set_max_level(log::LevelFilter::Info);
std::panic::set_hook(Box::new(move |info: &std::panic::PanicInfo| {
let payload: &str = if let Some(s) = info.payload().downcast_ref::<&'static str>() {
s
} else if let Some(s) = info.payload().downcast_ref::<String>() {
&s
} else {
"[unknown]"
};
let mut message = String::new();
let thread = std::thread::current();
if let Some(name) = thread.name() {
write!(message, "thread '{}' ", name).unwrap();
}
write!(message, "panicked at '{}'", payload).unwrap();
if let Some(loc) = info.location() {
write!(message, ", {}", loc).unwrap();
}
message.push('\0');
px4_log_modulename(
LogLevel::Panic as i32,
modulename.as_ptr(),
"%s\0".as_ptr(),
message.as_ptr(),
);
}));
}
}