Skip to content

Commit a88dc5c

Browse files
committed
feat(logger): implement configurable log writer with filesystem support
* Add flexible log writer interface for multiple destinations * Implement filesystem writing capability via FilesystemLogger * Prefix LDK-based objects with 'Ldk' for consistency * Add configuration options for log file path and log level
1 parent 0558d91 commit a88dc5c

24 files changed

+259
-216
lines changed

bindings/ldk_node.udl

+15-11
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@ namespace ldk_node {
55

66
dictionary Config {
77
string storage_dir_path;
8-
string? log_file_path;
98
Network network;
109
sequence<SocketAddress>? listening_addresses;
1110
NodeAlias? node_alias;
1211
sequence<PublicKey> trusted_peers_0conf;
1312
u64 probing_liquidity_limit_multiplier;
14-
LogLevel log_level;
1513
AnchorChannelsConfig? anchor_channels_config;
1614
SendingParameters? sending_parameters;
1715
};
@@ -27,6 +25,20 @@ dictionary EsploraSyncConfig {
2725
u64 fee_rate_cache_update_interval_secs;
2826
};
2927

28+
enum LdkLevel {
29+
"Gossip",
30+
"Trace",
31+
"Debug",
32+
"Info",
33+
"Warn",
34+
"Error",
35+
};
36+
37+
dictionary FilesystemLoggerConfig {
38+
string log_file_path;
39+
LdkLevel level;
40+
};
41+
3042
interface Builder {
3143
constructor();
3244
[Name=from_config]
@@ -41,6 +53,7 @@ interface Builder {
4153
void set_gossip_source_rgs(string rgs_server_url);
4254
void set_liquidity_source_lsps2(SocketAddress address, PublicKey node_id, string? token);
4355
void set_storage_dir_path(string storage_dir_path);
56+
void set_filesystem_logger(FilesystemLoggerConfig fs_config);
4457
void set_network(Network network);
4558
[Throws=BuildError]
4659
void set_listening_addresses(sequence<SocketAddress> listening_addresses);
@@ -535,15 +548,6 @@ interface MaxDustHTLCExposure {
535548
FeeRateMultiplier ( u64 multiplier );
536549
};
537550

538-
enum LogLevel {
539-
"Gossip",
540-
"Trace",
541-
"Debug",
542-
"Info",
543-
"Warn",
544-
"Error",
545-
};
546-
547551
interface NetworkGraph {
548552
sequence<u64> list_channels();
549553
ChannelInfo? channel(u64 short_channel_id);

src/builder.rs

+52-38
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
// accordance with one or both of these licenses.
77

88
use crate::chain::{ChainSource, DEFAULT_ESPLORA_SERVER_URL};
9-
use crate::config::{default_user_config, Config, EsploraSyncConfig, WALLET_KEYS_SEED_LEN};
9+
use crate::config::{
10+
default_user_config, Config, EsploraSyncConfig, FilesystemLoggerConfig, WALLET_KEYS_SEED_LEN,
11+
};
1012

1113
use crate::connection::ConnectionManager;
1214
use crate::event::EventQueue;
@@ -16,7 +18,7 @@ use crate::io::sqlite_store::SqliteStore;
1618
use crate::io::utils::{read_node_metrics, write_node_metrics};
1719
use crate::io::vss_store::VssStore;
1820
use crate::liquidity::LiquiditySource;
19-
use crate::logger::{log_error, log_info, FilesystemLogger, Logger};
21+
use crate::logger::{log_error, log_info, LdkLogger, Logger};
2022
use crate::message_handler::NodeCustomMessageHandler;
2123
use crate::payment::store::PaymentStore;
2224
use crate::peer_store::PeerStore;
@@ -27,8 +29,8 @@ use crate::types::{
2729
};
2830
use crate::wallet::persist::KVStoreWalletPersister;
2931
use crate::wallet::Wallet;
32+
use crate::Node;
3033
use crate::{io, NodeMetrics};
31-
use crate::{LogLevel, Node};
3234

3335
use lightning::chain::{chainmonitor, BestBlock, Watch};
3436
use lightning::io::Cursor;
@@ -106,6 +108,17 @@ impl Default for LiquiditySourceConfig {
106108
}
107109
}
108110

111+
#[derive(Debug)]
112+
enum LogWriterConfig {
113+
File(FilesystemLoggerConfig),
114+
}
115+
116+
impl Default for LogWriterConfig {
117+
fn default() -> Self {
118+
Self::File(FilesystemLoggerConfig::default())
119+
}
120+
}
121+
109122
/// An error encountered during building a [`Node`].
110123
///
111124
/// [`Node`]: crate::Node
@@ -182,6 +195,7 @@ pub struct NodeBuilder {
182195
chain_data_source_config: Option<ChainDataSourceConfig>,
183196
gossip_source_config: Option<GossipSourceConfig>,
184197
liquidity_source_config: Option<LiquiditySourceConfig>,
198+
log_writer_config: Option<LogWriterConfig>,
185199
}
186200

187201
impl NodeBuilder {
@@ -197,12 +211,14 @@ impl NodeBuilder {
197211
let chain_data_source_config = None;
198212
let gossip_source_config = None;
199213
let liquidity_source_config = None;
214+
let log_writer_config = None;
200215
Self {
201216
config,
202217
entropy_source_config,
203218
chain_data_source_config,
204219
gossip_source_config,
205220
liquidity_source_config,
221+
log_writer_config,
206222
}
207223
}
208224

@@ -298,9 +314,9 @@ impl NodeBuilder {
298314
self
299315
}
300316

301-
/// Sets the log file path if the log file needs to live separate from the storage directory path.
302-
pub fn set_log_file_path(&mut self, log_dir_path: String) -> &mut Self {
303-
self.config.log_file_path = Some(log_dir_path);
317+
/// Configures the [`Node`] instance to write logs to the filesystem.
318+
pub fn set_filesystem_logger(&mut self, fs_config: FilesystemLoggerConfig) -> &mut Self {
319+
self.log_writer_config = Some(LogWriterConfig::File(fs_config));
304320
self
305321
}
306322

@@ -333,12 +349,6 @@ impl NodeBuilder {
333349
Ok(self)
334350
}
335351

336-
/// Sets the level at which [`Node`] will log messages.
337-
pub fn set_log_level(&mut self, level: LogLevel) -> &mut Self {
338-
self.config.log_level = level;
339-
self
340-
}
341-
342352
/// Builds a [`Node`] instance with a [`SqliteStore`] backend and according to the options
343353
/// previously configured.
344354
pub fn build(&self) -> Result<Node, BuildError> {
@@ -391,7 +401,10 @@ impl NodeBuilder {
391401
) -> Result<Node, BuildError> {
392402
use bitcoin::key::Secp256k1;
393403

394-
let logger = setup_logger(&self.config)?;
404+
let writer = LogWriterConfig::default();
405+
let log_writer_config =
406+
if let Some(config) = &self.log_writer_config { config } else { &writer };
407+
let logger = setup_logger(&log_writer_config)?;
395408

396409
let seed_bytes = seed_bytes_from_config(
397410
&self.config,
@@ -456,7 +469,10 @@ impl NodeBuilder {
456469
pub fn build_with_vss_store_and_header_provider(
457470
&self, vss_url: String, store_id: String, header_provider: Arc<dyn VssHeaderProvider>,
458471
) -> Result<Node, BuildError> {
459-
let logger = setup_logger(&self.config)?;
472+
let writer = LogWriterConfig::default();
473+
let log_writer_config =
474+
if let Some(config) = &self.log_writer_config { config } else { &writer };
475+
let logger = setup_logger(&log_writer_config)?;
460476

461477
let seed_bytes = seed_bytes_from_config(
462478
&self.config,
@@ -488,7 +504,11 @@ impl NodeBuilder {
488504

489505
/// Builds a [`Node`] instance according to the options previously configured.
490506
pub fn build_with_store(&self, kv_store: Arc<DynStore>) -> Result<Node, BuildError> {
491-
let logger = setup_logger(&self.config)?;
507+
let writer = LogWriterConfig::default();
508+
let log_writer_config =
509+
if let Some(config) = &self.log_writer_config { config } else { &writer };
510+
let logger = setup_logger(&log_writer_config)?;
511+
492512
let seed_bytes = seed_bytes_from_config(
493513
&self.config,
494514
self.entropy_source_config.as_ref(),
@@ -610,9 +630,9 @@ impl ArcedNodeBuilder {
610630
self.inner.write().unwrap().set_storage_dir_path(storage_dir_path);
611631
}
612632

613-
/// Sets the log file path if logs need to live separate from the storage directory path.
614-
pub fn set_log_file_path(&self, log_file_path: String) {
615-
self.inner.write().unwrap().set_log_file_path(log_file_path);
633+
/// Configures the [`Node`] instance to write logs to the filesystem.
634+
pub fn set_filesystem_logger(&self, fs_config: FilesystemLoggerConfig) {
635+
self.inner.write().unwrap().set_filesystem_logger(fs_config);
616636
}
617637

618638
/// Sets the Bitcoin network used.
@@ -635,11 +655,6 @@ impl ArcedNodeBuilder {
635655
self.inner.write().unwrap().set_node_alias(node_alias).map(|_| ())
636656
}
637657

638-
/// Sets the level at which [`Node`] will log messages.
639-
pub fn set_log_level(&self, level: LogLevel) {
640-
self.inner.write().unwrap().set_log_level(level);
641-
}
642-
643658
/// Builds a [`Node`] instance with a [`SqliteStore`] backend and according to the options
644659
/// previously configured.
645660
pub fn build(&self) -> Result<Arc<Node>, BuildError> {
@@ -734,7 +749,7 @@ fn build_with_store_internal(
734749
config: Arc<Config>, chain_data_source_config: Option<&ChainDataSourceConfig>,
735750
gossip_source_config: Option<&GossipSourceConfig>,
736751
liquidity_source_config: Option<&LiquiditySourceConfig>, seed_bytes: [u8; 64],
737-
logger: Arc<FilesystemLogger>, kv_store: Arc<DynStore>,
752+
logger: Arc<Logger>, kv_store: Arc<DynStore>,
738753
) -> Result<Node, BuildError> {
739754
// Initialize the status fields.
740755
let is_listening = Arc::new(AtomicBool::new(false));
@@ -1242,23 +1257,22 @@ fn build_with_store_internal(
12421257
})
12431258
}
12441259

1245-
/// Sets up the node logger, creating a new log file if it does not exist, or utilizing
1246-
/// the existing log file.
1247-
fn setup_logger(config: &Config) -> Result<Arc<FilesystemLogger>, BuildError> {
1248-
let log_file_path = match &config.log_file_path {
1249-
Some(log_dir) => String::from(log_dir),
1250-
None => format!("{}/{}", config.storage_dir_path.clone(), "ldk_node.log"),
1251-
};
1260+
/// Sets up the node logger.
1261+
fn setup_logger(config: &LogWriterConfig) -> Result<Arc<Logger>, BuildError> {
1262+
match config {
1263+
LogWriterConfig::File(fs_logger_config) => {
1264+
let log_file_path = &fs_logger_config.log_file_path;
12521265

1253-
Ok(Arc::new(
1254-
FilesystemLogger::new(log_file_path, config.log_level)
1255-
.map_err(|_| BuildError::LoggerSetupFailed)?,
1256-
))
1266+
Ok(Arc::new(
1267+
Logger::new_fs_writer(log_file_path.to_string(), fs_logger_config.level)
1268+
.map_err(|_| BuildError::LoggerSetupFailed)?,
1269+
))
1270+
},
1271+
}
12571272
}
12581273

12591274
fn seed_bytes_from_config(
1260-
config: &Config, entropy_source_config: Option<&EntropySourceConfig>,
1261-
logger: Arc<FilesystemLogger>,
1275+
config: &Config, entropy_source_config: Option<&EntropySourceConfig>, logger: Arc<Logger>,
12621276
) -> Result<[u8; 64], BuildError> {
12631277
match entropy_source_config {
12641278
Some(EntropySourceConfig::SeedBytes(bytes)) => Ok(bytes.clone()),
@@ -1280,7 +1294,7 @@ fn seed_bytes_from_config(
12801294
}
12811295

12821296
fn derive_vss_xprv(
1283-
config: Arc<Config>, seed_bytes: &[u8; 64], logger: Arc<FilesystemLogger>,
1297+
config: Arc<Config>, seed_bytes: &[u8; 64], logger: Arc<Logger>,
12841298
) -> Result<Xpriv, BuildError> {
12851299
use bitcoin::key::Secp256k1;
12861300

src/chain/mod.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use crate::fee_estimator::{
2121
ConfirmationTarget, OnchainFeeEstimator,
2222
};
2323
use crate::io::utils::write_node_metrics;
24-
use crate::logger::{log_bytes, log_error, log_info, log_trace, FilesystemLogger, Logger};
24+
use crate::logger::{log_bytes, log_error, log_info, log_trace, LdkLogger, Logger};
2525
use crate::types::{Broadcaster, ChainMonitor, ChannelManager, DynStore, Sweeper, Wallet};
2626
use crate::{Error, NodeMetrics};
2727

@@ -113,13 +113,13 @@ pub(crate) enum ChainSource {
113113
esplora_client: EsploraAsyncClient,
114114
onchain_wallet: Arc<Wallet>,
115115
onchain_wallet_sync_status: Mutex<WalletSyncStatus>,
116-
tx_sync: Arc<EsploraSyncClient<Arc<FilesystemLogger>>>,
116+
tx_sync: Arc<EsploraSyncClient<Arc<Logger>>>,
117117
lightning_wallet_sync_status: Mutex<WalletSyncStatus>,
118118
fee_estimator: Arc<OnchainFeeEstimator>,
119119
tx_broadcaster: Arc<Broadcaster>,
120120
kv_store: Arc<DynStore>,
121121
config: Arc<Config>,
122-
logger: Arc<FilesystemLogger>,
122+
logger: Arc<Logger>,
123123
node_metrics: Arc<RwLock<NodeMetrics>>,
124124
},
125125
BitcoindRpc {
@@ -132,7 +132,7 @@ pub(crate) enum ChainSource {
132132
tx_broadcaster: Arc<Broadcaster>,
133133
kv_store: Arc<DynStore>,
134134
config: Arc<Config>,
135-
logger: Arc<FilesystemLogger>,
135+
logger: Arc<Logger>,
136136
node_metrics: Arc<RwLock<NodeMetrics>>,
137137
},
138138
}
@@ -141,7 +141,7 @@ impl ChainSource {
141141
pub(crate) fn new_esplora(
142142
server_url: String, sync_config: EsploraSyncConfig, onchain_wallet: Arc<Wallet>,
143143
fee_estimator: Arc<OnchainFeeEstimator>, tx_broadcaster: Arc<Broadcaster>,
144-
kv_store: Arc<DynStore>, config: Arc<Config>, logger: Arc<FilesystemLogger>,
144+
kv_store: Arc<DynStore>, config: Arc<Config>, logger: Arc<Logger>,
145145
node_metrics: Arc<RwLock<NodeMetrics>>,
146146
) -> Self {
147147
let mut client_builder = esplora_client::Builder::new(&server_url);
@@ -171,7 +171,7 @@ impl ChainSource {
171171
host: String, port: u16, rpc_user: String, rpc_password: String,
172172
onchain_wallet: Arc<Wallet>, fee_estimator: Arc<OnchainFeeEstimator>,
173173
tx_broadcaster: Arc<Broadcaster>, kv_store: Arc<DynStore>, config: Arc<Config>,
174-
logger: Arc<FilesystemLogger>, node_metrics: Arc<RwLock<NodeMetrics>>,
174+
logger: Arc<Logger>, node_metrics: Arc<RwLock<NodeMetrics>>,
175175
) -> Self {
176176
let bitcoind_rpc_client =
177177
Arc::new(BitcoindRpcClient::new(host, port, rpc_user, rpc_password));
@@ -1125,7 +1125,7 @@ impl Filter for ChainSource {
11251125

11261126
fn periodically_archive_fully_resolved_monitors(
11271127
channel_manager: Arc<ChannelManager>, chain_monitor: Arc<ChainMonitor>,
1128-
kv_store: Arc<DynStore>, logger: Arc<FilesystemLogger>, node_metrics: Arc<RwLock<NodeMetrics>>,
1128+
kv_store: Arc<DynStore>, logger: Arc<Logger>, node_metrics: Arc<RwLock<NodeMetrics>>,
11291129
) -> Result<(), Error> {
11301130
let mut locked_node_metrics = node_metrics.write().unwrap();
11311131
let cur_height = channel_manager.current_best_block().height;

0 commit comments

Comments
 (0)