From 1a6eb05ca1ab0639dcf6e0de5b2627a6b667fb65 Mon Sep 17 00:00:00 2001 From: Igor Katson Date: Mon, 27 Nov 2023 23:19:24 +0000 Subject: [PATCH] Optional file logging --- TODO.md | 7 +++++-- crates/rqbit/src/main.rs | 40 ++++++++++++++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/TODO.md b/TODO.md index 339c3ac..7c24028 100644 --- a/TODO.md +++ b/TODO.md @@ -16,11 +16,14 @@ - [ ] DHT - [ ] for torrents with a few seeds might be cool to re-query DHT once in a while. - [x] it's sending many requests now way too fast, locks up Mac OS UI annoyingly + - [ ] After the search is exhausted, the client then inserts the peer contact information for itself onto the responding nodes with IDs closest to the infohash of the torrent. + - [ ] Bad actors: + - [ ] Ensure that if we query the "returned" nodes, they are even closer to our request than the responding node id was. someday: - [x] cancellation from the client-side for the lib (i.e. stop the torrent manager) -- [ ] favicons for Web UI +- [x] favicons for Web UI refactor: - [x] where are peers stored @@ -33,4 +36,4 @@ refactor: - [ ] if the torrent was completed, not need to re-check it - [x] checking is very slow on raspberry checked. nothing much can be done here. Even if raspberry's own libssl.so is used it's still super slow (sha1) -- [ ] .rqbit-session.json file has 0 bytes when disk full. I guess fs::rename does this when disk is full? at least on linux \ No newline at end of file +- [ ] .rqbit-session.json file has 0 bytes when disk full. I guess fs::rename does this when disk is full? at least on linux. Couldn't repro on MacOS \ No newline at end of file diff --git a/crates/rqbit/src/main.rs b/crates/rqbit/src/main.rs index bf96634..f9fa5c4 100644 --- a/crates/rqbit/src/main.rs +++ b/crates/rqbit/src/main.rs @@ -1,4 +1,4 @@ -use std::{net::SocketAddr, path::PathBuf, sync::Arc, time::Duration}; +use std::{io::BufWriter, net::SocketAddr, path::PathBuf, sync::Arc, time::Duration}; use anyhow::Context; use clap::{Parser, ValueEnum}; @@ -28,10 +28,18 @@ enum LogLevel { #[derive(Parser)] #[command(version, author, about)] struct Opts { - /// The loglevel + /// The console loglevel #[arg(value_enum, short = 'v')] log_level: Option, + /// The log filename to also write to in addition to the console. + #[arg(long = "log-file")] + log_file: Option, + + /// The value for RUST_LOG in the log file + #[arg(long = "log-file-rust-log", default_value = "librqbit=trace,info")] + log_file_rust_log: String, + /// The interval to poll trackers, e.g. 30s. /// Trackers send the refresh interval when we connect to them. Often this is /// pretty big, e.g. 30 minutes. This can force a certain value. @@ -193,10 +201,30 @@ fn init_logging(opts: &Opts) -> tokio::sync::mpsc::UnboundedSender { #[cfg(not(feature = "tokio-console"))] { - tracing_subscriber::registry() - .with(fmt::layer()) - .with(stderr_filter) - .init(); + let layered = tracing_subscriber::registry().with(fmt::layer().with_filter(stderr_filter)); + if let Some(log_file) = &opts.log_file { + let log_file = log_file.clone(); + let log_file = move || { + BufWriter::new( + std::fs::OpenOptions::new() + .create(true) + .append(true) + .write(true) + .open(&log_file) + .with_context(|| format!("error opening log file {:?}", log_file)) + .unwrap(), + ) + }; + layered + .with( + fmt::layer() + .with_writer(log_file) + .with_filter(EnvFilter::builder().parse(&opts.log_file_rust_log).unwrap()), + ) + .init(); + } else { + layered.init(); + } } let (reload_tx, mut reload_rx) = tokio::sync::mpsc::unbounded_channel::();