From 4a04f34ac97a29178723f074611df33ce70f7030 Mon Sep 17 00:00:00 2001 From: Lijun Wang <83639177+lijunwangs@users.noreply.github.com> Date: Wed, 26 Feb 2025 16:06:14 -0800 Subject: [PATCH] missing library files --- .gitignore | 1 + log-utils/Cargo.toml | 25 +++++++++++++++++ log-utils/src/lib.rs | 64 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 log-utils/Cargo.toml create mode 100644 log-utils/src/lib.rs diff --git a/.gitignore b/.gitignore index 3127645a259560..03bd1844eb2a01 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ log-*.txt log-*/ !log-collector/ !log-analyzer/* +!log-utils/ # intellij files .idea/ diff --git a/log-utils/Cargo.toml b/log-utils/Cargo.toml new file mode 100644 index 00000000000000..4fd696aaa3d1b3 --- /dev/null +++ b/log-utils/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "solana-log-utils" +description = "Solana Logging Utilitites" +documentation = "https://docs.rs/solana-log-utils" +publish = false +version = { workspace = true } +authors = { workspace = true } +repository = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +edition = { workspace = true } + +[dependencies] +clap = { workspace = true } +libc = { workspace = true } +log = { workspace = true } +signal-hook = { workspace = true } +solana-logger = { workspace = true } + +[lib] +crate-type = ["lib"] +name = "solana_log_utils" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] diff --git a/log-utils/src/lib.rs b/log-utils/src/lib.rs new file mode 100644 index 00000000000000..06d327373bb141 --- /dev/null +++ b/log-utils/src/lib.rs @@ -0,0 +1,64 @@ +use std::{env, thread::JoinHandle}; + +#[cfg(unix)] +fn redirect_stderr(filename: &str) { + use std::{fs::OpenOptions, os::unix::io::AsRawFd}; + match OpenOptions::new().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}"), + } +} + +// Redirect stderr to a file with support for logrotate by sending a SIGUSR1 to the process. +// +// Upon success, future `log` macros and `eprintln!()` can be found in the specified log file. +pub fn redirect_stderr_to_file(logfile: Option) -> Option> { + // Default to RUST_BACKTRACE=1 for more informative validator logs + if env::var_os("RUST_BACKTRACE").is_none() { + env::set_var("RUST_BACKTRACE", "1") + } + + match logfile { + None => { + solana_logger::setup_with_default_filter(); + None + } + Some(logfile) => { + #[cfg(unix)] + { + use log::info; + let mut signals = + signal_hook::iterator::Signals::new([signal_hook::consts::SIGUSR1]) + .unwrap_or_else(|err| { + eprintln!("Unable to register SIGUSR1 handler: {err:?}"); + std::process::exit(1); + }); + + solana_logger::setup_with_default_filter(); + redirect_stderr(&logfile); + Some( + std::thread::Builder::new() + .name("solSigUsr1".into()) + .spawn(move || { + for signal in signals.forever() { + info!( + "received SIGUSR1 ({}), reopening log file: {:?}", + signal, logfile + ); + redirect_stderr(&logfile); + } + }) + .unwrap(), + ) + } + #[cfg(not(unix))] + { + println!("logrotate is not supported on this platform"); + solana_logger::setup_file_with_default(&logfile, solana_logger::DEFAULT_FILTER); + None + } + } + } +}