feat: record-daemon logs to a file
This commit is contained in:
@@ -42,6 +42,10 @@ struct Args {
|
||||
/// Socket path for IPC.
|
||||
#[arg(short, long)]
|
||||
socket: Option<std::path::PathBuf>,
|
||||
|
||||
/// Path to log file. If not specified, logs to stdout/stderr.
|
||||
#[arg(short, long, value_name = "PATH")]
|
||||
log_file: Option<std::path::PathBuf>,
|
||||
}
|
||||
|
||||
/// Main daemon structure.
|
||||
@@ -579,15 +583,49 @@ impl Daemon {
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize logging.
|
||||
fn init_logging(level: &str) {
|
||||
/// Initialize logging with optional file output.
|
||||
fn init_logging(level: &str, log_file: Option<&std::path::Path>) {
|
||||
let filter = tracing_subscriber::EnvFilter::try_from_default_env()
|
||||
.unwrap_or_else(|_| tracing_subscriber::EnvFilter::new(level));
|
||||
|
||||
tracing_subscriber::registry()
|
||||
.with(filter)
|
||||
.with(tracing_subscriber::fmt::layer())
|
||||
.init();
|
||||
if let Some(log_path) = log_file {
|
||||
// Ensure parent directory exists
|
||||
if let Some(parent) = log_path.parent() {
|
||||
let _ = std::fs::create_dir_all(parent);
|
||||
}
|
||||
|
||||
// Use file appender for logging
|
||||
let prefix = log_path
|
||||
.file_stem()
|
||||
.and_then(|s| s.to_str())
|
||||
.unwrap_or("daemon");
|
||||
|
||||
let file_appender = tracing_appender::rolling::RollingFileAppender::builder()
|
||||
.rotation(tracing_appender::rolling::Rotation::DAILY)
|
||||
.filename_prefix(prefix)
|
||||
.filename_suffix("log")
|
||||
.build(log_path.parent().unwrap_or(std::path::Path::new(".")))
|
||||
.expect("Failed to create log file appender");
|
||||
|
||||
let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender);
|
||||
|
||||
// Store the guard to prevent it from being dropped
|
||||
// We leak it intentionally to keep logging working for the daemon's lifetime
|
||||
std::mem::forget(_guard);
|
||||
|
||||
tracing_subscriber::registry()
|
||||
.with(filter)
|
||||
.with(tracing_subscriber::fmt::layer().with_writer(non_blocking))
|
||||
.init();
|
||||
|
||||
eprintln!("Logging to file: {}", log_path.display());
|
||||
} else {
|
||||
// Log to stdout/stderr
|
||||
tracing_subscriber::registry()
|
||||
.with(filter)
|
||||
.with(tracing_subscriber::fmt::layer())
|
||||
.init();
|
||||
}
|
||||
|
||||
// Set up panic hook to log panics
|
||||
std::panic::set_hook(Box::new(|panic_info| {
|
||||
@@ -614,7 +652,7 @@ async fn main() -> Result<()> {
|
||||
let args = Args::parse();
|
||||
|
||||
// Initialize logging
|
||||
init_logging(&args.log_level);
|
||||
init_logging(&args.log_level, args.log_file.as_deref());
|
||||
|
||||
info!("Record Daemon v{} starting", record_daemon::VERSION);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user