I want to implement a logger for the log create, that allows me to stream / asynchronously publish the messages to JavaScript, so they can be displayed to the user.
Currently, I have a very simple setup, that requires JavaScript to "ask" for the logs, which isn't optimal, since I'm not really in a context, where I only want to display the logs, after something is done, but while it's happening.
static LOGGER: Logger = Logger::new();
#[wasm_bindgen]
pub struct Logger {
logs: Mutex<Vec<String>>,
level: Mutex<LogLevel>,
}
impl Logger {
pub fn init_once() {
static INIT: Once = Once::new();
INIT.call_once(|| {
log::set_logger(&LOGGER).unwrap();
log::set_max_level(log::LevelFilter::max());
})
}
}
#[wasm_bindgen]
impl Logger {
pub fn get_logs() -> Vec<String> {
let logs = LOGGER
.logs
.lock()
.expect("failed to acquire a lock to logger while getting logs");
logs.clone()
}
}
I've tried adding a add_log_listener
and remove_log_listener
method, but found that this doesn't work, since js_sys::Function
is at some point a *mut u*
(I'm guessing that some sort of pointer? And for some reason it's *mut
?), which doesn't implement Send
, which is required by the log::Log
trait.
I don't have any particular visions on how the API should work, as long as the logs can be displayd in a asynchrounous manner :)
PS: The displaying is currently being done by the Monaco Editor, so just passing in an HTML-Element and appending to it, isn't that easy. And I'm also not sure if that would be more thread safe. Haven't looked too deep into it. And I really would like the display logic to not necessarily be mixed with my logging logic... if possible.
I have also thought about polling the logger with a setInterval
from JavaScript, but that sounds quite hacky. It shouldn't be a problem right now, I think, but as soon as more than one thingy calls get_logs()
(and consequently clear_logs()
), that wouldn't work anymore.
There are two options:
However, the best strategy actually is to do neither, and instead do what you dismissed as hacky - setInterval()
. That is because logs can be emitted very fast, and calling JS from WASM and even more writing to the DOM is very slow, so if you will do that for every log record this will hurt your speed. You only want that at a constant rate, since the human eye cannot tell the difference anyway.