Skip to content

Commit c182ca3

Browse files
committed
Add configurable log level and log file
Before we were dropping all our logs on the floor besides a few printlns in the code. This implements a logger for the log facade that writes logs to the console as well as to the log file. We also add to the config options for setting the log file and log level.
1 parent 281b5e8 commit c182ca3

7 files changed

Lines changed: 281 additions & 28 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ldk-server/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ rusqlite = { version = "0.31.0", features = ["bundled"] }
1818
rand = { version = "0.8.5", default-features = false }
1919
async-trait = { version = "0.1.85", default-features = false }
2020
toml = { version = "0.8.9", default-features = false, features = ["parse"] }
21+
chrono = { version = "0.4", default-features = false, features = ["clock"] }
22+
log = "0.4.28"
2123

2224
# Required for RabittMQ based EventPublisher. Only enabled for `events-rabbitmq` feature.
2325
lapin = { version = "2.4.0", features = ["rustls"], default-features = false, optional = true }

ldk-server/ldk-server-config.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ rest_service_address = "127.0.0.1:3002" # LDK Server REST address
88
[storage.disk]
99
dir_path = "/tmp/ldk-server/" # Path for LDK and BDK data persistence
1010

11+
[log]
12+
level = "Debug" # Log level (Error, Warn, Info, Debug, Trace)
13+
file_path = "/tmp/ldk-server/ldk-server.log" # Log file path
1114

1215
# Must set either bitcoind or esplora settings, but not both
1316

ldk-server/src/main.rs

Lines changed: 63 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,15 @@ use crate::io::persist::{
2525
PAYMENTS_PERSISTENCE_SECONDARY_NAMESPACE,
2626
};
2727
use crate::util::config::{load_config, ChainSource};
28+
use crate::util::logger::ServerLogger;
2829
use crate::util::proto_adapter::{forwarded_payment_to_proto, payment_to_proto};
2930
use hex::DisplayHex;
3031
use ldk_node::config::Config;
3132
use ldk_node::lightning::ln::channelmanager::PaymentId;
3233
use ldk_server_protos::events;
3334
use ldk_server_protos::events::{event_envelope, EventEnvelope};
3435
use ldk_server_protos::types::Payment;
36+
use log::{error, info};
3537
use prost::Message;
3638
use rand::Rng;
3739
use std::fs;
@@ -70,6 +72,25 @@ fn main() {
7072
},
7173
};
7274

75+
let log_file_path = config_file.log_file_path.map(|p| PathBuf::from(p)).unwrap_or_else(|| {
76+
let mut default_log_path = PathBuf::from(&config_file.storage_dir_path);
77+
default_log_path.push("ldk-server.log");
78+
default_log_path
79+
});
80+
81+
if log_file_path == PathBuf::from(&config_file.storage_dir_path) {
82+
eprintln!("Log file path cannot be the same as storage directory path.");
83+
std::process::exit(-1);
84+
}
85+
86+
let logger = match ServerLogger::init(config_file.log_level, &log_file_path) {
87+
Ok(logger) => logger,
88+
Err(e) => {
89+
eprintln!("Failed to initialize logger: {e}");
90+
std::process::exit(-1);
91+
},
92+
};
93+
7394
ldk_node_config.storage_dir_path = config_file.storage_dir_path.clone();
7495
ldk_node_config.listening_addresses = Some(vec![config_file.listening_addr]);
7596
ldk_node_config.network = config_file.network;
@@ -79,7 +100,7 @@ fn main() {
79100

80101
if let Some(alias) = config_file.alias {
81102
if let Err(e) = builder.set_node_alias(alias.to_string()) {
82-
eprintln!("Failed to set node alias: {e}");
103+
error!("Failed to set node alias: {e}");
83104
std::process::exit(-1);
84105
}
85106
}
@@ -107,7 +128,7 @@ fn main() {
107128
let runtime = match tokio::runtime::Builder::new_multi_thread().enable_all().build() {
108129
Ok(runtime) => Arc::new(runtime),
109130
Err(e) => {
110-
eprintln!("Failed to setup tokio runtime: {}", e);
131+
error!("Failed to setup tokio runtime: {e}");
111132
std::process::exit(-1);
112133
},
113134
};
@@ -117,7 +138,7 @@ fn main() {
117138
let node = match builder.build() {
118139
Ok(node) => Arc::new(node),
119140
Err(e) => {
120-
eprintln!("Failed to build LDK Node: {}", e);
141+
error!("Failed to build LDK Node: {e}");
121142
std::process::exit(-1);
122143
},
123144
};
@@ -126,7 +147,7 @@ fn main() {
126147
Arc::new(match SqliteStore::new(PathBuf::from(config_file.storage_dir_path), None, None) {
127148
Ok(store) => store,
128149
Err(e) => {
129-
eprintln!("Failed to create SqliteStore: {:?}", e);
150+
error!("Failed to create SqliteStore: {e:?}");
130151
std::process::exit(-1);
131152
},
132153
});
@@ -142,26 +163,35 @@ fn main() {
142163
Arc::new(RabbitMqEventPublisher::new(rabbitmq_config))
143164
};
144165

145-
println!("Starting up...");
166+
info!("Starting up...");
146167
match node.start() {
147168
Ok(()) => {},
148169
Err(e) => {
149-
eprintln!("Failed to start up LDK Node: {}", e);
170+
error!("Failed to start up LDK Node: {e}");
150171
std::process::exit(-1);
151172
},
152173
}
153174

154-
println!(
175+
info!(
155176
"CONNECTION_STRING: {}@{}",
156177
node.node_id(),
157178
node.config().listening_addresses.as_ref().unwrap().first().unwrap()
158179
);
159180

160181
runtime.block_on(async {
182+
// Register SIGHUP handler for log rotation
183+
let mut sighup_stream = match tokio::signal::unix::signal(SignalKind::hangup()) {
184+
Ok(stream) => stream,
185+
Err(e) => {
186+
error!("Failed to register SIGHUP handler: {e}");
187+
std::process::exit(-1);
188+
}
189+
};
190+
161191
let mut sigterm_stream = match tokio::signal::unix::signal(SignalKind::terminate()) {
162192
Ok(stream) => stream,
163193
Err(e) => {
164-
println!("Failed to register for SIGTERM stream: {}", e);
194+
error!("Failed to register for SIGTERM stream: {e}");
165195
std::process::exit(-1);
166196
}
167197
};
@@ -174,25 +204,25 @@ fn main() {
174204
event = event_node.next_event_async() => {
175205
match event {
176206
Event::ChannelPending { channel_id, counterparty_node_id, .. } => {
177-
println!(
207+
info!(
178208
"CHANNEL_PENDING: {} from counterparty {}",
179209
channel_id, counterparty_node_id
180210
);
181211
if let Err(e) = event_node.event_handled() {
182-
eprintln!("Failed to mark event as handled: {e}");
212+
error!("Failed to mark event as handled: {e}");
183213
}
184214
},
185215
Event::ChannelReady { channel_id, counterparty_node_id, .. } => {
186-
println!(
216+
info!(
187217
"CHANNEL_READY: {} from counterparty {:?}",
188218
channel_id, counterparty_node_id
189219
);
190220
if let Err(e) = event_node.event_handled() {
191-
eprintln!("Failed to mark event as handled: {e}");
221+
error!("Failed to mark event as handled: {e}");
192222
}
193223
},
194224
Event::PaymentReceived { payment_id, payment_hash, amount_msat, .. } => {
195-
println!(
225+
info!(
196226
"PAYMENT_RECEIVED: with id {:?}, hash {}, amount_msat {}",
197227
payment_id, payment_hash, amount_msat
198228
);
@@ -233,7 +263,7 @@ fn main() {
233263
let payment = payment_to_proto(payment_details);
234264
upsert_payment_details(&event_node, Arc::clone(&paginated_store), &payment);
235265
} else {
236-
eprintln!("Unable to find payment with paymentId: {}", payment_id.to_string());
266+
error!("Unable to find payment with paymentId: {}", payment_id.to_string());
237267
}
238268
},
239269
Event::PaymentForwarded {
@@ -249,7 +279,7 @@ fn main() {
249279
outbound_amount_forwarded_msat
250280
} => {
251281

252-
println!("PAYMENT_FORWARDED: with outbound_amount_forwarded_msat {}, total_fee_earned_msat: {}, inbound channel: {}, outbound channel: {}",
282+
info!("PAYMENT_FORWARDED: with outbound_amount_forwarded_msat {}, total_fee_earned_msat: {}, inbound channel: {}, outbound channel: {}",
253283
outbound_amount_forwarded_msat.unwrap_or(0), total_fee_earned_msat.unwrap_or(0), prev_channel_id, next_channel_id
254284
);
255285

@@ -281,7 +311,7 @@ fn main() {
281311
}).await {
282312
Ok(_) => {},
283313
Err(e) => {
284-
println!("Failed to publish 'PaymentForwarded' event: {}", e);
314+
error!("Failed to publish 'PaymentForwarded' event: {}", e);
285315
continue;
286316
}
287317
};
@@ -293,17 +323,17 @@ fn main() {
293323
) {
294324
Ok(_) => {
295325
if let Err(e) = event_node.event_handled() {
296-
eprintln!("Failed to mark event as handled: {e}");
326+
error!("Failed to mark event as handled: {e}");
297327
}
298328
}
299329
Err(e) => {
300-
println!("Failed to write forwarded payment to persistence: {}", e);
330+
error!("Failed to write forwarded payment to persistence: {}", e);
301331
}
302332
}
303333
},
304334
_ => {
305335
if let Err(e) = event_node.event_handled() {
306-
eprintln!("Failed to mark event as handled: {e}");
336+
error!("Failed to mark event as handled: {e}");
307337
}
308338
},
309339
}
@@ -315,27 +345,32 @@ fn main() {
315345
let node_service = NodeService::new(Arc::clone(&node), Arc::clone(&paginated_store));
316346
runtime.spawn(async move {
317347
if let Err(err) = http1::Builder::new().serve_connection(io_stream, node_service).await {
318-
eprintln!("Failed to serve connection: {}", err);
348+
error!("Failed to serve connection: {}", err);
319349
}
320350
});
321351
},
322-
Err(e) => eprintln!("Failed to accept connection: {}", e),
352+
Err(e) => error!("Failed to accept connection: {}", e),
323353
}
324354
}
325355
_ = tokio::signal::ctrl_c() => {
326-
println!("Received CTRL-C, shutting down..");
356+
info!("Received CTRL-C, shutting down..");
327357
break;
328358
}
359+
_ = sighup_stream.recv() => {
360+
if let Err(e) = logger.reopen() {
361+
error!("Failed to reopen log file on SIGHUP: {e}");
362+
}
363+
}
329364
_ = sigterm_stream.recv() => {
330-
println!("Received SIGTERM, shutting down..");
365+
info!("Received SIGTERM, shutting down..");
331366
break;
332367
}
333368
}
334369
}
335370
});
336371

337372
node.stop().expect("Shutdown should always succeed.");
338-
println!("Shutdown complete..");
373+
info!("Shutdown complete..");
339374
}
340375

341376
async fn publish_event_and_upsert_payment(
@@ -351,14 +386,14 @@ async fn publish_event_and_upsert_payment(
351386
match event_publisher.publish(EventEnvelope { event: Some(event) }).await {
352387
Ok(_) => {},
353388
Err(e) => {
354-
println!("Failed to publish '{}' event, : {}", event_name, e);
389+
error!("Failed to publish '{event_name}' event, : {e}");
355390
return;
356391
},
357392
};
358393

359394
upsert_payment_details(event_node, Arc::clone(&paginated_store), &payment);
360395
} else {
361-
eprintln!("Unable to find payment with paymentId: {}", payment_id);
396+
error!("Unable to find payment with paymentId: {payment_id}");
362397
}
363398
}
364399

@@ -377,11 +412,11 @@ fn upsert_payment_details(
377412
) {
378413
Ok(_) => {
379414
if let Err(e) = event_node.event_handled() {
380-
eprintln!("Failed to mark event as handled: {e}");
415+
error!("Failed to mark event as handled: {e}");
381416
}
382417
},
383418
Err(e) => {
384-
eprintln!("Failed to write payment to persistence: {}", e);
419+
error!("Failed to write payment to persistence: {e}");
385420
},
386421
}
387422
}

0 commit comments

Comments
 (0)