Reputation: 29971
I'm developing a project in Rust that is meant to be used by systems administrators, via CLI. In this program, I would like to have lines like these:
warn!("File {} not found, proceeding to next file", file_path);
Which I don't consider errors in the context of the software, but I still would want my users to be aware of.
However, Rust's logging system, by default, only prints messages on the ERROR
log level, and the only way I found to change this default is to set the RUST_LOG
environment variable - which I don't want my users to have to do. I guess I could create a wrapper script that just sets the variable and exec
s the program, but I would rather not.
Is there a way to change the default level programmatically, from inside the program?
Upvotes: 12
Views: 9412
Reputation: 96733
This is the cleanest way I could find:
let env = Env::new().filter_or("FOO_LOG", "info");
Builder::from_env(env).init();
Upvotes: 4
Reputation: 704
If you use env_logger you can do in main something like this:
env_logger::builder()
.filter_level(log::LevelFilter::Debug)
.format_target(false)
.format_timestamp(None)
.init();
Upvotes: 13
Reputation: 4727
Here's a trick which will make it
if env::var("RUST_LOG").is_err() {
env::set_var("RUST_LOG", "info")
}
env_logger::init();
Upvotes: 18
Reputation: 86248
Here is an example of what I think you are looking for:
#[macro_use]
extern crate log;
use log::{LogRecord, LogLevel, LogMetadata, LogLevelFilter, SetLoggerError};
struct SimpleLogger;
impl log::Log for SimpleLogger {
fn enabled(&self, metadata: &LogMetadata) -> bool {
metadata.level() <= LogLevel::Warn
}
fn log(&self, record: &LogRecord) {
if self.enabled(record.metadata()) {
// I can probably change colors here
println!("{} - {}", record.level(), record.args());
}
}
}
pub fn init() -> Result<(), SetLoggerError> {
log::set_logger(|max_log_level| {
max_log_level.set(LogLevelFilter::Warn);
Box::new(SimpleLogger)
})
}
fn main() {
init(); // probably should do something better here
info!("I am info");
warn!("I am warn");
error!("I am error");
}
Upvotes: 3
Reputation: 29971
Thanks to Vladimir's answer, I dug on the liblog
source, and ended up finding a hacky (and probably racy) way to do it:
fn main() {
use std::os;
os::setenv("RUST_LOG", "warn");
}
If this is done before any logging, then the logging system will be set up as if it was set from the outside.
Upvotes: 1
Reputation: 127941
No, this is not possible. Just skimming through the code of liblog
library you can see that all log level configuration is stored in global variables which are modified only once, using Once
primitive, and there is no way to modify this configuration.
Rust logging is very simple; if you want something more sophisticated, you will have to do it yourself. liblog
provides an extension point, a trait called Logger
, it probably can be used for your purpose.
Upvotes: 5