You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Bug Description:
When using the Rust API to develop a plugin, I attempted to enable logging in headless mode using:
binaryninja::logger::Logger::new("Test").init();
However, no log output is produced, even when explicitly setting the log level. This makes it difficult to debug plugins in headless mode.
Most existing Rust plugin examples use print* macros instead of the log crate, which suggests that logger.init() may not be supported in this context — or perhaps I’m missing a required step.
Steps To Reproduce:
Create a headless plugin using the Binary Ninja Rust API.
Call binaryninja::logger::Logger::new("Test").init() and attempt to log a message using log::info!, warn!, etc.
Run the plugin in headless mode using cargo run.
Observe that no output is produced in the console.
Expected Behavior:
I expected that logger.init() would configure logging correctly and output log messages to the console when running in headless mode.
Screenshots/Video Recording:
N/A
Binary:
Not applicable — this issue concerns plugin development using the Rust API.
Additional Information:
Possibly related to issue #5101 and issue #1990.
Is this the intended behavior? Should I be using a third-party logging solution instead of the built-in Binary Ninja logger when working in headless mode?
The logger constructs a log crate compatible sink so that when you have log::info!("test") the logs are output to the binary ninja logger. What you want is to register a LogListener, using register_listener.
So to answer
Should I be using a third-party logging solution instead of the built-in Binary Ninja logger when working in headless mode?
Yea, you will want to probably do something like:
use binaryninja::headless::Session;use binaryninja::logger::{register_listener,Level,LogListener,Logger};structMyLogListener;implLogListenerforMyLogListener{fnlog(&self,session:usize,level:Level,msg:&str,logger_name:&str,tid:usize){println!("[{:?}] {}: {}", level, logger_name, msg);}fnlevel(&self) -> Level{Level::DebugLog}}#[test]fntest_log_listener(){// Registering the listener before i initialize the session to get the initialization logs as well.let guard = register_listener(MyLogListener);let _session = Session::new().expect("Failed to initialize session");// Also show that our logs through `log` crate are now being printed.Logger::new("Test").init();
log::info!("test");// Remember the guard will close the listener once it goes out of scope! (or we manually drop it like here)drop(guard);}
I am going to add this as an example, clearly the documentation (or lack thereof) is lacking!
Thanks for the quick reply and the solution — I tried it out, and everything works as expected now.
BTW, I ended up using tracing with a custom implementation of the LogListener trait.
Activity
emesare commentedon May 22, 2025
The logger constructs a
logcrate compatible sink so that when you havelog::info!("test")the logs are output to the binary ninja logger. What you want is to register aLogListener, usingregister_listener.So to answer
Yea, you will want to probably do something like:
I am going to add this as an example, clearly the documentation (or lack thereof) is lacking!
[-][Rust API] Logger not working in headless mode[/-][+][Rust API] Improve logger documentation[/+]saruman9 commentedon May 22, 2025
Thanks for the quick reply and the solution — I tried it out, and everything works as expected now.
BTW, I ended up using
tracingwith a custom implementation of theLogListenertrait.