runtime: allow setting UART log level explicitly.

This is way more convenient than commenting out parts
of session.rs when debugging.
This commit is contained in:
whitequark 2017-04-15 08:27:18 +00:00
parent 0531dc45c3
commit c6e8d5c901
7 changed files with 73 additions and 40 deletions

View File

@ -11,6 +11,7 @@ class Request(Enum):
GetLog = 1 GetLog = 1
ClearLog = 2 ClearLog = 2
SetLogFilter = 3 SetLogFilter = 3
SetUartLogFilter = 6
Hotswap = 4 Hotswap = 4
Reboot = 5 Reboot = 5
@ -128,6 +129,14 @@ class CommMgmt:
self._write_int8(getattr(LogLevel, level).value) self._write_int8(getattr(LogLevel, level).value)
self._read_expect(Reply.Success) self._read_expect(Reply.Success)
def set_uart_log_level(self, level):
if level not in LogLevel.__members__:
raise ValueError("invalid log level {}".format(level))
self._write_header(Request.SetUartLogFilter)
self._write_int8(getattr(LogLevel, level).value)
self._read_expect(Reply.Success)
def hotswap(self, firmware): def hotswap(self, firmware):
self._write_header(Request.Hotswap) self._write_header(Request.Hotswap)
self._write_bytes(firmware) self._write_bytes(firmware)

View File

@ -1,6 +1,5 @@
#![no_std] #![no_std]
#[macro_use]
extern crate log; extern crate log;
extern crate log_buffer; extern crate log_buffer;
extern crate board; extern crate board;
@ -8,14 +7,14 @@ extern crate board;
use core::{mem, ptr}; use core::{mem, ptr};
use core::cell::{Cell, RefCell}; use core::cell::{Cell, RefCell};
use core::fmt::Write; use core::fmt::Write;
use log::{Log, LogLevel, LogMetadata, LogRecord, LogLevelFilter, MaxLogLevelFilter}; use log::{Log, LogMetadata, LogRecord, LogLevelFilter, MaxLogLevelFilter};
use log_buffer::LogBuffer; use log_buffer::LogBuffer;
use board::{Console, clock}; use board::{Console, clock};
pub struct BufferLogger { pub struct BufferLogger {
buffer: RefCell<LogBuffer<&'static mut [u8]>>, buffer: RefCell<LogBuffer<&'static mut [u8]>>,
filter: RefCell<Option<MaxLogLevelFilter>>, filter: RefCell<Option<MaxLogLevelFilter>>,
concise_uart: Cell<bool> uart_filter: Cell<LogLevelFilter>
} }
static mut LOGGER: *const BufferLogger = 0 as *const _; static mut LOGGER: *const BufferLogger = 0 as *const _;
@ -25,7 +24,7 @@ impl BufferLogger {
BufferLogger { BufferLogger {
buffer: RefCell::new(LogBuffer::new(buffer)), buffer: RefCell::new(LogBuffer::new(buffer)),
filter: RefCell::new(None), filter: RefCell::new(None),
concise_uart: Cell::new(true) uart_filter: Cell::new(LogLevelFilter::Info),
} }
} }
@ -68,12 +67,8 @@ impl BufferLogger {
.set(max_level) .set(max_level)
} }
pub fn enable_concise_uart(&self) { pub fn set_uart_log_level(&self, max_level: LogLevelFilter) {
if self.concise_uart.get() { self.uart_filter.set(max_level)
trace!("disabling tracing to UART; all further trace messages \
are sent to core log only");
self.concise_uart.set(false)
}
} }
} }
@ -101,9 +96,7 @@ impl Log for BufferLogger {
} }
}; };
// Printing to UART is really slow, so avoid doing that when we have an alternative if record.level() <= self.uart_filter.get() || force_uart {
// route to retrieve the debug messages.
if self.concise_uart.get() || record.level() <= LogLevel::Info || force_uart {
writeln!(Console, "[{:12}us] {:>5}({}): {}", writeln!(Console, "[{:12}us] {:>5}({}): {}",
clock::get_us(), record.level(), clock::get_us(), record.level(),
record.target(), record.args()).unwrap(); record.target(), record.args()).unwrap();

View File

@ -10,6 +10,8 @@ pub enum Request {
ClearLog, ClearLog,
#[cfg(feature = "log")] #[cfg(feature = "log")]
SetLogFilter(LogLevelFilter), SetLogFilter(LogLevelFilter),
#[cfg(feature = "log")]
SetUartLogFilter(LogLevelFilter),
Hotswap(Vec<u8>), Hotswap(Vec<u8>),
Reboot, Reboot,
@ -25,12 +27,9 @@ pub enum Reply<'a> {
impl Request { impl Request {
pub fn read_from(reader: &mut Read) -> io::Result<Request> { pub fn read_from(reader: &mut Read) -> io::Result<Request> {
Ok(match reader.read_u8()? {
1 => Request::GetLog,
2 => Request::ClearLog,
#[cfg(feature = "log")] #[cfg(feature = "log")]
3 => { fn read_log_level_filter(reader: &mut Read) -> io::Result<LogLevelFilter> {
let level = match reader.read_u8()? { Ok(match reader.read_u8()? {
0 => LogLevelFilter::Off, 0 => LogLevelFilter::Off,
1 => LogLevelFilter::Error, 1 => LogLevelFilter::Error,
2 => LogLevelFilter::Warn, 2 => LogLevelFilter::Warn,
@ -39,9 +38,16 @@ impl Request {
5 => LogLevelFilter::Trace, 5 => LogLevelFilter::Trace,
_ => return Err(io::Error::new(io::ErrorKind::InvalidData, _ => return Err(io::Error::new(io::ErrorKind::InvalidData,
"invalid log level")) "invalid log level"))
}; })
Request::SetLogFilter(level)
} }
Ok(match reader.read_u8()? {
1 => Request::GetLog,
2 => Request::ClearLog,
#[cfg(feature = "log")]
3 => Request::SetLogFilter(read_log_level_filter(reader)?),
#[cfg(feature = "log")]
6 => Request::SetUartLogFilter(read_log_level_filter(reader)?),
4 => Request::Hotswap(reader.read_bytes()?), 4 => Request::Hotswap(reader.read_bytes()?),
5 => Request::Reboot, 5 => Request::Reboot,
_ => return Err(io::Error::new(io::ErrorKind::InvalidData, "unknown request type")) _ => return Err(io::Error::new(io::ErrorKind::InvalidData, "unknown request type"))

View File

@ -69,15 +69,6 @@ fn startup() {
} }
info!("continuing boot"); info!("continuing boot");
match config::read_str("log_level", |r| r?.parse()) {
Err(()) => (),
Ok(log_level_filter) => {
info!("log level set to {} in configuration", log_level_filter);
logger_artiq::BufferLogger::with_instance(|logger|
logger.set_max_log_level(log_level_filter));
}
}
#[cfg(has_i2c)] #[cfg(has_i2c)]
board::i2c::init(); board::i2c::init();
#[cfg(has_ad9516)] #[cfg(has_ad9516)]
@ -132,6 +123,28 @@ fn startup() {
#[cfg(has_rtio_analyzer)] #[cfg(has_rtio_analyzer)]
io.spawn(4096, analyzer::thread); io.spawn(4096, analyzer::thread);
match config::read_str("log_level", |r| r?.parse()) {
Err(()) => (),
Ok(log_level_filter) => {
info!("log level set to {} by `log_level` config key",
log_level_filter);
logger_artiq::BufferLogger::with_instance(|logger|
logger.set_max_log_level(log_level_filter));
}
}
match config::read_str("uart_log_level", |r| r?.parse()) {
Err(()) => {
info!("UART log level set to INFO by default");
},
Ok(uart_log_level_filter) => {
info!("UART log level set to {} by `uart_log_level` config key",
uart_log_level_filter);
logger_artiq::BufferLogger::with_instance(|logger|
logger.set_uart_log_level(uart_log_level_filter));
}
}
loop { loop {
scheduler.run(); scheduler.run();

View File

@ -44,6 +44,13 @@ fn worker(mut stream: &mut TcpStream) -> io::Result<()> {
Reply::Success.write_to(stream)?; Reply::Success.write_to(stream)?;
}, },
Request::SetUartLogFilter(level) => {
info!("changing UART log level to {}", level);
BufferLogger::with_instance(|logger|
logger.set_uart_log_level(level));
Reply::Success.write_to(stream)?;
},
Request::Hotswap(firmware) => { Request::Hotswap(firmware) => {
Reply::RebootImminent.write_to(stream)?; Reply::RebootImminent.write_to(stream)?;
stream.close()?; stream.close()?;

View File

@ -4,7 +4,6 @@ use std::cell::{Cell, RefCell};
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
use std::error::Error; use std::error::Error;
use {config, rtio_mgt, mailbox, rpc_queue, kernel}; use {config, rtio_mgt, mailbox, rpc_queue, kernel};
use logger_artiq::BufferLogger;
use cache::Cache; use cache::Cache;
use rtio_dma::Manager as DmaManager; use rtio_dma::Manager as DmaManager;
use urc::Urc; use urc::Urc;
@ -668,8 +667,6 @@ pub fn thread(io: Io) {
listener.listen(1381).expect("session: cannot listen"); listener.listen(1381).expect("session: cannot listen");
info!("accepting network sessions"); info!("accepting network sessions");
BufferLogger::with_instance(|logger| logger.enable_concise_uart());
let congress = Urc::new(RefCell::new(Congress::new())); let congress = Urc::new(RefCell::new(Congress::new()));
let mut kernel_thread = None; let mut kernel_thread = None;

View File

@ -25,6 +25,12 @@ def get_argparser():
p_set_level.add_argument("level", metavar="LEVEL", type=str, p_set_level.add_argument("level", metavar="LEVEL", type=str,
help="log level (one of: OFF ERROR WARN INFO DEBUG TRACE)") help="log level (one of: OFF ERROR WARN INFO DEBUG TRACE)")
p_set_uart_level = subparsers.add_parser("set_uart_level",
help="set minimum level for messages to be logged "
"to UART")
p_set_uart_level.add_argument("level", metavar="LEVEL", type=str,
help="log level (one of: OFF ERROR WARN INFO DEBUG TRACE)")
return parser return parser
@ -37,6 +43,8 @@ def main():
mgmt = CommMgmt(device_mgr, core_addr) mgmt = CommMgmt(device_mgr, core_addr)
if args.action == "set_level": if args.action == "set_level":
mgmt.set_log_level(args.level) mgmt.set_log_level(args.level)
elif args.action == "set_uart_level":
mgmt.set_uart_log_level(args.level)
elif args.action == "clear": elif args.action == "clear":
mgmt.clear_log() mgmt.clear_log()
else: else: