-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
A way to change log level in runtime? #76
Comments
Hi! There isn't a built-in way, but it's fairly possible to build this on top of fern & something to synchronize the level get/set. Something like the following should work: lazy_static! {
static LOG_LEVEL: RwLock<log::LevelFilter> = RwLock::new(log::LevelFilter::Off);
}
fn set_log_level(level: log::LevelFilter) {
*LOG_LEVEL.write() = level;
}
fn setup_logging() -> Result<(), fern::InitError> {
fern::Dispatch::new()
.filter(|metadata| {
metadata.level() < *LOG_LEVEL.read()
})
.format(|out, message, record| {
out.finish(format_args!(
"{}[{}][{}] {}",
chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
record.target(),
record.level(),
message
))
})
.chain(fern::log_file("program.log")?)
.apply()?;
Ok(())
} I don't plan on adding this to fern natively for performance reasons, but if you get this working, it could be a great example to add. |
Ha! It works. I had to add unwrap() for RwLock since it's Result, but the key here is not to set .level() in initialization chain. Then it works like a charm! Thank you very much! |
Nice! Glad you got it working. I'll leave this open for the sake of documenting this somewhere, or making an example of it, if that's alright. |
I did it this way: use std::sync::RwLock;
lazy_static! {
static ref LOG_LEVEL: RwLock<LevelFilter> = RwLock::new(LevelFilter::Info);
}
/// Set log level dynamically at runtime
fn set_log_level() {
let level = Config::load().get_log_level();
match LOG_LEVEL.read() {
Ok(loglevel) => {
if level != *loglevel {
drop(loglevel);
match LOG_LEVEL.write() {
Ok(mut log) => {
println!("Changing log level to: {}", level);
*log = level
}
Err(err) => {
println!("Failed to change log level to: {}, cause: {}", level, err);
}
}
}
}
Err(_) => {}
}
}
fn setup_logger() -> Result<(), SetLoggerError> {
let log_file = Config::load()
.log_file
.unwrap_or_else(|| String::from("krecik.log"));
let colors_line = ColoredLevelConfig::new()
.error(Color::Red)
.warn(Color::Yellow)
.info(Color::White)
.debug(Color::Magenta)
.trace(Color::Cyan);
Dispatch::new()
.filter(|metadata| {
match LOG_LEVEL.read() {
Ok(log) => metadata.level() <= *log,
Err(_err) => true,
}
})
.format(move |out, message, record| {
out.finish(format_args!(
"{color_line}[{date}][{target}][{level}{color_line}] {message}\x1B[0m",
color_line = format_args!(
"\x1B[{}m",
colors_line.get_color(&record.level()).to_fg_str()
),
date = Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
target = record.target(),
level = record.level(),
message = message
))
})
// .level(level) -- it's very important to not do this, otherwise level never changes in runtime!!
.chain(std::io::stdout())
.chain(fern::DateBased::new(format!("{}.", log_file), "%Y-%m-%d"))
.apply()
} and then I just run set_log_level(); in my server main loop :) |
I wish to change the log level in runtime without restarting my long-running service. Is there a way of doing so?
The text was updated successfully, but these errors were encountered: