Skip to content

Commit 0acfff6

Browse files
committed
Add log facade option
Previously, we only had the option of a log file and we'd always drop the trusted wallet's logs on the floor because they do not implement LDK's Logger interface. We add the option to have logs output using the `log` crate instead of to a file. This allows the user to handle the logs in the way they see fit and can integrate better with other rust projects.
1 parent 93a7b24 commit 0acfff6

6 files changed

Lines changed: 86 additions & 32 deletions

File tree

examples/cli/src/main.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use rustyline::error::ReadlineError;
66

77
use orange_sdk::bitcoin_payment_instructions::amount::Amount;
88
use orange_sdk::{
9-
ChainSource, Event, ExtraConfig, Mnemonic, PaymentInfo, Seed, SparkWalletConfig, StorageConfig,
10-
Tunables, Wallet, WalletConfig, bitcoin::Network,
9+
ChainSource, Event, ExtraConfig, LoggerType, Mnemonic, PaymentInfo, Seed, SparkWalletConfig,
10+
StorageConfig, Tunables, Wallet, WalletConfig, bitcoin::Network,
1111
};
1212
use rand::RngCore;
1313
use std::fs;
@@ -79,7 +79,9 @@ fn get_config(network: Network) -> Result<WalletConfig> {
7979

8080
Ok(WalletConfig {
8181
storage_config: StorageConfig::LocalSQLite(storage_path.to_string()),
82-
log_file: PathBuf::from(format!("{storage_path}/wallet.log")),
82+
logger_type: LoggerType::File {
83+
path: PathBuf::from(format!("{storage_path}/wallet.log")),
84+
},
8385
chain_source: ChainSource::Electrum(
8486
"tcp://spark-regtest.benthecarman.com:50001".to_string(),
8587
),
@@ -104,7 +106,9 @@ fn get_config(network: Network) -> Result<WalletConfig> {
104106

105107
Ok(WalletConfig {
106108
storage_config: StorageConfig::LocalSQLite(storage_path.to_string()),
107-
log_file: PathBuf::from(format!("{storage_path}/wallet.log")),
109+
logger_type: LoggerType::File {
110+
path: PathBuf::from(format!("{storage_path}/wallet.log")),
111+
},
108112
chain_source: ChainSource::Esplora {
109113
url: "https://blockstream.info/api".to_string(),
110114
username: None,

orange-sdk/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ uuid = { version = "1.0", default-features = false, optional = true }
2929
cdk = { git = "https://github.com/benthecarman/cdk.git", rev = "7d25e9ae5ed7f47f9ae7e87d8a9ee16797fee8cd", default-features = false, features = ["wallet"], optional = true }
3030
serde_json = { version = "1.0", optional = true }
3131
async-trait = "0.1"
32+
log = "0.4.28"
3233

3334
corepc-node = { version = "0.8.0", features = ["29_0", "download"], optional = true }
3435
cdk-ldk-node = { git = "https://github.com/benthecarman/cdk.git", rev = "7d25e9ae5ed7f47f9ae7e87d8a9ee16797fee8cd", optional = true }

orange-sdk/src/ffi/orange/config.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use crate::ffi::Network;
1818
use crate::ffi::bitcoin_payment_instructions::Amount;
1919
use crate::ffi::ldk_node::Mnemonic;
2020
use crate::ffi::orange::error::ConfigError;
21+
use crate::logging::LoggerType;
2122
use crate::trusted_wallet::ExtraConfig as OrangeExtraConfig;
2223
use crate::{impl_from_core_type, impl_into_core_type};
2324

@@ -261,7 +262,7 @@ impl TryFrom<WalletConfig> for OrangeWalletConfig {
261262
.map_err(|e| ConfigError::InvalidLspAddress(e.to_string()))?;
262263
Ok(OrangeWalletConfig {
263264
storage_config: config.storage_config.into(),
264-
log_file: PathBuf::from(config.log_file),
265+
logger_type: LoggerType::File { path: PathBuf::from(config.log_file) },
265266
chain_source: config.chain_source.into(),
266267
lsp: (lsp_address, lsp_node_id, config.lsp_token.clone()),
267268
scorer_url: config.scorer_url.clone(),

orange-sdk/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ use tokio::runtime::Runtime;
4646

4747
use std::collections::HashMap;
4848
use std::fmt::{self, Debug, Write};
49-
use std::path::PathBuf;
5049
use std::sync::Arc;
5150
use std::time::{Duration, SystemTime};
5251

@@ -63,6 +62,7 @@ use lightning_wallet::LightningWallet;
6362
use logging::Logger;
6463
use trusted_wallet::TrustedError;
6564

65+
pub use crate::logging::LoggerType;
6666
#[cfg(feature = "cashu")]
6767
pub use crate::trusted_wallet::cashu::CashuConfig;
6868
#[cfg(feature = "spark")]
@@ -215,8 +215,8 @@ pub enum ChainSource {
215215
pub struct WalletConfig {
216216
/// Configuration for wallet storage.
217217
pub storage_config: StorageConfig,
218-
/// Location of the wallet's log file.
219-
pub log_file: PathBuf,
218+
/// The type of logger to use.
219+
pub logger_type: LoggerType,
220220
/// Configuration for the blockchain data source.
221221
pub chain_source: ChainSource,
222222
/// Lightning Service Provider (LSP) configuration.
@@ -518,7 +518,7 @@ impl Wallet {
518518
) -> Result<Wallet, InitFailure> {
519519
let tunables = config.tunables;
520520
let network = config.network;
521-
let logger = Arc::new(Logger::new(&config.log_file).expect("Failed to open log file"));
521+
let logger = Arc::new(Logger::new(&config.logger_type).expect("Failed to open log file"));
522522

523523
log_info!(logger, "Initializing orange on network: {network}");
524524

orange-sdk/src/logging.rs

Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,45 @@
11
use chrono::Utc;
22
use ldk_node::lightning::util::logger::Logger as LdkLogger;
33
use ldk_node::lightning::util::logger::{Level, Record};
4-
use ldk_node::logger::{LogRecord, LogWriter};
4+
use ldk_node::logger::{LogLevel, LogRecord, LogWriter};
55
use std::fs;
66
use std::io::{BufWriter, Write};
7-
use std::path::Path;
7+
use std::path::PathBuf;
88
use std::sync::Mutex;
99

10+
/// The type of logger to use.
11+
#[derive(Debug, Clone)]
12+
pub enum LoggerType {
13+
/// A logger that uses the `log` crate facade.
14+
/// This allows integration with existing logging infrastructure.
15+
LogFacade,
16+
/// A logger that writes to a specified file.
17+
/// The file will be created if it does not exist and its parent directories will be created as needed.
18+
File {
19+
/// The path to the log file.
20+
path: PathBuf,
21+
},
22+
}
23+
1024
#[derive(Debug)]
11-
pub struct Logger(Mutex<fs::File>);
25+
pub(crate) enum Logger {
26+
Facade,
27+
File(Mutex<fs::File>),
28+
}
1229

1330
impl Logger {
14-
pub(crate) fn new(path: &Path) -> Result<Logger, ()> {
15-
if path.parent().is_some_and(|p| !p.exists()) {
16-
fs::create_dir_all(path.parent().unwrap()).map_err(|_| ())?;
31+
pub(crate) fn new(logger_type: &LoggerType) -> Result<Self, ()> {
32+
match logger_type {
33+
LoggerType::LogFacade => Ok(Self::Facade),
34+
LoggerType::File { path } => {
35+
if path.parent().is_some_and(|p| !p.exists()) {
36+
fs::create_dir_all(path.parent().unwrap()).map_err(|_| ())?;
37+
}
38+
Ok(Self::File(Mutex::new(
39+
fs::OpenOptions::new().create(true).append(true).open(path).map_err(|_| ())?,
40+
)))
41+
},
1742
}
18-
Ok(Self(Mutex::new(
19-
fs::OpenOptions::new().create(true).append(true).open(path).map_err(|_| ())?,
20-
)))
2143
}
2244
}
2345

@@ -26,17 +48,41 @@ impl LogWriter for Logger {
2648
if record.level == Level::Gossip {
2749
return;
2850
}
29-
let mut file = self.0.lock().unwrap();
30-
let mut buffer = BufWriter::new(&mut *file);
31-
let _ = writeln!(
32-
&mut buffer,
33-
"{} {:<5} [{}:{}] {}",
34-
Utc::now().format("%Y-%m-%d %H:%M:%S"),
35-
record.level.to_string(),
36-
record.module_path,
37-
record.line,
38-
record.args
39-
);
51+
52+
match self {
53+
Logger::Facade => {
54+
let mut builder = log::Record::builder();
55+
56+
match record.level {
57+
LogLevel::Gossip | LogLevel::Trace => builder.level(log::Level::Trace),
58+
LogLevel::Debug => builder.level(log::Level::Debug),
59+
LogLevel::Info => builder.level(log::Level::Info),
60+
LogLevel::Warn => builder.level(log::Level::Warn),
61+
LogLevel::Error => builder.level(log::Level::Error),
62+
};
63+
64+
log::logger().log(
65+
&builder
66+
.module_path(Some(record.module_path))
67+
.line(Some(record.line))
68+
.args(format_args!("{}", record.args))
69+
.build(),
70+
);
71+
},
72+
Logger::File(fs) => {
73+
let mut file = fs.lock().unwrap();
74+
let mut buffer = BufWriter::new(&mut *file);
75+
let _ = writeln!(
76+
&mut buffer,
77+
"{} {:<5} [{}:{}] {}",
78+
Utc::now().format("%Y-%m-%d %H:%M:%S"),
79+
record.level.to_string(),
80+
record.module_path,
81+
record.line,
82+
record.args
83+
);
84+
},
85+
}
4086
}
4187
}
4288

orange-sdk/tests/test_utils.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ use ldk_node::payment::PaymentStatus;
1616
use ldk_node::{Node, bitcoin};
1717
#[cfg(not(feature = "_cashu-tests"))]
1818
use orange_sdk::trusted_wallet::dummy::DummyTrustedWalletExtraConfig;
19-
use orange_sdk::{ChainSource, ExtraConfig, Seed, StorageConfig, Tunables, Wallet, WalletConfig};
19+
use orange_sdk::{
20+
ChainSource, ExtraConfig, LoggerType, Seed, StorageConfig, Tunables, Wallet, WalletConfig,
21+
};
2022
use rand::RngCore;
2123
use std::env::temp_dir;
2224
use std::future::Future;
@@ -290,7 +292,7 @@ pub fn build_test_nodes() -> TestParams {
290292

291293
let wallet_config = WalletConfig {
292294
storage_config: StorageConfig::LocalSQLite(tmp.to_str().unwrap().to_string()),
293-
log_file: tmp.join("orange.log"),
295+
logger_type: LoggerType::LogFacade,
294296
scorer_url: None,
295297
rgs_url: None,
296298
tunables: Tunables::default(),
@@ -422,7 +424,7 @@ pub fn build_test_nodes() -> TestParams {
422424
let tmp = temp_dir().join(format!("orange-test-{test_id}/wallet"));
423425
let wallet_config = WalletConfig {
424426
storage_config: StorageConfig::LocalSQLite(tmp.to_str().unwrap().to_string()),
425-
log_file: tmp.join("orange.log"),
427+
logger_type: LoggerType::LogFacade,
426428
scorer_url: None,
427429
tunables: Tunables::default(),
428430
chain_source: ChainSource::BitcoindRPC {

0 commit comments

Comments
 (0)