@@ -23,6 +23,9 @@ use log::LevelFilter;
2323use serde:: { Deserialize , Serialize } ;
2424
2525const DEFAULT_GRPC_SERVICE_ADDRESS : & str = "127.0.0.1:3536" ;
26+ const DEFAULT_LOG_MAX_SIZE_MB : u64 = 50 ;
27+ const DEFAULT_LOG_ROTATION_INTERVAL_HOURS : u64 = 24 ;
28+ const DEFAULT_LOG_MAX_FILES : usize = 5 ;
2629
2730#[ cfg( not( test) ) ]
2831const DEFAULT_CONFIG_FILE : & str = "config.toml" ;
@@ -56,6 +59,10 @@ pub struct Config {
5659 pub lsps2_service_config : Option < LSPS2ServiceConfig > ,
5760 pub log_level : LevelFilter ,
5861 pub log_file_path : Option < String > ,
62+ pub log_max_size_bytes : usize ,
63+ pub log_rotation_interval_secs : u64 ,
64+ pub log_max_files : usize ,
65+ pub log_to_file : bool ,
5966 pub pathfinding_scores_source_url : Option < String > ,
6067 pub metrics_enabled : bool ,
6168 pub poll_metrics_interval : Option < u64 > ,
@@ -110,6 +117,10 @@ struct ConfigBuilder {
110117 lsps2 : Option < LiquidityConfig > ,
111118 log_level : Option < String > ,
112119 log_file_path : Option < String > ,
120+ log_max_size_mb : Option < u64 > ,
121+ log_rotation_interval_hours : Option < u64 > ,
122+ log_max_files : Option < usize > ,
123+ log_to_file : Option < bool > ,
113124 pathfinding_scores_source_url : Option < String > ,
114125 metrics_enabled : Option < bool > ,
115126 poll_metrics_interval : Option < u64 > ,
@@ -158,6 +169,11 @@ impl ConfigBuilder {
158169 if let Some ( log) = toml. log {
159170 self . log_level = log. level . or ( self . log_level . clone ( ) ) ;
160171 self . log_file_path = log. file . or ( self . log_file_path . clone ( ) ) ;
172+ self . log_max_size_mb = log. max_size_mb . or ( self . log_max_size_mb ) ;
173+ self . log_rotation_interval_hours =
174+ log. rotation_interval_hours . or ( self . log_rotation_interval_hours ) ;
175+ self . log_max_files = log. max_files . or ( self . log_max_files ) ;
176+ self . log_to_file = log. log_to_file . or ( self . log_to_file ) ;
161177 }
162178
163179 if let Some ( liquidity) = toml. liquidity {
@@ -249,6 +265,22 @@ impl ConfigBuilder {
249265 if let Some ( tor_proxy_address) = & args. tor_proxy_address {
250266 self . tor_proxy_address = Some ( tor_proxy_address. clone ( ) ) ;
251267 }
268+
269+ if let Some ( log_max_size_mb) = args. log_max_size_mb {
270+ self . log_max_size_mb = Some ( log_max_size_mb) ;
271+ }
272+
273+ if let Some ( log_rotation_interval_hours) = args. log_rotation_interval_hours {
274+ self . log_rotation_interval_hours = Some ( log_rotation_interval_hours) ;
275+ }
276+
277+ if let Some ( log_max_files) = args. log_max_files {
278+ self . log_max_files = Some ( log_max_files) ;
279+ }
280+
281+ if let Some ( log_file_path) = args. log_to_file {
282+ self . log_to_file = Some ( log_file_path) ;
283+ }
252284 }
253285
254286 fn build ( self ) -> io:: Result < Config > {
@@ -358,6 +390,14 @@ impl ConfigBuilder {
358390 . transpose ( ) ?
359391 . unwrap_or ( LevelFilter :: Debug ) ;
360392
393+ let log_max_size_bytes =
394+ self . log_max_size_mb . unwrap_or ( DEFAULT_LOG_MAX_SIZE_MB ) * 1024 * 1024 ;
395+ let log_rotation_interval_secs =
396+ self . log_rotation_interval_hours . unwrap_or ( DEFAULT_LOG_ROTATION_INTERVAL_HOURS )
397+ * 60 * 60 ;
398+ let log_max_files = self . log_max_files . unwrap_or ( DEFAULT_LOG_MAX_FILES ) ;
399+ let log_to_file = self . log_to_file . unwrap_or ( true ) ;
400+
361401 let lsps2_client_config = self
362402 . lsps2
363403 . as_ref ( )
@@ -428,6 +468,10 @@ impl ConfigBuilder {
428468 lsps2_service_config,
429469 log_level,
430470 log_file_path : self . log_file_path ,
471+ log_max_size_bytes : log_max_size_bytes as usize ,
472+ log_rotation_interval_secs,
473+ log_max_files,
474+ log_to_file,
431475 pathfinding_scores_source_url,
432476 metrics_enabled,
433477 poll_metrics_interval,
@@ -497,6 +541,10 @@ struct EsploraConfig {
497541struct LogConfig {
498542 level : Option < String > ,
499543 file : Option < String > ,
544+ max_size_mb : Option < u64 > ,
545+ rotation_interval_hours : Option < u64 > ,
546+ max_files : Option < usize > ,
547+ log_to_file : Option < bool > ,
500548}
501549
502550#[ derive( Deserialize , Serialize ) ]
@@ -733,6 +781,34 @@ pub struct ArgsConfig {
733781 ) ]
734782 node_alias : Option < String > ,
735783
784+ #[ arg(
785+ long,
786+ env = "LDK_SERVER_LOG_MAX_SIZE_MB" ,
787+ help = "The maximum size of the log file in MB before rotation. Defaults to 50MB."
788+ ) ]
789+ log_max_size_mb : Option < u64 > ,
790+
791+ #[ arg(
792+ long,
793+ env = "LDK_SERVER_LOG_ROTATION_INTERVAL_HOURS" ,
794+ help = "The maximum age of the log file in hours before rotation. Defaults to 24h."
795+ ) ]
796+ log_rotation_interval_hours : Option < u64 > ,
797+
798+ #[ arg(
799+ long,
800+ env = "LDK_SERVER_LOG_MAX_FILES" ,
801+ help = "The maximum number of rotated log files to keep. Defaults to 5."
802+ ) ]
803+ log_max_files : Option < usize > ,
804+
805+ #[ arg(
806+ long,
807+ env = "LDK_SERVER_LOG_TO_FILE" ,
808+ help = "The option to enable logging to a file. Defaults to true. If false, logging to file is disabled."
809+ ) ]
810+ log_to_file : Option < bool > ,
811+
736812 #[ arg(
737813 long,
738814 env = "LDK_SERVER_BITCOIND_RPC_ADDRESS" ,
@@ -896,6 +972,10 @@ mod tests {
896972 [log]
897973 level = "Trace"
898974 file = "/var/log/ldk-server.log"
975+ max_size_mb = 50
976+ rotation_interval_hours = 24
977+ max_files = 5
978+ log_to_file = true
899979
900980 [bitcoind]
901981 rpc_address = "127.0.0.1:8332"
@@ -941,6 +1021,10 @@ mod tests {
9411021 metrics_username : None ,
9421022 metrics_password : None ,
9431023 tor_proxy_address : None ,
1024+ log_to_file : Some ( true ) ,
1025+ log_max_size_mb : Some ( 50 ) ,
1026+ log_rotation_interval_hours : Some ( 24 ) ,
1027+ log_max_files : Some ( 5 ) ,
9441028 }
9451029 }
9461030
@@ -962,6 +1046,10 @@ mod tests {
9621046 metrics_username : None ,
9631047 metrics_password : None ,
9641048 tor_proxy_address : None ,
1049+ log_to_file : Some ( true ) ,
1050+ log_max_size_mb : None ,
1051+ log_rotation_interval_hours : None ,
1052+ log_max_files : None ,
9651053 }
9661054 }
9671055
@@ -1029,6 +1117,10 @@ mod tests {
10291117 } ) ,
10301118 log_level : LevelFilter :: Trace ,
10311119 log_file_path : Some ( "/var/log/ldk-server.log" . to_string ( ) ) ,
1120+ log_max_size_bytes : 50 * 1024 * 1024 ,
1121+ log_rotation_interval_secs : 24 * 60 * 60 ,
1122+ log_max_files : 5 ,
1123+ log_to_file : true ,
10321124 pathfinding_scores_source_url : None ,
10331125 metrics_enabled : false ,
10341126 poll_metrics_interval : None ,
@@ -1344,6 +1436,10 @@ mod tests {
13441436 metrics_password : None ,
13451437 tor_config : None ,
13461438 hrn_config : HumanReadableNamesConfig :: default ( ) ,
1439+ log_max_size_bytes : 50 * 1024 * 1024 ,
1440+ log_rotation_interval_secs : 24 * 60 * 60 ,
1441+ log_max_files : 5 ,
1442+ log_to_file : true ,
13471443 } ;
13481444
13491445 assert_eq ! ( config. listening_addrs, expected. listening_addrs) ;
@@ -1357,6 +1453,10 @@ mod tests {
13571453 assert_eq ! ( config. pathfinding_scores_source_url, expected. pathfinding_scores_source_url) ;
13581454 assert_eq ! ( config. metrics_enabled, expected. metrics_enabled) ;
13591455 assert_eq ! ( config. tor_config, expected. tor_config) ;
1456+ assert_eq ! ( config. log_max_size_bytes, expected. log_max_size_bytes) ;
1457+ assert_eq ! ( config. log_rotation_interval_secs, expected. log_rotation_interval_secs) ;
1458+ assert_eq ! ( config. log_max_files, expected. log_max_files) ;
1459+ assert_eq ! ( config. log_to_file, expected. log_to_file) ;
13601460 }
13611461
13621462 #[ test]
@@ -1454,6 +1554,10 @@ mod tests {
14541554 proxy_address : SocketAddress :: from_str ( "127.0.0.1:9050" ) . unwrap ( ) ,
14551555 } ) ,
14561556 hrn_config : HumanReadableNamesConfig :: default ( ) ,
1557+ log_max_size_bytes : 50 * 1024 * 1024 ,
1558+ log_rotation_interval_secs : 24 * 60 * 60 ,
1559+ log_max_files : 5 ,
1560+ log_to_file : false ,
14571561 } ;
14581562
14591563 assert_eq ! ( config. listening_addrs, expected. listening_addrs) ;
0 commit comments