Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ libc = "0.2"
uniffi = { version = "0.27.3", features = ["build"], optional = true }
serde = { version = "1.0.210", default-features = false, features = ["std", "derive"] }
serde_json = { version = "1.0.128", default-features = false, features = ["std"] }

log = { version = "0.4.22" }
vss-client = "0.3"
prost = { version = "0.11.6", default-features = false}

Expand Down
68 changes: 45 additions & 23 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

use crate::chain::{ChainSource, DEFAULT_ESPLORA_SERVER_URL};
use crate::config::{
default_user_config, Config, EsploraSyncConfig, LoggingConfig, WALLET_KEYS_SEED_LEN,
default_user_config, Config, EsploraSyncConfig, FormatterConfig, LoggerConfig, WriterConfig,
WriterType, WALLET_KEYS_SEED_LEN,
};

use crate::connection::ConnectionManager;
Expand All @@ -18,7 +19,7 @@ use crate::io::sqlite_store::SqliteStore;
use crate::io::utils::{read_node_metrics, write_node_metrics};
use crate::io::vss_store::VssStore;
use crate::liquidity::LiquiditySource;
use crate::logger::{default_format, log_error, log_info, FileWriter, LdkNodeLogger, Logger};
use crate::logger::{build_formatter, log_error, log_info, LdkNodeLogger, Logger, Writer};
use crate::message_handler::NodeCustomMessageHandler;
use crate::payment::store::PaymentStore;
use crate::peer_store::PeerStore;
Expand Down Expand Up @@ -300,6 +301,18 @@ impl NodeBuilder {
self
}

/// Sets the logger's writer config.
pub fn set_log_writer_config(&mut self, writer_config: WriterConfig) -> &mut Self {
self.config.logger_config.writer = writer_config;
self
}

/// Sets the logger's formatter config.
pub fn set_log_formatter_config(&mut self, formatter_config: FormatterConfig) -> &mut Self {
self.config.logger_config.formatter = formatter_config;
self
}

/// Sets the Bitcoin network used.
pub fn set_network(&mut self, network: Network) -> &mut Self {
self.config.network = network;
Expand Down Expand Up @@ -381,7 +394,7 @@ impl NodeBuilder {
) -> Result<Node, BuildError> {
use bitcoin::key::Secp256k1;

let logger = setup_logger(&self.config)?;
let logger = setup_logger(&self.config.logger_config)?;

let seed_bytes = seed_bytes_from_config(
&self.config,
Expand Down Expand Up @@ -446,7 +459,7 @@ impl NodeBuilder {
pub fn build_with_vss_store_and_header_provider(
&self, vss_url: String, store_id: String, header_provider: Arc<dyn VssHeaderProvider>,
) -> Result<Node, BuildError> {
let logger = setup_logger(&self.config)?;
let logger = setup_logger(&self.config.logger_config)?;

let seed_bytes = seed_bytes_from_config(
&self.config,
Expand Down Expand Up @@ -478,7 +491,7 @@ impl NodeBuilder {

/// Builds a [`Node`] instance according to the options previously configured.
pub fn build_with_store(&self, kv_store: Arc<DynStore>) -> Result<Node, BuildError> {
let logger = setup_logger(&self.config)?;
let logger = setup_logger(&self.config.logger_config)?;
let seed_bytes = seed_bytes_from_config(
&self.config,
self.entropy_source_config.as_ref(),
Expand Down Expand Up @@ -600,6 +613,16 @@ impl ArcedNodeBuilder {
self.inner.write().unwrap().set_storage_dir_path(storage_dir_path);
}

/// Sets the logger's writer config.
pub fn set_log_writer_config(&mut self, writer_config: WriterConfig) -> &mut Self {
self.inner.write().unwrap().set_log_writer_config(writer_config);
}

/// Sets the logger's formatter config.
pub fn set_log_formatter_config(&mut self, formatter_config: FormatterConfig) -> &mut Self {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not quite sure why we'd need separate configurations for the formatter? This is still related to a filesystem writer only, no?

self.inner.write().unwrap().set_log_formatter_config(formatter_config);
}

/// Sets the Bitcoin network used.
pub fn set_network(&self, network: Network) {
self.inner.write().unwrap().set_network(network);
Expand Down Expand Up @@ -1211,24 +1234,23 @@ fn build_with_store_internal(
})
}

/// Sets up the node logger, creating a new log file if it does not exist, or utilizing
/// the existing log file.
fn setup_logger(config: &Config) -> Result<Arc<LdkNodeLogger>, BuildError> {
match config.logging_config {
LoggingConfig::Custom(ref logger) => Ok(logger.clone()),
LoggingConfig::Filesystem { ref log_file_path, log_level } => {
let filesystem_log_writer = FileWriter::new(log_file_path.clone())
.map_err(|_| BuildError::LoggerSetupFailed)?;
Ok(Arc::new(
LdkNodeLogger::new(
log_level,
Box::new(default_format),
Box::new(move |s| filesystem_log_writer.write(s)),
)
.map_err(|_| BuildError::LoggerSetupFailed)?,
))
},
}
/// Sets up the node logger.
fn setup_logger(config: &LoggerConfig) -> Result<Arc<LdkNodeLogger>, BuildError> {
let level = match &config.writer.writer_type {
WriterType::File(file_writer_config) => file_writer_config.level,
WriterType::LogRelay(log_relay_writer_config) => log_relay_writer_config.level,
WriterType::Custom(custom_writer_config) => custom_writer_config.level,
};

let writer =
Writer::new(&config.writer.writer_type).map_err(|_e| BuildError::LoggerSetupFailed)?;

let formatter = build_formatter(config.formatter.clone());

let ldk_node_logger =
LdkNodeLogger::new(level, formatter, writer).map_err(|_e| BuildError::LoggerSetupFailed)?;

Ok(Arc::new(ldk_node_logger))
}

fn seed_bytes_from_config(
Expand Down
130 changes: 103 additions & 27 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,31 @@

//! Objects for configuring the node.

use crate::logger::LdkNodeLogger;
use crate::logger::LogWriter;
use crate::payment::SendingParameters;

use lightning::ln::msgs::SocketAddress;
use lightning::routing::gossip::NodeAlias;
use lightning::util::config::ChannelConfig as LdkChannelConfig;
use lightning::util::config::MaxDustHTLCExposure as LdkMaxDustHTLCExposure;
use lightning::util::config::UserConfig;
use lightning::util::logger::Level as LogLevel;
use lightning::util::logger::Level;

use bitcoin::secp256k1::PublicKey;
use bitcoin::Network;

use std::sync::Arc;
use std::time::Duration;

// Config defaults
const DEFAULT_STORAGE_DIR_PATH: &str = "/tmp/ldk_node";
const DEFAULT_LOG_FILE_PATH: &str = "/tmp/ldk_node/ldk_node.log";
const DEFAULT_NETWORK: Network = Network::Bitcoin;
const DEFAULT_BDK_WALLET_SYNC_INTERVAL_SECS: u64 = 80;
const DEFAULT_LDK_WALLET_SYNC_INTERVAL_SECS: u64 = 30;
const DEFAULT_FEE_RATE_CACHE_UPDATE_INTERVAL_SECS: u64 = 60 * 10;
const DEFAULT_PROBING_LIQUIDITY_LIMIT_MULTIPLIER: u64 = 3;
const DEFAULT_LOG_LEVEL: LogLevel = LogLevel::Debug;
const DEFAULT_LOG_LEVEL: Level = Level::Debug;
const DEFAULT_ANCHOR_PER_CHANNEL_RESERVE_SATS: u64 = 25_000;

// The 'stop gap' parameter used by BDK's wallet sync. This seems to configure the threshold
Expand Down Expand Up @@ -104,9 +106,8 @@ pub(crate) const WALLET_KEYS_SEED_LEN: usize = 64;
pub struct Config {
/// The path where the underlying LDK and BDK persist their data.
pub storage_dir_path: String,
/// In the default configuration logs can be found in the [`DEFAULT_STORAGE_DIR_PATH`] subdirectory in
/// [`Config::storage_dir_path`], and the log level is set to [`DEFAULT_LOG_LEVEL`].
pub logging_config: LoggingConfig,
/// The configuration options for the logger.
pub logger_config: LoggerConfig,
/// The used Bitcoin network.
pub network: Network,
/// The addresses on which the node will listen for incoming connections.
Expand Down Expand Up @@ -163,7 +164,7 @@ impl Default for Config {
fn default() -> Self {
Self {
storage_dir_path: DEFAULT_STORAGE_DIR_PATH.to_string(),
logging_config: LoggingConfig::default(),
logger_config: LoggerConfig::default(),
network: DEFAULT_NETWORK,
listening_addresses: None,
trusted_peers_0conf: Vec::new(),
Expand All @@ -175,34 +176,109 @@ impl Default for Config {
}
}

/// Configuration options for logging.
/// Logger configuration.
#[derive(Debug, Clone)]
pub enum LoggingConfig {
/// An opinionated filesystem logger.
///
/// This logger will always write at `{log_dir}/ldk_node_latest.log`, which is a symlink to the
/// most recent log file, which is created and timestamped at initialization.
Filesystem {
/// The absolute path where logs are stored.
log_file_path: String,
/// The level at which we log messages.
///
/// Any messages below this level will be excluded from the logs.
log_level: LogLevel,
},
/// A custom logger.
Custom(std::sync::Arc<LdkNodeLogger>),
pub struct LoggerConfig {
/// Writer configuration.
pub writer: WriterConfig,
/// Formatter configuration.
pub formatter: FormatterConfig,
}

impl Default for LoggerConfig {
fn default() -> Self {
Self { writer: WriterConfig::default(), formatter: FormatterConfig::default() }
}
}

/// Logger formatter configuration.
#[derive(Debug, Clone)]
pub struct FormatterConfig {
/// Specifies if timestamps should be included in the log messages.
pub include_timestamp: bool,
/// Specifies timestamp format , e.g., "%Y-%m-%d %H:%M:%S".
pub timestamp_format: Option<String>,
/// Specifies if log levels should be included in the log messages.
pub include_level: bool,
/// Specifies the template for log message format, e.g., "{timestamp} [{level}] {message}".
pub message_template: Option<String>,
}

impl Default for LoggingConfig {
impl Default for FormatterConfig {
fn default() -> Self {
Self::Filesystem {
log_file_path: format!("{}/{}", DEFAULT_STORAGE_DIR_PATH, "ldk_node.log"),
log_level: DEFAULT_LOG_LEVEL,
Self {
include_timestamp: true,
timestamp_format: Some("%Y-%m-%d %H:%M:%S".to_string()),
include_level: true,
message_template: Some(
"{timestamp} {level} [{module_path}:{line}] {message}\n".to_string(),
),
}
}
}

/// Logger writer configuration.
#[derive(Debug, Clone)]
pub struct WriterConfig {
/// Writer type for the logger.
pub writer_type: WriterType,
}

impl Default for WriterConfig {
fn default() -> Self {
WriterConfig {
writer_type: WriterType::File(FileWriterConfig::new(
DEFAULT_LOG_FILE_PATH,
DEFAULT_LOG_LEVEL,
)),
}
}
}

/// Log writer configuration type.
#[derive(Debug, Clone)]
pub enum WriterType {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this the internal config object mentioned above, but it should live in builder.rs and should be named accordingly (e.g., LoggingConfig, LogWriterConfig, etc.).

/// Wraps configuration options for logging to the filesystem.
File(FileWriterConfig),
/// Wraps configuration options for relaying logs to [`log`].
LogRelay(LogRelayWriterConfig),
/// Wraps configuration options for relaying logs to a custom logger.
Custom(CustomWriterConfig),
}

/// Configuration for writing to the filesystem.
#[derive(Debug, Clone)]
pub struct FileWriterConfig {
/// Specifies the file path for the logs.
pub log_file_path: String,
/// Specifies the log level.
pub level: Level,
}

impl FileWriterConfig {
/// Creates a new configuration given the path to the log file
/// and the log level.
pub fn new(log_file_path: &str, level: Level) -> Self {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't need a constructor.

Self { log_file_path: log_file_path.to_string(), level }
}
}

/// Configuration options for [`log`]'s writer.
#[derive(Debug, Clone)]
pub struct LogRelayWriterConfig {
/// Specifies the log level.
pub level: Level,
}

/// Configuration options for a custom log writer.
#[derive(Debug, Clone)]
pub struct CustomWriterConfig {
/// Pointer to any custom log writer.
pub inner: Arc<dyn LogWriter + Send + Sync>,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't live in the public API config object, but just as a field in the (to be renamed) WriterType.

/// Specifies the log level.
pub level: Level,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the custom writer decide how to filter for level? I.e., do we really need CustomWriterConfig at all?

}

/// Configuration options pertaining to 'Anchor' channels, i.e., channels for which the
/// `option_anchors_zero_fee_htlc_tx` channel type is negotiated.
///
Expand Down
Loading