runtime/logger: use blocking wait.
Fixes #84 using the first solution. If the performance is considered too slow, we can do the second option later.
This commit is contained in:
parent
4b6c5d5679
commit
c85e85aa6d
@ -38,7 +38,8 @@ impl<'a> Drop for LogBufferRef<'a> {
|
||||
|
||||
pub struct BufferLogger {
|
||||
buffer: Mutex<LogBuffer<&'static mut [u8]>>,
|
||||
uart_filter: Cell<LevelFilter>
|
||||
uart_filter: Cell<LevelFilter>,
|
||||
buffer_filter: Cell<LevelFilter>,
|
||||
}
|
||||
|
||||
static mut LOGGER: Option<BufferLogger> = None;
|
||||
@ -48,6 +49,7 @@ impl BufferLogger {
|
||||
BufferLogger {
|
||||
buffer: Mutex::new(LogBuffer::new(buffer)),
|
||||
uart_filter: Cell::new(LevelFilter::Info),
|
||||
buffer_filter: Cell::new(LevelFilter::Trace),
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,6 +78,15 @@ impl BufferLogger {
|
||||
pub fn set_uart_log_level(&self, max_level: LevelFilter) {
|
||||
self.uart_filter.set(max_level)
|
||||
}
|
||||
|
||||
pub fn buffer_log_level(&self) -> LevelFilter {
|
||||
self.buffer_filter.get()
|
||||
}
|
||||
|
||||
/// this should be reserverd for mgmt module
|
||||
pub fn set_buffer_log_level(&self, max_level: LevelFilter) {
|
||||
self.buffer_filter.set(max_level)
|
||||
}
|
||||
}
|
||||
|
||||
// required for impl Log
|
||||
@ -94,7 +105,8 @@ impl Log for BufferLogger {
|
||||
let seconds = timestamp / 1_000_000;
|
||||
let micros = timestamp % 1_000_000;
|
||||
|
||||
if let Some(mut buffer) = self.buffer.try_lock() {
|
||||
if record.level() <= self.buffer_log_level() {
|
||||
let mut buffer = self.buffer.lock();
|
||||
writeln!(buffer, "[{:6}.{:06}s] {:>5}({}): {}", seconds, micros,
|
||||
record.level(), record.target(), record.args()).unwrap();
|
||||
}
|
||||
|
@ -98,9 +98,9 @@ async fn handle_connection(stream: &mut TcpStream, pull_id: Rc<RefCell<u32>>) ->
|
||||
let msg: Request = FromPrimitive::from_i8(msg?).ok_or(Error::UnrecognizedPacket)?;
|
||||
match msg {
|
||||
Request::GetLog => {
|
||||
let mut buffer = get_logger_buffer().await;
|
||||
let buffer = get_logger_buffer().await.extract().as_bytes().to_vec();
|
||||
write_i8(stream, Reply::LogContent as i8).await?;
|
||||
write_chunk(stream, buffer.extract().as_bytes()).await?;
|
||||
write_chunk(stream, &buffer).await?;
|
||||
}
|
||||
Request::ClearLog => {
|
||||
let mut buffer = get_logger_buffer().await;
|
||||
@ -115,24 +115,22 @@ async fn handle_connection(stream: &mut TcpStream, pull_id: Rc<RefCell<u32>>) ->
|
||||
};
|
||||
loop {
|
||||
let mut buffer = get_logger_buffer_pred(|b| !b.is_empty()).await;
|
||||
let bytes = buffer.extract().as_bytes();
|
||||
if id != *pull_id.borrow() {
|
||||
// another connection attempts to pull the log...
|
||||
// abort this connection...
|
||||
break;
|
||||
}
|
||||
write_chunk(stream, bytes).await?;
|
||||
if log::max_level() == LevelFilter::Trace {
|
||||
// Hold exclusive access over the logger until we get positive
|
||||
// acknowledgement; otherwise we get an infinite loop of network
|
||||
// trace messages being transmitted and causing more network
|
||||
// trace messages to be emitted.
|
||||
//
|
||||
// Any messages unrelated to this management socket that arrive
|
||||
// while it is flushed are lost, but such is life.
|
||||
stream.flush().await?;
|
||||
}
|
||||
let bytes = buffer.extract().as_bytes().to_vec();
|
||||
buffer.clear();
|
||||
core::mem::drop(buffer);
|
||||
write_chunk(stream, &bytes).await?;
|
||||
if log::max_level() == LevelFilter::Trace {
|
||||
// temporarily discard all trace level log
|
||||
let logger = unsafe { BufferLogger::get_logger().as_mut().unwrap() };
|
||||
logger.set_buffer_log_level(LevelFilter::Debug);
|
||||
stream.flush().await?;
|
||||
logger.set_buffer_log_level(LevelFilter::Trace);
|
||||
}
|
||||
}
|
||||
},
|
||||
Request::SetLogFilter => {
|
||||
|
Loading…
Reference in New Issue
Block a user