2017-01-25 05:55:51 +08:00
|
|
|
#![no_std]
|
|
|
|
|
|
|
|
extern crate log;
|
|
|
|
extern crate log_buffer;
|
|
|
|
extern crate board;
|
|
|
|
|
2016-10-02 12:37:24 +08:00
|
|
|
use core::{mem, ptr};
|
2016-11-23 21:49:19 +08:00
|
|
|
use core::cell::{Cell, RefCell};
|
2017-01-25 05:55:51 +08:00
|
|
|
use core::fmt::Write;
|
2017-04-15 16:27:18 +08:00
|
|
|
use log::{Log, LogMetadata, LogRecord, LogLevelFilter, MaxLogLevelFilter};
|
2016-09-29 02:25:25 +08:00
|
|
|
use log_buffer::LogBuffer;
|
2017-01-25 05:55:51 +08:00
|
|
|
use board::{Console, clock};
|
2016-09-29 02:25:25 +08:00
|
|
|
|
|
|
|
pub struct BufferLogger {
|
2017-04-15 16:27:18 +08:00
|
|
|
buffer: RefCell<LogBuffer<&'static mut [u8]>>,
|
|
|
|
filter: RefCell<Option<MaxLogLevelFilter>>,
|
|
|
|
uart_filter: Cell<LogLevelFilter>
|
2016-09-29 02:25:25 +08:00
|
|
|
}
|
|
|
|
|
2017-01-25 05:55:51 +08:00
|
|
|
static mut LOGGER: *const BufferLogger = 0 as *const _;
|
2016-10-02 12:37:24 +08:00
|
|
|
|
2016-09-29 02:25:25 +08:00
|
|
|
impl BufferLogger {
|
|
|
|
pub fn new(buffer: &'static mut [u8]) -> BufferLogger {
|
|
|
|
BufferLogger {
|
2016-11-23 21:49:19 +08:00
|
|
|
buffer: RefCell::new(LogBuffer::new(buffer)),
|
2017-03-03 14:06:26 +08:00
|
|
|
filter: RefCell::new(None),
|
2017-04-15 16:27:18 +08:00
|
|
|
uart_filter: Cell::new(LogLevelFilter::Info),
|
2016-09-29 02:25:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-02 12:37:24 +08:00
|
|
|
pub fn register<F: FnOnce()>(&self, f: F) {
|
2016-09-29 02:25:25 +08:00
|
|
|
// log::set_logger_raw captures a pointer to ourselves, so we must prevent
|
|
|
|
// ourselves from being moved or dropped after that function is called (and
|
|
|
|
// before log::shutdown_logger_raw is called).
|
|
|
|
unsafe {
|
|
|
|
log::set_logger_raw(|max_log_level| {
|
2017-03-03 14:06:26 +08:00
|
|
|
max_log_level.set(LogLevelFilter::Info);
|
|
|
|
*self.filter.borrow_mut() = Some(max_log_level);
|
2016-09-29 02:25:25 +08:00
|
|
|
self as *const Log
|
|
|
|
}).expect("global logger can only be initialized once");
|
2016-10-02 12:37:24 +08:00
|
|
|
LOGGER = self;
|
2016-09-29 02:25:25 +08:00
|
|
|
}
|
2016-10-02 12:37:24 +08:00
|
|
|
f();
|
2016-09-29 02:25:25 +08:00
|
|
|
log::shutdown_logger_raw().unwrap();
|
2016-10-02 12:37:24 +08:00
|
|
|
unsafe {
|
|
|
|
LOGGER = ptr::null();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-18 12:10:33 +08:00
|
|
|
pub fn with<R, F: FnOnce(&BufferLogger) -> R>(f: F) -> R {
|
2016-10-02 12:37:24 +08:00
|
|
|
f(unsafe { mem::transmute::<*const BufferLogger, &BufferLogger>(LOGGER) })
|
2016-09-29 02:25:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn clear(&self) {
|
2017-01-25 05:55:51 +08:00
|
|
|
self.buffer.borrow_mut().clear()
|
2016-09-29 02:25:25 +08:00
|
|
|
}
|
|
|
|
|
2017-07-18 12:10:33 +08:00
|
|
|
pub fn is_empty(&self) -> bool {
|
|
|
|
self.buffer.borrow_mut().extract().len() == 0
|
|
|
|
}
|
|
|
|
|
2016-09-29 02:25:25 +08:00
|
|
|
pub fn extract<R, F: FnOnce(&str) -> R>(&self, f: F) -> R {
|
2017-07-18 12:10:33 +08:00
|
|
|
let old_log_level = self.max_log_level();
|
|
|
|
self.set_max_log_level(LogLevelFilter::Off);
|
|
|
|
let result = f(self.buffer.borrow_mut().extract());
|
|
|
|
self.set_max_log_level(old_log_level);
|
|
|
|
result
|
2016-09-29 02:25:25 +08:00
|
|
|
}
|
2016-11-23 21:49:19 +08:00
|
|
|
|
2017-07-05 02:18:31 +08:00
|
|
|
pub fn max_log_level(&self) -> LogLevelFilter {
|
|
|
|
self.filter
|
|
|
|
.borrow()
|
|
|
|
.as_ref()
|
|
|
|
.expect("register the logger before touching maximum log level")
|
|
|
|
.get()
|
|
|
|
}
|
|
|
|
|
2017-03-03 14:06:26 +08:00
|
|
|
pub fn set_max_log_level(&self, max_level: LogLevelFilter) {
|
|
|
|
self.filter
|
|
|
|
.borrow()
|
|
|
|
.as_ref()
|
2017-07-05 02:18:31 +08:00
|
|
|
.expect("register the logger before touching maximum log level")
|
2017-03-03 14:06:26 +08:00
|
|
|
.set(max_level)
|
|
|
|
}
|
|
|
|
|
2017-07-05 02:18:31 +08:00
|
|
|
pub fn uart_log_level(&self) -> LogLevelFilter {
|
|
|
|
self.uart_filter.get()
|
|
|
|
}
|
|
|
|
|
2017-04-15 16:27:18 +08:00
|
|
|
pub fn set_uart_log_level(&self, max_level: LogLevelFilter) {
|
|
|
|
self.uart_filter.set(max_level)
|
2016-11-23 21:49:19 +08:00
|
|
|
}
|
2016-09-29 02:25:25 +08:00
|
|
|
}
|
|
|
|
|
2017-01-25 05:55:51 +08:00
|
|
|
// required for impl Log
|
|
|
|
unsafe impl Sync for BufferLogger {}
|
|
|
|
|
2016-09-29 02:25:25 +08:00
|
|
|
impl Log for BufferLogger {
|
2016-09-30 02:54:08 +08:00
|
|
|
fn enabled(&self, _metadata: &LogMetadata) -> bool {
|
2016-09-29 02:25:25 +08:00
|
|
|
true
|
|
|
|
}
|
|
|
|
|
|
|
|
fn log(&self, record: &LogRecord) {
|
|
|
|
if self.enabled(record.metadata()) {
|
2017-07-18 10:53:55 +08:00
|
|
|
let timestamp = clock::get_us();
|
|
|
|
let seconds = timestamp / 1_000_000;
|
|
|
|
let micros = timestamp % 1_000_000;
|
|
|
|
|
2017-07-18 12:10:33 +08:00
|
|
|
writeln!(self.buffer.borrow_mut(),
|
|
|
|
"[{:6}.{:06}s] {:>5}({}): {}", seconds, micros,
|
|
|
|
record.level(), record.target(), record.args()).unwrap();
|
|
|
|
|
|
|
|
if record.level() <= self.uart_filter.get() {
|
|
|
|
writeln!(Console,
|
|
|
|
"[{:6}.{:06}s] {:>5}({}): {}", seconds, micros,
|
|
|
|
record.level(), record.target(), record.args()).unwrap();
|
2016-11-13 04:16:25 +08:00
|
|
|
}
|
2016-09-29 02:25:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|