-
Notifications
You must be signed in to change notification settings - Fork 912
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
lightningd/log: Improve logging to handle multi-line messages #7944
base: master
Are you sure you want to change the base?
lightningd/log: Improve logging to handle multi-line messages #7944
Conversation
70e99c1
to
62ed812
Compare
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.
Nice work!
Hey @rustyrussell , I made some modifications based on your feedback. Could you please check if everything is covered, or if I need to check anything further? |
Hey @rustyrussell, I tried debugging this memory leak issue in CI but couldn't understand the root cause. Could you point me to some documentation that explains how Core Lightning handles memory leaks? Thanks! |
c83501c
to
df4f617
Compare
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.
Looking much better!
lightningd/log.c
Outdated
struct log_entry *l = new_log_entry(log, level, node_id); | ||
|
||
/* Split to lines and log them separately. */ | ||
for (size_t j = 0; lines[j]; j++) { | ||
l->log = tal_strdup(log, lines[j]); | ||
l->log = strdup(log_msg); | ||
size_t log_len = strlen(l->log); | ||
|
||
/* Sanitize any non-printable characters, and replace with '?' | ||
*/ | ||
size_t line_len = strlen(l->log); | ||
for (size_t i = 0; i < line_len; i++) | ||
for (size_t i = 0; i < log_len; i++) | ||
if (l->log[i] < ' ' || l->log[i] >= 0x7f) | ||
l->log[i] = '?'; | ||
|
||
maybe_print(log, l); | ||
maybe_notify_log(log, l); | ||
|
||
add_entry(log, &l); | ||
} | ||
|
||
if (call_notifier) |
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.
Extract this common code into a new function, rather than calling twice. Say "add_one_log_entry(log, level, nodeid, string)", which does new_log_entry, strdup, sanitize, maybe_print, maybe_notify_log, add_entry.
Then you can make the code a bit more optimal, and avoid json_escape if there are no escapes:
/* Nothing to escape: simple copy */
if (!strchr(log_msg, '\\'))
add_one_log_entry(log, level, nodeid, log_msg);
/* If it's weird, unescaping can fail */
else if ((unescaped_log = json_escape_unescape(tmpctx, (struct json_escape *)log_msg)) == NULL)
add_one_log_entry(log, level, nodeid, log_msg);
else {
char **lines = tal_strsplit(unescaped_log, unescaped_log, "\n", STR_EMPTY_OK);
/* Split to lines and log them separately. */
for (size_t i = 0; lines[i]; i++)
add_one_log_entry(log, level, nodeid, lines[i]);
}
lightningd/log.c
Outdated
log, json_escape_unescape(log, (struct json_escape *)log_msg), "\n", | ||
STR_NO_EMPTY); | ||
const char *unescaped_log = | ||
json_escape_unescape(NULL, (struct json_escape *)log_msg); |
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 is the cause of your leak, BTW. Every tal allocation is off some other tal allocation (or NULL). There's a special throwaway one called tmpctx
which automagically gets cleaned in the event loop. Since you used NULL here, and don't free it, it gets caught as a leak by our leak detection code (and it is!).
lightningd/log.c
Outdated
char *log_msg = NULL; | ||
|
||
/* This is WARN_UNUSED_RESULT, because everyone should somehow deal | ||
* with OOM, even though nobody does. */ | ||
if (vasprintf(&log_msg, fmt, ap) == -1) | ||
abort(); | ||
|
||
char **lines = tal_strsplit( | ||
log, json_escape_unescape(log, (struct json_escape *)log_msg), "\n", | ||
STR_NO_EMPTY); |
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.
STR_EMPTY_OK, since you want to log empty lines too I think?
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.
Now the output will look something like:
$ bitcoin-cli -rpcclienttimeout=60 echo 'hello world'
2024-12-19T06:39:55.230Z **BROKEN** plugin-bcli:
2024-12-19T06:39:55.230Z **BROKEN** plugin-bcli: Could not connect to bitcoind using bitcoin-cli. Is bitcoind running?
2024-12-19T06:39:55.230Z **BROKEN** plugin-bcli:
2024-12-19T06:39:55.230Z **BROKEN** plugin-bcli: Make sure you have bitcoind running and that bitcoin-cli is able to connect to bitcoind.
2024-12-19T06:39:55.230Z **BROKEN** plugin-bcli:
2024-12-19T06:39:55.230Z **BROKEN** plugin-bcli: You can verify that your Bitcoin Core installation is ready for use by running:
2024-12-19T06:39:55.230Z **BROKEN** plugin-bcli:
2024-12-19T06:39:55.230Z **BROKEN** plugin-bcli: $ bitcoin-cli -rpcclienttimeout=60 echo 'hello world'
2024-12-19T06:39:55.230Z INFO plugin-bcli: Killing plugin: exited before we sent init
The Bitcoin backend died.
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 think that's right, TBH?
Hey @rustyrussell, thank you for helping me out with this PR—it means a lot to me. I learned something new while working on this. One more thing: could you please let me know what configuration/tool the core-lightning codebase uses to format its C code? I noticed a lot of formatting changes happening on save. |
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 is looking really good now. Since you're a new contributor I've really nit-picked it, so there are two more trivial changes.
Also, squish it into a single commit please, so I can apply it!
lightningd/log.c
Outdated
@@ -558,70 +558,60 @@ static void maybe_notify_log(struct logger *log, | |||
notify_log(log->log_book->ld, l); | |||
} | |||
|
|||
static void add_one_log_entry(struct logger *log, enum log_level level, | |||
const struct node_id *node_id, bool call_notifier, | |||
char *log_msg) |
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.
const char *
- we always use const when we can (it's a C bug that it's not the default!)
lightningd/log.c
Outdated
size_t log_len = strlen(l->log); | ||
|
||
/* Sanitize any non-printable characters, and replace with '?' | ||
*/ | ||
for (size_t i = 0; i < log_len; i++) |
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.
Drop log_len, use log_msg[i] != '\0'
?
I use emacs, so that just does it all for me :( |
Changelog-Added: Improved logging format in `lightningd/log` to handle multi-line messages by unescaping '\n' and logging each line separately. Signed-off-by: Nishant Bansal <nishant.bansal.282003@gmail.com> lightningd/log: Improve log handling Changelog-Added: Improved log handling to save memory. Signed-off-by: Nishant Bansal <nishant.bansal.282003@gmail.com> lightningd/log: Refactor code for logging Changelog-Added: Refactored code for log handling. Signed-off-by: Nishant Bansal <nishant.bansal.282003@gmail.com>
499365f
to
abf30f5
Compare
Changelog-Added: Improved logging format in
lightningd/log
to handle multi-line messages by unescaping '\n' and logging each line separately.Important
24.11 FREEZE NOVEMBER 7TH: Non-bugfix PRs not ready by this date will wait for 25.02.
Fixes: #4912
Log-Output:
Checklist
Before submitting the PR, ensure the following tasks are completed. If an item is not applicable to your PR, please mark it as checked: