From c565e87d4d6028b155f71c78389375ce75802d1d Mon Sep 17 00:00:00 2001 From: pythcoiner Date: Sun, 15 Sep 2024 14:51:02 +0200 Subject: [PATCH 1/2] doc fix --- src/lib.rs | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e08be92..96c6da1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,11 +18,13 @@ use bitcoind::tempfile::TempDir; use bitcoind::{get_available_port, BitcoinD}; use electrum_client::raw_client::{ElectrumPlaintextStream, RawClient}; use log::{debug, error, warn}; -use std::env; use std::ffi::OsStr; +use std::io::{BufRead, BufReader}; use std::path::PathBuf; use std::process::{Child, Command, Stdio}; +use std::sync::mpsc::{self, Receiver}; use std::time::Duration; +use std::{env, thread}; // re-export bitcoind pub use bitcoind; @@ -54,6 +56,9 @@ pub struct Conf<'a> { /// if `true` electrsd log output will not be suppressed pub view_stderr: bool, + /// Log level of electrs + pub log_level: log::Level, + /// if `true` electrsd exposes an esplora endpoint pub http_enabled: bool, @@ -103,11 +108,12 @@ impl Default for Conf<'_> { tmpdir: None, staticdir: None, attempts: 3, + log_level: log::Level::Info, } } } -/// Struct representing the bitcoind process with related information +/// Struct representing the electrs process with related information pub struct ElectrsD { /// Process child handle, used to terminate the process when this struct is dropped process: Child, @@ -119,6 +125,8 @@ pub struct ElectrsD { pub electrum_url: String, /// Url to connect to esplora protocol (http) pub esplora_url: Option, + /// A buffer receiving stdout and stderr + pub logs: Receiver, } /// The DataDir struct defining the kind of data directory electrs will use. @@ -250,19 +258,36 @@ impl ElectrsD { None }; - let view_stderr = if conf.view_stderr { - Stdio::inherit() - } else { - Stdio::null() - }; + let log_level = format!("--log-filters {}", conf.log_level); + args.push(&log_level); debug!("args: {:?}", args); let mut process = Command::new(&exe) .args(args) - .stderr(view_stderr) + .stderr(Stdio::piped()) + .stdout(Stdio::piped()) .spawn() .with_context(|| format!("Error while executing {:?}", exe.as_ref()))?; + let (sender, logs) = mpsc::channel(); + let stdout = process.stdout.take().unwrap(); + let stderr = process.stderr.take().unwrap(); + + let s = sender.clone(); + thread::spawn(move || { + let reader = BufReader::new(stdout); + for line in reader.lines() { + s.send(line.unwrap()); + } + }); + + thread::spawn(move || { + let reader = BufReader::new(stderr); + for line in reader.lines() { + sender.send(line.unwrap()); + } + }); + let client = loop { if let Some(status) = process.try_wait()? { if conf.attempts > 0 { @@ -288,6 +313,7 @@ impl ElectrsD { work_dir, electrum_url, esplora_url, + logs, }) } From d0e740d1924dc0fa0e3c4e0a371dac839d6bf505 Mon Sep 17 00:00:00 2001 From: pythcoiner Date: Sat, 21 Sep 2024 04:18:17 +0200 Subject: [PATCH 2/2] add option to redirect stdout/stderr to an mpsc::channel --- src/lib.rs | 53 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 96c6da1..75ac2d6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,8 +56,9 @@ pub struct Conf<'a> { /// if `true` electrsd log output will not be suppressed pub view_stderr: bool, - /// Log level of electrs - pub log_level: log::Level, + /// if true, logs (stdout + stderr) are redirected to ElectrsD.logs + /// note: this feature will take precedence over `view_stderr` + pub buffered_logs: bool, /// if `true` electrsd exposes an esplora endpoint pub http_enabled: bool, @@ -108,7 +109,7 @@ impl Default for Conf<'_> { tmpdir: None, staticdir: None, attempts: 3, - log_level: log::Level::Info, + buffered_logs: false, } } } @@ -258,14 +259,19 @@ impl ElectrsD { None }; - let log_level = format!("--log-filters {}", conf.log_level); - args.push(&log_level); + let (stderr, stdout) = if conf.buffered_logs { + (Stdio::piped(), Stdio::piped()) + } else if conf.view_stderr { + (Stdio::inherit(), Stdio::null()) + } else { + (Stdio::null(), Stdio::null()) + }; debug!("args: {:?}", args); let mut process = Command::new(&exe) .args(args) - .stderr(Stdio::piped()) - .stdout(Stdio::piped()) + .stderr(stderr) + .stdout(stdout) .spawn() .with_context(|| format!("Error while executing {:?}", exe.as_ref()))?; @@ -273,20 +279,22 @@ impl ElectrsD { let stdout = process.stdout.take().unwrap(); let stderr = process.stderr.take().unwrap(); - let s = sender.clone(); - thread::spawn(move || { - let reader = BufReader::new(stdout); - for line in reader.lines() { - s.send(line.unwrap()); - } - }); + if conf.buffered_logs { + let s = sender.clone(); + thread::spawn(move || { + let reader = BufReader::new(stdout); + for line in reader.lines() { + s.send(line.unwrap()); + } + }); - thread::spawn(move || { - let reader = BufReader::new(stderr); - for line in reader.lines() { - sender.send(line.unwrap()); - } - }); + thread::spawn(move || { + let reader = BufReader::new(stderr); + for line in reader.lines() { + sender.send(line.unwrap()); + } + }); + } let client = loop { if let Some(status) = process.try_wait()? { @@ -351,6 +359,11 @@ impl ElectrsD { } } + /// clear the log buffer + pub fn clear_logs(&mut self) { + while self.logs.try_recv().is_ok() {} + } + #[cfg(not(target_os = "windows"))] fn inner_kill(&mut self) -> anyhow::Result<()> { // Send SIGINT signal to electrsd