Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion dash-spv-ffi/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ use key_wallet_ffi::FFIWalletManager as KeyWalletFFIWalletManager;

use dash_spv::storage::DiskStorageManager;
use dash_spv::DashSpvClient;
use tracing::dispatcher::{get_default, set_default};

use std::mem::{forget, take};
Comment thread
xdustinface marked this conversation as resolved.
use std::sync::{Arc, Mutex};
use tokio::runtime::Runtime;
use tokio::sync::{broadcast, watch};
Expand Down Expand Up @@ -141,6 +143,15 @@ pub unsafe extern "C" fn dash_spv_ffi_client_new(
if config.worker_threads > 0 {
builder.worker_threads(config.worker_threads as usize);
}

// Propagate the caller's tracing subscriber to worker threads so that
// thread-local subscribers (used by tests for per-test log isolation)
// capture logs from spawned async tasks.
let dispatch = get_default(|d| d.clone());
builder.on_thread_start(move || {
let guard = set_default(&dispatch);
forget(guard);
});
let runtime = match builder.build() {
Ok(rt) => Arc::new(rt),
Err(e) => {
Expand Down Expand Up @@ -196,7 +207,7 @@ impl FFIDashSpvClient {
fn cancel_active_tasks(&self) {
let tasks = {
let mut guard = self.active_tasks.lock().unwrap();
std::mem::take(&mut *guard)
take(&mut *guard)
};

for task in &tasks {
Expand Down
1 change: 1 addition & 0 deletions dash-spv-ffi/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ pub unsafe extern "C" fn dash_spv_ffi_init_logging(
level: level_filter,
console: enable_console,
file: file_config,
thread_local: false,
};

match dash_spv::init_logging(config) {
Expand Down
31 changes: 25 additions & 6 deletions dash-spv/src/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::path::{Path, PathBuf};

use chrono::{DateTime, Local};
use tracing::level_filters::LevelFilter;
use tracing::subscriber::{set_default, DefaultGuard};
use tracing_appender::non_blocking::{NonBlocking, WorkerGuard};
use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};

Expand All @@ -19,9 +20,11 @@ const ACTIVE_LOG_NAME: &str = "run.log";

/// Guard that must be kept alive to ensure log flushing on shutdown.
/// When this guard is dropped, all buffered log entries will be flushed.
/// For thread-local logging (tests), also holds the subscriber scope guard.
#[derive(Debug)]
pub struct LoggingGuard {
_worker_guard: Option<WorkerGuard>,
_default_guard: Option<DefaultGuard>,
}

/// Configuration for logging output.
Expand All @@ -33,6 +36,11 @@ pub struct LoggingConfig {
pub console: bool,
/// Optional file logging configuration.
pub file: Option<LogFileConfig>,
/// Use a thread-local subscriber instead of the global one.
/// Allows multiple independent loggers in the same process (e.g. parallel tests).
/// Scoped to the calling thread by default. Worker threads need explicit dispatcher
/// propagation to participate.
pub thread_local: bool,
}

/// Configuration for log file output.
Expand All @@ -53,6 +61,7 @@ pub fn init_console_logging(level: LevelFilter) -> LoggingResult<LoggingGuard> {
level: Some(level),
console: true,
file: None,
thread_local: false,
})
}

Expand Down Expand Up @@ -86,6 +95,7 @@ pub fn init_console_logging(level: LevelFilter) -> LoggingResult<LoggingGuard> {
/// level: Some(LevelFilter::INFO),
/// console: true,
/// file: None,
/// thread_local: false,
/// }).unwrap();
///
/// // File logging only (CLI default)
Expand All @@ -96,13 +106,15 @@ pub fn init_console_logging(level: LevelFilter) -> LoggingResult<LoggingGuard> {
/// log_dir: PathBuf::from("/path/to/data/logs"),
/// max_files: 20,
/// }),
/// thread_local: false,
/// }).unwrap();
/// ```
pub fn init_logging(config: LoggingConfig) -> LoggingResult<LoggingGuard> {
// No output configured - tracing macros become no-ops
if !config.console && config.file.is_none() {
return Ok(LoggingGuard {
_worker_guard: None,
_default_guard: None,
});
}

Expand Down Expand Up @@ -131,15 +143,21 @@ pub fn init_logging(config: LoggingConfig) -> LoggingResult<LoggingGuard> {
config.console.then(|| fmt::layer().with_target(true).with_thread_ids(false));

// Combine layers and initialize
tracing_subscriber::registry()
.with(env_filter)
.with(file_layer)
.with(console_layer)
.try_init()
.map_err(|e| LoggingError::SubscriberInit(e.to_string()))?;
let subscriber =
tracing_subscriber::registry().with(env_filter).with(file_layer).with(console_layer);

let default_guard = if config.thread_local {
// Thread-local subscriber — allows multiple independent loggers per process
Some(set_default(subscriber))
} else {
// Global subscriber — covers all threads, can only be set once
subscriber.try_init().map_err(|e| LoggingError::SubscriberInit(e.to_string()))?;
None
};

Ok(LoggingGuard {
_worker_guard: guard,
_default_guard: default_guard,
})
}

Expand Down Expand Up @@ -557,6 +575,7 @@ mod tests {
level: Some(LevelFilter::INFO),
console: false,
file: None,
thread_local: false,
});

assert!(result.is_ok());
Expand Down
1 change: 1 addition & 0 deletions dash-spv/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ async fn run() -> Result<(), Box<dyn std::error::Error>> {
level: Some(log_level),
console: console_enabled,
file: file_config,
thread_local: false,
};

// Initialize logging, keep guard alive for the duration of run()
Expand Down
Loading