-
Notifications
You must be signed in to change notification settings - Fork 113
feat: add customizable logging system #401
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
1. Rename FilesystemLogger to LdkNodeLogger. 2. Make LdkNodeLogger technically customizable, retain default behavior. 3. Add customizable logging to configuration.
1. Remove left-over log_dir & log_file_path related fields from Config 2. Rename log_dir to log_file_path 3. Update the creation of new FileWriter to handle recursive parent directory 4. Fix integration tests
- Creates a LogWriter interface for different writers to write logs to their preferred destinations. These destinations could be either the filesystem or another logger (e.g. custom logger or any that implements log's facade. - The writer and formatter of LdkNodeLogger can be created by configurable options.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for looking into this! Here is a first round of comments.
Generally, I would have preferred a clean start rather than basing it off #393, since, as discussed there, the chosen approach isn't really bindings compatible and breaks a few of our LDK Node-internal preexisting idioms. That said, happy to continue the work in this PR. However, please try to ensure to have commits be discrete changes that always compile, and if possible avoid touching parts of the code again in later commits as it makes reviewing and understanding whats going a lot harder. To this end, you might want to squash and then split out commits for the custom writer and log parts.
|
|
||
| pub(crate) struct FilesystemLogger { | ||
| file_path: String, | ||
| pub struct LdkNodeLogger { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's drop the LdkNode prefix please, as we also don't prefix other objects. This could just be Logger (although that would mean we'd need to refer to the upstream trait as LdkLogger as we do with others, e.g., LdkFeeEstimator), or find another suitable name that capture its properties.
src/logger.rs
Outdated
| file_path: String, | ||
| pub struct LdkNodeLogger { | ||
| level: Level, | ||
| formatter: Box<dyn Fn(&Record) -> String + Send + Sync>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if it's worth introducing a separate heap object for this. Let's just not for now, and re-add it if we really find use for it.
src/config.rs
Outdated
| pub log_file_path: Option<String>, | ||
| /// In the default configuration logs can be found in the `logs` subdirectory in | ||
| /// [`Config::storage_dir_path`], and the log level is set to [`DEFAULT_LOG_LEVEL`]. | ||
| pub logging_config: LoggingConfig, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned in the original PR, we can't do this as it likely won't be really compatible with bindings and also doesn't match how we handle other things.
Rather, we'd need to add three builder methods to allow configuring the three modes:
a) set_logger_file/set_logger_filesystem taking a FilesystemLogger config object allowing to set loglevel and path (also exposed in the bindings builder)
b) set_logger_facade to use the log facade
c) set_logger_custom taking an Arc<dyn LogWriter + Send + Sync> (also exposed in the bindings builder)
That said, we'd likely want to keep something like LoggingConfig as an internal config object, similar to ChainSourceConfig, EntropySourceConfig, etc.
That is, the API would be controlled by Builder methods, but the 'state' is kept in that object and used to setup in Builder::build.
src/config.rs
Outdated
| /// | ||
| /// If set to `None`, logs can be found in `ldk_node.log` in the [`Config::storage_dir_path`] | ||
| /// directory. | ||
| pub log_file_path: Option<String>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be dropped/moved, too, as it only makes sense for the filesystem writer.
src/logger.rs
Outdated
| pub struct LdkNodeLogger { | ||
| level: Level, | ||
| formatter: Box<dyn Fn(&Record) -> String + Send + Sync>, | ||
| writer: Box<dyn Fn(&String) + Send + Sync>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll need to expose a LogWriter trait that can be used for custom loggers exposed via bindings (see https://mozilla.github.io/uniffi-rs/0.27/udl/interfaces.html#exposing-traits-as-interfaces)
|
|
||
| /// Log writer configuration type. | ||
| #[derive(Debug, Clone)] | ||
| pub enum WriterType { |
There was a problem hiding this comment.
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.).
| 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 { |
There was a problem hiding this comment.
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.
| #[derive(Debug, Clone)] | ||
| pub struct CustomWriterConfig { | ||
| /// Pointer to any custom log writer. | ||
| pub inner: Arc<dyn LogWriter + Send + Sync>, |
There was a problem hiding this comment.
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.
| /// Pointer to any custom log writer. | ||
| pub inner: Arc<dyn LogWriter + Send + Sync>, | ||
| /// Specifies the log level. | ||
| pub level: Level, |
There was a problem hiding this comment.
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?
|
|
||
| [features] | ||
| default = [] | ||
| log_relay = ["log"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't use any features in LDK Node so far (mostly to keep ~feature-parity of the Rust vs bindings API, for which everything needs to be configurable via the Builder), so please drop this and just take a non-optional dependency on log for now.
|
Closing this because, given the feedback, I also think it's best to have a clean slate. #407 addresses all the concerns here. |
Summary
This PR builds on #393 to add a customizable logging system.
What this PR does
Introduces a
LogWriterinterface, allowingWritervariants to handle log output destinations. The supportedWritervariants can now:logMakes
Writervariants configurable.Expose
LogWriterto bindings (pending).Test logging to different destinations.
Related Issue
loggerinterface #309