From c85e85aa6d66918e19fe6233ef69ed8ace8e1d06 Mon Sep 17 00:00:00 2001 From: pca006132 Date: Wed, 5 Aug 2020 16:20:20 +0800 Subject: [PATCH] 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. --- src/runtime/src/logger.rs | 16 ++++++++++++++-- src/runtime/src/mgmt.rs | 26 ++++++++++++-------------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/runtime/src/logger.rs b/src/runtime/src/logger.rs index 0a7b97e..7f93ddc 100644 --- a/src/runtime/src/logger.rs +++ b/src/runtime/src/logger.rs @@ -38,7 +38,8 @@ impl<'a> Drop for LogBufferRef<'a> { pub struct BufferLogger { buffer: Mutex>, - uart_filter: Cell + uart_filter: Cell, + buffer_filter: Cell, } static mut LOGGER: Option = 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(); } diff --git a/src/runtime/src/mgmt.rs b/src/runtime/src/mgmt.rs index dbd95c4..8af35b0 100644 --- a/src/runtime/src/mgmt.rs +++ b/src/runtime/src/mgmt.rs @@ -98,9 +98,9 @@ async fn handle_connection(stream: &mut TcpStream, pull_id: Rc>) -> 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>) -> }; 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 => {