Add support for log rotation, sending SIGUSR1 will cause the log file to be re-opened (#9713)

This commit is contained in:
Michael Vines 2020-04-24 14:26:53 -07:00 committed by GitHub
parent 76b1c2baf0
commit 50f1ec0374
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 75 additions and 36 deletions

View File

@ -31,7 +31,8 @@ solana-vote-program = { path = "../programs/vote", version = "1.2.0" }
solana-vote-signer = { path = "../vote-signer", version = "1.2.0" }
[target."cfg(unix)".dependencies]
gag = "0.1.10"
libc = "0.2.66"
signal-hook = "0.1.13"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

View File

@ -45,7 +45,7 @@ use std::{
atomic::{AtomicBool, Ordering},
Arc,
},
thread::sleep,
thread::{sleep, JoinHandle},
time::{Duration, Instant},
};
@ -400,6 +400,64 @@ fn is_snapshot_config_invalid(
|| snapshot_interval_slots % accounts_hash_interval_slots != 0)
}
#[cfg(unix)]
fn redirect_stderr(filename: &str) {
use std::{fs::OpenOptions, os::unix::io::AsRawFd};
match OpenOptions::new()
.write(true)
.create(true)
.append(true)
.open(filename)
{
Ok(file) => unsafe {
libc::dup2(file.as_raw_fd(), libc::STDERR_FILENO);
},
Err(err) => eprintln!("Unable to open {}: {}", filename, err),
}
}
fn start_logger(logfile: Option<String>) -> Option<JoinHandle<()>> {
let logger_thread = match logfile {
None => None,
Some(logfile) => {
#[cfg(unix)]
{
let signals = signal_hook::iterator::Signals::new(&[signal_hook::SIGUSR1])
.unwrap_or_else(|err| {
eprintln!("Unable to register SIGUSR1 handler: {:?}", err);
exit(1);
});
redirect_stderr(&logfile);
Some(std::thread::spawn(move || {
for signal in signals.forever() {
info!(
"received SIGUSR1 ({}), reopening log file: {:?}",
signal, logfile
);
redirect_stderr(&logfile);
}
}))
}
#[cfg(not(unix))]
{
println!("logging to a file is not supported on this platform");
()
}
}
};
solana_logger::setup_with_default(
&[
"solana=info", /* info logging for all solana modules */
"rpc=trace", /* json_rpc request/response logging */
]
.join(","),
);
logger_thread
}
#[allow(clippy::cognitive_complexity)]
pub fn main() {
let default_dynamic_port_range =
@ -661,7 +719,9 @@ pub fn main() {
.long("log")
.value_name("FILE")
.takes_value(true)
.help("Redirect logging to the specified file, '-' for standard error"),
.help("Redirect logging to the specified file, '-' for standard error. \
Sending the SIGUSR1 signal to the validator process will cause it \
to re-open the log file"),
)
.arg(
Arg::with_name("wait_for_supermajority")
@ -927,42 +987,20 @@ pub fn main() {
warn!("--vote-signer-address ignored");
}
let _log_redirect = {
#[cfg(unix)]
{
let default_logfile = format!(
"solana-validator-{}-{}.log",
identity_keypair.pubkey(),
chrono::Utc::now().format("%Y%m%d-%H%M%S")
);
let logfile = matches.value_of("logfile").unwrap_or(&default_logfile);
let logfile = {
let logfile = matches
.value_of("logfile")
.map(|s| s.into())
.unwrap_or_else(|| format!("solana-validator-{}.log", identity_keypair.pubkey()));
if logfile == "-" {
None
} else {
println!("log file: {}", logfile);
Some(gag::Redirect::stderr(File::create(logfile).unwrap_or_else(
|err| {
eprintln!("Unable to create {}: {:?}", logfile, err);
exit(1);
},
)))
}
}
#[cfg(not(unix))]
{
println!("logging to a file is not supported on this platform");
()
if logfile == "-" {
None
} else {
println!("log file: {}", logfile);
Some(logfile)
}
};
solana_logger::setup_with_default(
&[
"solana=info", /* info logging for all solana modules */
"rpc=trace", /* json_rpc request/response logging */
]
.join(","),
);
let _logger_thread = start_logger(logfile);
// Default to RUST_BACKTRACE=1 for more informative validator logs
if env::var_os("RUST_BACKTRACE").is_none() {