Cleanup logging - #965

Merged
TheBlueMatt merged 14 commits into
lightningdevkit:mainfrom
TheBlueMatt:2021-06-log-cleanups
Jun 29, 2021
Merged

Cleanup logging#965
TheBlueMatt merged 14 commits into
lightningdevkit:mainfrom
TheBlueMatt:2021-06-log-cleanups

Conversation

@TheBlueMatt

@TheBlueMattTheBlueMatt commented Jun 23, 2021

Copy link
Copy Markdown
Collaborator

This is the result of going through almost all of the logging in the library, as well as feedback from a few different users over the past month or so noting lack of logging in a few places.

  • I still need to go through onchaintx.rs and package.rs, but otherwise I think this is good.

These patches have been merged upstream and are in releases now so
we don't need to patch them locally.
When a peer sends us the routing graph, it may include gossip
messages for our channels, despite it not being a party to them.
This is completely fine, but we currently print a somewhat-scary
looking log messages in these cases, eg:
```
ERROR [lightning::ln::channelmanager:4104] Got a message for a channel from the wrong node!
TRACE [lightning::ln::peer_handler:1267] Handling SendErrorMessage HandleError event in peer_handler for node ... with message Got a message for a channel from the wrong node!
```
Instead, we should simply not consider this an "error" condition
and stay silent.
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from f83fa1a to 4a87105CompareJune 23, 2021 16:00
@codecov

codecovBot commented Jun 23, 2021

Copy link
Copy Markdown

Codecov Report

Merging #965 (6d98aed) into main (073afbb) will increase coverage by 1.08%.
The diff coverage is 73.09%.

Impacted file tree graph

@@ Coverage Diff @@## main #965 +/- ##
==========================================
+ Coverage 90.66% 91.75% +1.08% 
==========================================
Files 60 60 Lines 30407 34788 +4381 ==========================================
+ Hits 27568 31919 +4351 - Misses 2839 2869 +30 
Impacted FilesCoverage Δ
lightning/src/ln/msgs.rs90.60% <0.00%> (+2.25%)⬆️
lightning/src/ln/peer_handler.rs46.73% <12.50%> (+0.22%)⬆️
lightning/src/ln/wire.rs53.53% <50.00%> (-10.57%)⬇️
lightning/src/routing/network_graph.rs91.76% <50.00%> (-0.22%)⬇️
lightning/src/util/macro_logger.rs87.87% <50.00%> (-1.19%)⬇️
lightning/src/chain/package.rs93.04% <83.33%> (+0.74%)⬆️
lightning/src/ln/channelmanager.rs86.18% <83.33%> (+2.32%)⬆️
lightning/src/chain/channelmonitor.rs91.90% <100.00%> (+1.14%)⬆️
lightning/src/chain/onchaintx.rs94.19% <100.00%> (+0.04%)⬆️
lightning/src/ln/channel.rs92.51% <100.00%> (+4.22%)⬆️
... and 16 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 073afbb...6d98aed. Read the comment docs.

@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 4a87105 to edd0da5CompareJune 23, 2021 16:20
@TheBlueMattTheBlueMatt added this to the 0.0.99 milestone Jun 23, 2021

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for this cleanup :)

// a scary-looking error message and return Ok instead.
return Ok(());
}
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a channel_update for a channel from the wrong node - it shouldn't know about our private channels!".to_owned(), chan_id));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Though #949 blurs this assertion, a direct peer might learn a channel_update for outbound-from-us payments.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

#949 should only be sending the message directly to the channel counterparty, so I think its still correct. Its true we do tell other nodes about our private channels in invoices, but they still shouldn't remember that, nor should they ever have channel_updates for those messages. Do you have a suggestion for a different concrete wording?

@ariardariardJun 30, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think your comment is right if this peer is applying the same gossip policy than us ? Some weird LN client could not sort discovered gossips according to their sources and treat them uniformly, I don't think that's something the specification is covering (and IMHO it should be strongly opinionated on this).

So as a suggestion maybe prefix "Gossip policy: Got a channel_update for a channel from the wrong node - we consider it shouldn't know about this private channels!" ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

The specification is clear that you should not accept or forward a channel_update unless you've received the corresponding channel_announcement, which we will never generate signatures for, so it cannot exist.

log_error!(args.logger, " The ChannelMonitor for channel {} is at update_id {} but the ChannelManager is at update_id {}.",
log_bytes!(channel.channel_id()), monitor.get_latest_update_id(), channel.get_latest_monitor_update_id());
log_error!(args.logger, " The chain::Watch API *requires* that monitors are persisted durably before returning,");
log_error!(args.logger, " client applications must ensure that ChannelMonitor data is always available and the latest to avoid funds loss!");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Maybe add another line "You can search for a ChannelMonitor update_id matching the ChannelManager", otherwise what the user can do ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, isn't that included in the line two lines up The ChannelMonitor for channel {} is at update_id {} but the ChannelManager is at update_id {}.? I don't really think there is anything the user can do here, the application developer has a critical bug that may result/has resulted in funds loss, that bug needs to be resolved, and then maybe we can chat with them about how to deal directly with ChannelMonitors to close channels and create a new ChannelManager.

@ariardariardJun 30, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Right the update_id is already yielded. Maybe we could have a conventional message "This is a LDK API implementation bug : you can submit a bug report but ultimately solving the issue is on your side" ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

What do you think of #976 ?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Good to me

Comment threadlightning/src/ln/msgs.rs Outdated
IgnoreError,
/// The peer did something harmless (and expected) that we weren't able to meaningfully
/// process. Simply ignore.
IgnoreCommonError,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What do you think about HarmlessError/MinorError, a bit more meaningful w.r.t to IgnoreError ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, part of what I wanted to capture is that it is "common" in that it appears regularly. Ultimately that's the real difference between log_trace and log_debug - debug should still be readable, but trace you probably need to grep to get anything useful :). Maybe drop the Ignore part and just do ExpectedError?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The type indicates an action, though, so the naming is less meaningful without Ignore. Maybe use a single variant IgnoreAndLog with a severity parameter?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I really like that idea, will you kill me if I add a second type - there's a ton of Ignore references in the codebase and updating all of them in this PR seems like it would be a bit large. We can migrate to the explicit variant over time and then clean them all up when the repo is a bit quieter.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Done

Comment threadlightning/src/ln/channelmanager.rs Outdated

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice cleanup! Couldn't find any swapped args or anything

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/wire.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
IgnoreError,
/// The peer did something harmless (and expected) that we weren't able to meaningfully
/// process. Simply ignore.
IgnoreCommonError,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The type indicates an action, though, so the naming is less meaningful without Ignore. Maybe use a single variant IgnoreAndLog with a severity parameter?

Comment on lines +1537 to +1540
log_trace!(logger, "Checking funding_created tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} for channel {}.",
log_bytes!(sig.serialize_compact()[..]), log_bytes!(self.counterparty_funding_pubkey().serialize()),
encode::serialize_hex(&initial_commitment_bitcoin_tx.transaction), log_bytes!(sighash[..]),
encode::serialize_hex(&funding_script), log_bytes!(self.channel_id()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For some of these longer messages, I wonder if they would be easier to read if we logged a struct containing references to the data that implements Debug and used{:#?} to break across lines.

More thinking out loud. Feel free to ignore.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, good question! I wasn't aware that was a thing, but I'm a bit torn on it. I agree its pretty unreadable right now, but at the same time logging is an API not strictly a user-interface thing, so abstractly it feels weird to have linebreaks. More concretely, I currently grep the sample node logs pretty extensively to filter out verbose stuff, which moving towards inserting linebreaks would break. TRACE-level logging isn't really intended for direct human processing without some filtering, I think.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

FWIW, not sure how well supported this would be, but a log entry could theoretically contain new lines and the logger could write each entry separated by record separator control characters. Other loggers may log to a database or key-value store.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I still feel like that violates the principle of least-surprise - Users shouldn't be surprised that they have to do extra work to make our log entries "work" when writing to a file (the "common" use case IMO).

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/routing/router.rs Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch 3 times, most recently from bd6b560 to 15cc91aCompareJune 28, 2021 20:53
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Addressed all feedback, I think.

@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 15cc91a to 29991acCompareJune 28, 2021 20:59
Comment threadlightning/src/ln/peer_handler.rs Outdated
msgs::ErrorAction::IgnoreCommonError => {
log_trace!(self.logger, "Error handling message; ignoring: {}", e.err);
msgs::ErrorAction::IgnoreAndLog(level) => {
log_given_level!(self.logger, cmp::min(Level::Debug, level), "Error handling message; ignoring: {}", e.err);

@jkczyzjkczyzJun 29, 2021

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why is the cmp::min used? Would it make sense to write a custom macro for this so it doesn't need to be repeated elsewhere?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, I thought the "minimum level" there was pretty readable. I could move the cmp::min into the macro, but it felt readable and this is slightly more generic because it would let you do some match or if statement that sets the level?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

To rephrase my first question, why not just use level here? I don't quite understand why we want to use a lower level if IgnoreAndLog gives, say, Warn.

Hmm, I thought the "minimum level" there was pretty readable. I could move the cmp::min into the macro, but it felt readable and this is slightly more generic because it would let you do some match or if statement that sets the level?

I was saying to leave log_given_level as is and add another macro like log_debug_or_lower (or similarly named) to avoid a lot of boilerplate if this pattern will be common.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

To rephrase my first question, why not just use level here? I don't quite understand why we want to use a lower level if IgnoreAndLog gives, say, Warn.

Hmm, right, I guess we could? Its a bit strange to "warn" the user for an error that we "ignored", but I can just drop it.

I was saying to leave log_given_level as is and add another macro like log_debug_or_lower (or similarly named) to avoid a lot of boilerplate if this pattern will be common.

I mean we only handle the ErrorAction stuff in two places... :)

Comment threadlightning/src/util/logger.rs Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 29991ac to 7043607CompareJune 29, 2021 15:18
Comment threadlightning/src/util/logger.rs
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 7043607 to c37e76dCompareJune 29, 2021 16:02
// Note that if the pending_forward_status is not updated here, then it's because we're already failing
// the HTLC, i.e. its status is already set to failing.
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation");
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation in channel {}. Rebalancing is required.", log_bytes!(self.channel_id()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not a big deal but wish we could point people somewhere for expansion on "rebalancing is required" 🤔

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

We'll get there eventually :) #959

We had a client application which provided inconsistent monitor
state when deserializing a ChannelManager, resulting in opaque and
generic "InvalidData" deserialization failures. Instead, we log
some informative (and appropriately scary) warning messages in
such cases.
This makes our logging consistent and somewhat simplifies message
sending code in a few places.
This much more consistently logs information about messages
sent/received, including logging the full messages being
sent/received at the TRACE log level. Many other log messages which
are more often of interest were moved to the DEBUG log level.
For log entries which may have a variable level, we can't call an
arbitrary macro and need to be able to pass an explicit level. This
does so without breaking the compile-time disabling of certain log
levels.
Further, we "fix" the comparison order of log levels to make more
significant levels sort "higher", which implicitly makes more sense
than sorting "lower".
Finally, we remove the "Off" log level as no log entry should ever
be logged at the "Off" level - that would be nonsensical.
We very often receive duplicate gossip messages, which now causes us
to log at the DEBUG level, which is almost certainly not what a
user wants. Instead, we add a new form of ErrorAction which causes
us to only log at the TRACE level.
This updates a number of log sites in channel and channelmanager to
* Be a bit more verbose at the TRACE level,
* Move some error/useful messages to the ERROR/WARN/INFO level,
* Add new logs to always log once at the DEBUG level when we
send/receive a commitment_signed (with some extra data),
* Include the channel id being operated on in more log messages.
ChannelMonitor and related log entries can generally lean towards
being higher log levels than they necessarily need to be, as they
should be exceedingly rare, if only because they require
confirmation of an on-chain transaction.
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from c37e76d to 6d98aedCompareJune 29, 2021 19:36
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Squashed without changes:

$ git diff-tree -U1 c37e76da 6d98aeda
$

@TheBlueMatt
TheBlueMatt merged commit f472907 into lightningdevkit:mainJun 29, 2021
@ariard

Copy link
Copy Markdown

Post-merge Code Review ACK 6d98aed

+1 for the new ErrorAction::IgnoreAndLog API

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@TheBlueMatt@ariard@jkczyz@valentinewallace
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Cleanup logging - #965

Merged
TheBlueMatt merged 14 commits into
lightningdevkit:mainfrom
TheBlueMatt:2021-06-log-cleanups
Jun 29, 2021
Merged

Cleanup logging#965
TheBlueMatt merged 14 commits into
lightningdevkit:mainfrom
TheBlueMatt:2021-06-log-cleanups

Conversation

@TheBlueMatt

@TheBlueMattTheBlueMatt commented Jun 23, 2021

Copy link
Copy Markdown
Collaborator

This is the result of going through almost all of the logging in the library, as well as feedback from a few different users over the past month or so noting lack of logging in a few places.

  • I still need to go through onchaintx.rs and package.rs, but otherwise I think this is good.

These patches have been merged upstream and are in releases now so
we don't need to patch them locally.
When a peer sends us the routing graph, it may include gossip
messages for our channels, despite it not being a party to them.
This is completely fine, but we currently print a somewhat-scary
looking log messages in these cases, eg:
```
ERROR [lightning::ln::channelmanager:4104] Got a message for a channel from the wrong node!
TRACE [lightning::ln::peer_handler:1267] Handling SendErrorMessage HandleError event in peer_handler for node ... with message Got a message for a channel from the wrong node!
```
Instead, we should simply not consider this an "error" condition
and stay silent.
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from f83fa1a to 4a87105CompareJune 23, 2021 16:00
@codecov

codecovBot commented Jun 23, 2021

Copy link
Copy Markdown

Codecov Report

Merging #965 (6d98aed) into main (073afbb) will increase coverage by 1.08%.
The diff coverage is 73.09%.

Impacted file tree graph

@@ Coverage Diff @@## main #965 +/- ##
==========================================
+ Coverage 90.66% 91.75% +1.08% 
==========================================
Files 60 60 Lines 30407 34788 +4381 ==========================================
+ Hits 27568 31919 +4351 - Misses 2839 2869 +30 
Impacted FilesCoverage Δ
lightning/src/ln/msgs.rs90.60% <0.00%> (+2.25%)⬆️
lightning/src/ln/peer_handler.rs46.73% <12.50%> (+0.22%)⬆️
lightning/src/ln/wire.rs53.53% <50.00%> (-10.57%)⬇️
lightning/src/routing/network_graph.rs91.76% <50.00%> (-0.22%)⬇️
lightning/src/util/macro_logger.rs87.87% <50.00%> (-1.19%)⬇️
lightning/src/chain/package.rs93.04% <83.33%> (+0.74%)⬆️
lightning/src/ln/channelmanager.rs86.18% <83.33%> (+2.32%)⬆️
lightning/src/chain/channelmonitor.rs91.90% <100.00%> (+1.14%)⬆️
lightning/src/chain/onchaintx.rs94.19% <100.00%> (+0.04%)⬆️
lightning/src/ln/channel.rs92.51% <100.00%> (+4.22%)⬆️
... and 16 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 073afbb...6d98aed. Read the comment docs.

@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 4a87105 to edd0da5CompareJune 23, 2021 16:20
@TheBlueMattTheBlueMatt added this to the 0.0.99 milestone Jun 23, 2021

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for this cleanup :)

// a scary-looking error message and return Ok instead.
return Ok(());
}
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a channel_update for a channel from the wrong node - it shouldn't know about our private channels!".to_owned(), chan_id));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Though #949 blurs this assertion, a direct peer might learn a channel_update for outbound-from-us payments.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

#949 should only be sending the message directly to the channel counterparty, so I think its still correct. Its true we do tell other nodes about our private channels in invoices, but they still shouldn't remember that, nor should they ever have channel_updates for those messages. Do you have a suggestion for a different concrete wording?

@ariardariardJun 30, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think your comment is right if this peer is applying the same gossip policy than us ? Some weird LN client could not sort discovered gossips according to their sources and treat them uniformly, I don't think that's something the specification is covering (and IMHO it should be strongly opinionated on this).

So as a suggestion maybe prefix "Gossip policy: Got a channel_update for a channel from the wrong node - we consider it shouldn't know about this private channels!" ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

The specification is clear that you should not accept or forward a channel_update unless you've received the corresponding channel_announcement, which we will never generate signatures for, so it cannot exist.

log_error!(args.logger, " The ChannelMonitor for channel {} is at update_id {} but the ChannelManager is at update_id {}.",
log_bytes!(channel.channel_id()), monitor.get_latest_update_id(), channel.get_latest_monitor_update_id());
log_error!(args.logger, " The chain::Watch API *requires* that monitors are persisted durably before returning,");
log_error!(args.logger, " client applications must ensure that ChannelMonitor data is always available and the latest to avoid funds loss!");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Maybe add another line "You can search for a ChannelMonitor update_id matching the ChannelManager", otherwise what the user can do ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, isn't that included in the line two lines up The ChannelMonitor for channel {} is at update_id {} but the ChannelManager is at update_id {}.? I don't really think there is anything the user can do here, the application developer has a critical bug that may result/has resulted in funds loss, that bug needs to be resolved, and then maybe we can chat with them about how to deal directly with ChannelMonitors to close channels and create a new ChannelManager.

@ariardariardJun 30, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Right the update_id is already yielded. Maybe we could have a conventional message "This is a LDK API implementation bug : you can submit a bug report but ultimately solving the issue is on your side" ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

What do you think of #976 ?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Good to me

Comment threadlightning/src/ln/msgs.rs Outdated
IgnoreError,
/// The peer did something harmless (and expected) that we weren't able to meaningfully
/// process. Simply ignore.
IgnoreCommonError,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What do you think about HarmlessError/MinorError, a bit more meaningful w.r.t to IgnoreError ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, part of what I wanted to capture is that it is "common" in that it appears regularly. Ultimately that's the real difference between log_trace and log_debug - debug should still be readable, but trace you probably need to grep to get anything useful :). Maybe drop the Ignore part and just do ExpectedError?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The type indicates an action, though, so the naming is less meaningful without Ignore. Maybe use a single variant IgnoreAndLog with a severity parameter?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I really like that idea, will you kill me if I add a second type - there's a ton of Ignore references in the codebase and updating all of them in this PR seems like it would be a bit large. We can migrate to the explicit variant over time and then clean them all up when the repo is a bit quieter.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Done

Comment threadlightning/src/ln/channelmanager.rs Outdated

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice cleanup! Couldn't find any swapped args or anything

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/wire.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
IgnoreError,
/// The peer did something harmless (and expected) that we weren't able to meaningfully
/// process. Simply ignore.
IgnoreCommonError,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The type indicates an action, though, so the naming is less meaningful without Ignore. Maybe use a single variant IgnoreAndLog with a severity parameter?

Comment on lines +1537 to +1540
log_trace!(logger, "Checking funding_created tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} for channel {}.",
log_bytes!(sig.serialize_compact()[..]), log_bytes!(self.counterparty_funding_pubkey().serialize()),
encode::serialize_hex(&initial_commitment_bitcoin_tx.transaction), log_bytes!(sighash[..]),
encode::serialize_hex(&funding_script), log_bytes!(self.channel_id()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For some of these longer messages, I wonder if they would be easier to read if we logged a struct containing references to the data that implements Debug and used{:#?} to break across lines.

More thinking out loud. Feel free to ignore.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, good question! I wasn't aware that was a thing, but I'm a bit torn on it. I agree its pretty unreadable right now, but at the same time logging is an API not strictly a user-interface thing, so abstractly it feels weird to have linebreaks. More concretely, I currently grep the sample node logs pretty extensively to filter out verbose stuff, which moving towards inserting linebreaks would break. TRACE-level logging isn't really intended for direct human processing without some filtering, I think.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

FWIW, not sure how well supported this would be, but a log entry could theoretically contain new lines and the logger could write each entry separated by record separator control characters. Other loggers may log to a database or key-value store.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I still feel like that violates the principle of least-surprise - Users shouldn't be surprised that they have to do extra work to make our log entries "work" when writing to a file (the "common" use case IMO).

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/routing/router.rs Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch 3 times, most recently from bd6b560 to 15cc91aCompareJune 28, 2021 20:53
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Addressed all feedback, I think.

@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 15cc91a to 29991acCompareJune 28, 2021 20:59
Comment threadlightning/src/ln/peer_handler.rs Outdated
msgs::ErrorAction::IgnoreCommonError => {
log_trace!(self.logger, "Error handling message; ignoring: {}", e.err);
msgs::ErrorAction::IgnoreAndLog(level) => {
log_given_level!(self.logger, cmp::min(Level::Debug, level), "Error handling message; ignoring: {}", e.err);

@jkczyzjkczyzJun 29, 2021

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why is the cmp::min used? Would it make sense to write a custom macro for this so it doesn't need to be repeated elsewhere?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, I thought the "minimum level" there was pretty readable. I could move the cmp::min into the macro, but it felt readable and this is slightly more generic because it would let you do some match or if statement that sets the level?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

To rephrase my first question, why not just use level here? I don't quite understand why we want to use a lower level if IgnoreAndLog gives, say, Warn.

Hmm, I thought the "minimum level" there was pretty readable. I could move the cmp::min into the macro, but it felt readable and this is slightly more generic because it would let you do some match or if statement that sets the level?

I was saying to leave log_given_level as is and add another macro like log_debug_or_lower (or similarly named) to avoid a lot of boilerplate if this pattern will be common.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

To rephrase my first question, why not just use level here? I don't quite understand why we want to use a lower level if IgnoreAndLog gives, say, Warn.

Hmm, right, I guess we could? Its a bit strange to "warn" the user for an error that we "ignored", but I can just drop it.

I was saying to leave log_given_level as is and add another macro like log_debug_or_lower (or similarly named) to avoid a lot of boilerplate if this pattern will be common.

I mean we only handle the ErrorAction stuff in two places... :)

Comment threadlightning/src/util/logger.rs Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 29991ac to 7043607CompareJune 29, 2021 15:18
Comment threadlightning/src/util/logger.rs
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 7043607 to c37e76dCompareJune 29, 2021 16:02
// Note that if the pending_forward_status is not updated here, then it's because we're already failing
// the HTLC, i.e. its status is already set to failing.
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation");
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation in channel {}. Rebalancing is required.", log_bytes!(self.channel_id()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not a big deal but wish we could point people somewhere for expansion on "rebalancing is required" 🤔

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

We'll get there eventually :) #959

We had a client application which provided inconsistent monitor
state when deserializing a ChannelManager, resulting in opaque and
generic "InvalidData" deserialization failures. Instead, we log
some informative (and appropriately scary) warning messages in
such cases.
This makes our logging consistent and somewhat simplifies message
sending code in a few places.
This much more consistently logs information about messages
sent/received, including logging the full messages being
sent/received at the TRACE log level. Many other log messages which
are more often of interest were moved to the DEBUG log level.
For log entries which may have a variable level, we can't call an
arbitrary macro and need to be able to pass an explicit level. This
does so without breaking the compile-time disabling of certain log
levels.
Further, we "fix" the comparison order of log levels to make more
significant levels sort "higher", which implicitly makes more sense
than sorting "lower".
Finally, we remove the "Off" log level as no log entry should ever
be logged at the "Off" level - that would be nonsensical.
We very often receive duplicate gossip messages, which now causes us
to log at the DEBUG level, which is almost certainly not what a
user wants. Instead, we add a new form of ErrorAction which causes
us to only log at the TRACE level.
This updates a number of log sites in channel and channelmanager to
* Be a bit more verbose at the TRACE level,
* Move some error/useful messages to the ERROR/WARN/INFO level,
* Add new logs to always log once at the DEBUG level when we
send/receive a commitment_signed (with some extra data),
* Include the channel id being operated on in more log messages.
ChannelMonitor and related log entries can generally lean towards
being higher log levels than they necessarily need to be, as they
should be exceedingly rare, if only because they require
confirmation of an on-chain transaction.
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from c37e76d to 6d98aedCompareJune 29, 2021 19:36
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Squashed without changes:

$ git diff-tree -U1 c37e76da 6d98aeda
$

@TheBlueMatt
TheBlueMatt merged commit f472907 into lightningdevkit:mainJun 29, 2021
@ariard

Copy link
Copy Markdown

Post-merge Code Review ACK 6d98aed

+1 for the new ErrorAction::IgnoreAndLog API

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@TheBlueMatt@ariard@jkczyz@valentinewallace
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Cleanup logging - #965

Merged
TheBlueMatt merged 14 commits into
lightningdevkit:mainfrom
TheBlueMatt:2021-06-log-cleanups
Jun 29, 2021
Merged

Cleanup logging#965
TheBlueMatt merged 14 commits into
lightningdevkit:mainfrom
TheBlueMatt:2021-06-log-cleanups

Conversation

@TheBlueMatt

@TheBlueMattTheBlueMatt commented Jun 23, 2021

Copy link
Copy Markdown
Collaborator

This is the result of going through almost all of the logging in the library, as well as feedback from a few different users over the past month or so noting lack of logging in a few places.

  • I still need to go through onchaintx.rs and package.rs, but otherwise I think this is good.

These patches have been merged upstream and are in releases now so
we don't need to patch them locally.
When a peer sends us the routing graph, it may include gossip
messages for our channels, despite it not being a party to them.
This is completely fine, but we currently print a somewhat-scary
looking log messages in these cases, eg:
```
ERROR [lightning::ln::channelmanager:4104] Got a message for a channel from the wrong node!
TRACE [lightning::ln::peer_handler:1267] Handling SendErrorMessage HandleError event in peer_handler for node ... with message Got a message for a channel from the wrong node!
```
Instead, we should simply not consider this an "error" condition
and stay silent.
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from f83fa1a to 4a87105CompareJune 23, 2021 16:00
@codecov

codecovBot commented Jun 23, 2021

Copy link
Copy Markdown

Codecov Report

Merging #965 (6d98aed) into main (073afbb) will increase coverage by 1.08%.
The diff coverage is 73.09%.

Impacted file tree graph

@@ Coverage Diff @@## main #965 +/- ##
==========================================
+ Coverage 90.66% 91.75% +1.08% 
==========================================
Files 60 60 Lines 30407 34788 +4381 ==========================================
+ Hits 27568 31919 +4351 - Misses 2839 2869 +30 
Impacted FilesCoverage Δ
lightning/src/ln/msgs.rs90.60% <0.00%> (+2.25%)⬆️
lightning/src/ln/peer_handler.rs46.73% <12.50%> (+0.22%)⬆️
lightning/src/ln/wire.rs53.53% <50.00%> (-10.57%)⬇️
lightning/src/routing/network_graph.rs91.76% <50.00%> (-0.22%)⬇️
lightning/src/util/macro_logger.rs87.87% <50.00%> (-1.19%)⬇️
lightning/src/chain/package.rs93.04% <83.33%> (+0.74%)⬆️
lightning/src/ln/channelmanager.rs86.18% <83.33%> (+2.32%)⬆️
lightning/src/chain/channelmonitor.rs91.90% <100.00%> (+1.14%)⬆️
lightning/src/chain/onchaintx.rs94.19% <100.00%> (+0.04%)⬆️
lightning/src/ln/channel.rs92.51% <100.00%> (+4.22%)⬆️
... and 16 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 073afbb...6d98aed. Read the comment docs.

@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 4a87105 to edd0da5CompareJune 23, 2021 16:20
@TheBlueMattTheBlueMatt added this to the 0.0.99 milestone Jun 23, 2021

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for this cleanup :)

// a scary-looking error message and return Ok instead.
return Ok(());
}
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a channel_update for a channel from the wrong node - it shouldn't know about our private channels!".to_owned(), chan_id));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Though #949 blurs this assertion, a direct peer might learn a channel_update for outbound-from-us payments.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

#949 should only be sending the message directly to the channel counterparty, so I think its still correct. Its true we do tell other nodes about our private channels in invoices, but they still shouldn't remember that, nor should they ever have channel_updates for those messages. Do you have a suggestion for a different concrete wording?

@ariardariardJun 30, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think your comment is right if this peer is applying the same gossip policy than us ? Some weird LN client could not sort discovered gossips according to their sources and treat them uniformly, I don't think that's something the specification is covering (and IMHO it should be strongly opinionated on this).

So as a suggestion maybe prefix "Gossip policy: Got a channel_update for a channel from the wrong node - we consider it shouldn't know about this private channels!" ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

The specification is clear that you should not accept or forward a channel_update unless you've received the corresponding channel_announcement, which we will never generate signatures for, so it cannot exist.

log_error!(args.logger, " The ChannelMonitor for channel {} is at update_id {} but the ChannelManager is at update_id {}.",
log_bytes!(channel.channel_id()), monitor.get_latest_update_id(), channel.get_latest_monitor_update_id());
log_error!(args.logger, " The chain::Watch API *requires* that monitors are persisted durably before returning,");
log_error!(args.logger, " client applications must ensure that ChannelMonitor data is always available and the latest to avoid funds loss!");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Maybe add another line "You can search for a ChannelMonitor update_id matching the ChannelManager", otherwise what the user can do ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, isn't that included in the line two lines up The ChannelMonitor for channel {} is at update_id {} but the ChannelManager is at update_id {}.? I don't really think there is anything the user can do here, the application developer has a critical bug that may result/has resulted in funds loss, that bug needs to be resolved, and then maybe we can chat with them about how to deal directly with ChannelMonitors to close channels and create a new ChannelManager.

@ariardariardJun 30, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Right the update_id is already yielded. Maybe we could have a conventional message "This is a LDK API implementation bug : you can submit a bug report but ultimately solving the issue is on your side" ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

What do you think of #976 ?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Good to me

Comment threadlightning/src/ln/msgs.rs Outdated
IgnoreError,
/// The peer did something harmless (and expected) that we weren't able to meaningfully
/// process. Simply ignore.
IgnoreCommonError,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What do you think about HarmlessError/MinorError, a bit more meaningful w.r.t to IgnoreError ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, part of what I wanted to capture is that it is "common" in that it appears regularly. Ultimately that's the real difference between log_trace and log_debug - debug should still be readable, but trace you probably need to grep to get anything useful :). Maybe drop the Ignore part and just do ExpectedError?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The type indicates an action, though, so the naming is less meaningful without Ignore. Maybe use a single variant IgnoreAndLog with a severity parameter?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I really like that idea, will you kill me if I add a second type - there's a ton of Ignore references in the codebase and updating all of them in this PR seems like it would be a bit large. We can migrate to the explicit variant over time and then clean them all up when the repo is a bit quieter.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Done

Comment threadlightning/src/ln/channelmanager.rs Outdated

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice cleanup! Couldn't find any swapped args or anything

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/wire.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
IgnoreError,
/// The peer did something harmless (and expected) that we weren't able to meaningfully
/// process. Simply ignore.
IgnoreCommonError,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The type indicates an action, though, so the naming is less meaningful without Ignore. Maybe use a single variant IgnoreAndLog with a severity parameter?

Comment on lines +1537 to +1540
log_trace!(logger, "Checking funding_created tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} for channel {}.",
log_bytes!(sig.serialize_compact()[..]), log_bytes!(self.counterparty_funding_pubkey().serialize()),
encode::serialize_hex(&initial_commitment_bitcoin_tx.transaction), log_bytes!(sighash[..]),
encode::serialize_hex(&funding_script), log_bytes!(self.channel_id()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For some of these longer messages, I wonder if they would be easier to read if we logged a struct containing references to the data that implements Debug and used{:#?} to break across lines.

More thinking out loud. Feel free to ignore.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, good question! I wasn't aware that was a thing, but I'm a bit torn on it. I agree its pretty unreadable right now, but at the same time logging is an API not strictly a user-interface thing, so abstractly it feels weird to have linebreaks. More concretely, I currently grep the sample node logs pretty extensively to filter out verbose stuff, which moving towards inserting linebreaks would break. TRACE-level logging isn't really intended for direct human processing without some filtering, I think.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

FWIW, not sure how well supported this would be, but a log entry could theoretically contain new lines and the logger could write each entry separated by record separator control characters. Other loggers may log to a database or key-value store.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I still feel like that violates the principle of least-surprise - Users shouldn't be surprised that they have to do extra work to make our log entries "work" when writing to a file (the "common" use case IMO).

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/routing/router.rs Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch 3 times, most recently from bd6b560 to 15cc91aCompareJune 28, 2021 20:53
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Addressed all feedback, I think.

@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 15cc91a to 29991acCompareJune 28, 2021 20:59
Comment threadlightning/src/ln/peer_handler.rs Outdated
msgs::ErrorAction::IgnoreCommonError => {
log_trace!(self.logger, "Error handling message; ignoring: {}", e.err);
msgs::ErrorAction::IgnoreAndLog(level) => {
log_given_level!(self.logger, cmp::min(Level::Debug, level), "Error handling message; ignoring: {}", e.err);

@jkczyzjkczyzJun 29, 2021

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why is the cmp::min used? Would it make sense to write a custom macro for this so it doesn't need to be repeated elsewhere?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, I thought the "minimum level" there was pretty readable. I could move the cmp::min into the macro, but it felt readable and this is slightly more generic because it would let you do some match or if statement that sets the level?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

To rephrase my first question, why not just use level here? I don't quite understand why we want to use a lower level if IgnoreAndLog gives, say, Warn.

Hmm, I thought the "minimum level" there was pretty readable. I could move the cmp::min into the macro, but it felt readable and this is slightly more generic because it would let you do some match or if statement that sets the level?

I was saying to leave log_given_level as is and add another macro like log_debug_or_lower (or similarly named) to avoid a lot of boilerplate if this pattern will be common.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

To rephrase my first question, why not just use level here? I don't quite understand why we want to use a lower level if IgnoreAndLog gives, say, Warn.

Hmm, right, I guess we could? Its a bit strange to "warn" the user for an error that we "ignored", but I can just drop it.

I was saying to leave log_given_level as is and add another macro like log_debug_or_lower (or similarly named) to avoid a lot of boilerplate if this pattern will be common.

I mean we only handle the ErrorAction stuff in two places... :)

Comment threadlightning/src/util/logger.rs Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 29991ac to 7043607CompareJune 29, 2021 15:18
Comment threadlightning/src/util/logger.rs
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 7043607 to c37e76dCompareJune 29, 2021 16:02
// Note that if the pending_forward_status is not updated here, then it's because we're already failing
// the HTLC, i.e. its status is already set to failing.
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation");
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation in channel {}. Rebalancing is required.", log_bytes!(self.channel_id()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not a big deal but wish we could point people somewhere for expansion on "rebalancing is required" 🤔

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

We'll get there eventually :) #959

We had a client application which provided inconsistent monitor
state when deserializing a ChannelManager, resulting in opaque and
generic "InvalidData" deserialization failures. Instead, we log
some informative (and appropriately scary) warning messages in
such cases.
This makes our logging consistent and somewhat simplifies message
sending code in a few places.
This much more consistently logs information about messages
sent/received, including logging the full messages being
sent/received at the TRACE log level. Many other log messages which
are more often of interest were moved to the DEBUG log level.
For log entries which may have a variable level, we can't call an
arbitrary macro and need to be able to pass an explicit level. This
does so without breaking the compile-time disabling of certain log
levels.
Further, we "fix" the comparison order of log levels to make more
significant levels sort "higher", which implicitly makes more sense
than sorting "lower".
Finally, we remove the "Off" log level as no log entry should ever
be logged at the "Off" level - that would be nonsensical.
We very often receive duplicate gossip messages, which now causes us
to log at the DEBUG level, which is almost certainly not what a
user wants. Instead, we add a new form of ErrorAction which causes
us to only log at the TRACE level.
This updates a number of log sites in channel and channelmanager to
* Be a bit more verbose at the TRACE level,
* Move some error/useful messages to the ERROR/WARN/INFO level,
* Add new logs to always log once at the DEBUG level when we
send/receive a commitment_signed (with some extra data),
* Include the channel id being operated on in more log messages.
ChannelMonitor and related log entries can generally lean towards
being higher log levels than they necessarily need to be, as they
should be exceedingly rare, if only because they require
confirmation of an on-chain transaction.
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from c37e76d to 6d98aedCompareJune 29, 2021 19:36
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Squashed without changes:

$ git diff-tree -U1 c37e76da 6d98aeda
$

@TheBlueMatt
TheBlueMatt merged commit f472907 into lightningdevkit:mainJun 29, 2021
@ariard

Copy link
Copy Markdown

Post-merge Code Review ACK 6d98aed

+1 for the new ErrorAction::IgnoreAndLog API

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@TheBlueMatt@ariard@jkczyz@valentinewallace
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Cleanup logging - #965

Merged
TheBlueMatt merged 14 commits into
lightningdevkit:mainfrom
TheBlueMatt:2021-06-log-cleanups
Jun 29, 2021
Merged

Cleanup logging#965
TheBlueMatt merged 14 commits into
lightningdevkit:mainfrom
TheBlueMatt:2021-06-log-cleanups

Conversation

@TheBlueMatt

@TheBlueMattTheBlueMatt commented Jun 23, 2021

Copy link
Copy Markdown
Collaborator

This is the result of going through almost all of the logging in the library, as well as feedback from a few different users over the past month or so noting lack of logging in a few places.

  • I still need to go through onchaintx.rs and package.rs, but otherwise I think this is good.

These patches have been merged upstream and are in releases now so
we don't need to patch them locally.
When a peer sends us the routing graph, it may include gossip
messages for our channels, despite it not being a party to them.
This is completely fine, but we currently print a somewhat-scary
looking log messages in these cases, eg:
```
ERROR [lightning::ln::channelmanager:4104] Got a message for a channel from the wrong node!
TRACE [lightning::ln::peer_handler:1267] Handling SendErrorMessage HandleError event in peer_handler for node ... with message Got a message for a channel from the wrong node!
```
Instead, we should simply not consider this an "error" condition
and stay silent.
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from f83fa1a to 4a87105CompareJune 23, 2021 16:00
@codecov

codecovBot commented Jun 23, 2021

Copy link
Copy Markdown

Codecov Report

Merging #965 (6d98aed) into main (073afbb) will increase coverage by 1.08%.
The diff coverage is 73.09%.

Impacted file tree graph

@@ Coverage Diff @@## main #965 +/- ##
==========================================
+ Coverage 90.66% 91.75% +1.08% 
==========================================
Files 60 60 Lines 30407 34788 +4381 ==========================================
+ Hits 27568 31919 +4351 - Misses 2839 2869 +30 
Impacted FilesCoverage Δ
lightning/src/ln/msgs.rs90.60% <0.00%> (+2.25%)⬆️
lightning/src/ln/peer_handler.rs46.73% <12.50%> (+0.22%)⬆️
lightning/src/ln/wire.rs53.53% <50.00%> (-10.57%)⬇️
lightning/src/routing/network_graph.rs91.76% <50.00%> (-0.22%)⬇️
lightning/src/util/macro_logger.rs87.87% <50.00%> (-1.19%)⬇️
lightning/src/chain/package.rs93.04% <83.33%> (+0.74%)⬆️
lightning/src/ln/channelmanager.rs86.18% <83.33%> (+2.32%)⬆️
lightning/src/chain/channelmonitor.rs91.90% <100.00%> (+1.14%)⬆️
lightning/src/chain/onchaintx.rs94.19% <100.00%> (+0.04%)⬆️
lightning/src/ln/channel.rs92.51% <100.00%> (+4.22%)⬆️
... and 16 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 073afbb...6d98aed. Read the comment docs.

@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 4a87105 to edd0da5CompareJune 23, 2021 16:20
@TheBlueMattTheBlueMatt added this to the 0.0.99 milestone Jun 23, 2021

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for this cleanup :)

// a scary-looking error message and return Ok instead.
return Ok(());
}
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a channel_update for a channel from the wrong node - it shouldn't know about our private channels!".to_owned(), chan_id));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Though #949 blurs this assertion, a direct peer might learn a channel_update for outbound-from-us payments.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

#949 should only be sending the message directly to the channel counterparty, so I think its still correct. Its true we do tell other nodes about our private channels in invoices, but they still shouldn't remember that, nor should they ever have channel_updates for those messages. Do you have a suggestion for a different concrete wording?

@ariardariardJun 30, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think your comment is right if this peer is applying the same gossip policy than us ? Some weird LN client could not sort discovered gossips according to their sources and treat them uniformly, I don't think that's something the specification is covering (and IMHO it should be strongly opinionated on this).

So as a suggestion maybe prefix "Gossip policy: Got a channel_update for a channel from the wrong node - we consider it shouldn't know about this private channels!" ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

The specification is clear that you should not accept or forward a channel_update unless you've received the corresponding channel_announcement, which we will never generate signatures for, so it cannot exist.

log_error!(args.logger, " The ChannelMonitor for channel {} is at update_id {} but the ChannelManager is at update_id {}.",
log_bytes!(channel.channel_id()), monitor.get_latest_update_id(), channel.get_latest_monitor_update_id());
log_error!(args.logger, " The chain::Watch API *requires* that monitors are persisted durably before returning,");
log_error!(args.logger, " client applications must ensure that ChannelMonitor data is always available and the latest to avoid funds loss!");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Maybe add another line "You can search for a ChannelMonitor update_id matching the ChannelManager", otherwise what the user can do ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, isn't that included in the line two lines up The ChannelMonitor for channel {} is at update_id {} but the ChannelManager is at update_id {}.? I don't really think there is anything the user can do here, the application developer has a critical bug that may result/has resulted in funds loss, that bug needs to be resolved, and then maybe we can chat with them about how to deal directly with ChannelMonitors to close channels and create a new ChannelManager.

@ariardariardJun 30, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Right the update_id is already yielded. Maybe we could have a conventional message "This is a LDK API implementation bug : you can submit a bug report but ultimately solving the issue is on your side" ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

What do you think of #976 ?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Good to me

Comment threadlightning/src/ln/msgs.rs Outdated
IgnoreError,
/// The peer did something harmless (and expected) that we weren't able to meaningfully
/// process. Simply ignore.
IgnoreCommonError,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What do you think about HarmlessError/MinorError, a bit more meaningful w.r.t to IgnoreError ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, part of what I wanted to capture is that it is "common" in that it appears regularly. Ultimately that's the real difference between log_trace and log_debug - debug should still be readable, but trace you probably need to grep to get anything useful :). Maybe drop the Ignore part and just do ExpectedError?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The type indicates an action, though, so the naming is less meaningful without Ignore. Maybe use a single variant IgnoreAndLog with a severity parameter?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I really like that idea, will you kill me if I add a second type - there's a ton of Ignore references in the codebase and updating all of them in this PR seems like it would be a bit large. We can migrate to the explicit variant over time and then clean them all up when the repo is a bit quieter.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Done

Comment threadlightning/src/ln/channelmanager.rs Outdated

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice cleanup! Couldn't find any swapped args or anything

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/wire.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
IgnoreError,
/// The peer did something harmless (and expected) that we weren't able to meaningfully
/// process. Simply ignore.
IgnoreCommonError,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The type indicates an action, though, so the naming is less meaningful without Ignore. Maybe use a single variant IgnoreAndLog with a severity parameter?

Comment on lines +1537 to +1540
log_trace!(logger, "Checking funding_created tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} for channel {}.",
log_bytes!(sig.serialize_compact()[..]), log_bytes!(self.counterparty_funding_pubkey().serialize()),
encode::serialize_hex(&initial_commitment_bitcoin_tx.transaction), log_bytes!(sighash[..]),
encode::serialize_hex(&funding_script), log_bytes!(self.channel_id()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For some of these longer messages, I wonder if they would be easier to read if we logged a struct containing references to the data that implements Debug and used{:#?} to break across lines.

More thinking out loud. Feel free to ignore.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, good question! I wasn't aware that was a thing, but I'm a bit torn on it. I agree its pretty unreadable right now, but at the same time logging is an API not strictly a user-interface thing, so abstractly it feels weird to have linebreaks. More concretely, I currently grep the sample node logs pretty extensively to filter out verbose stuff, which moving towards inserting linebreaks would break. TRACE-level logging isn't really intended for direct human processing without some filtering, I think.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

FWIW, not sure how well supported this would be, but a log entry could theoretically contain new lines and the logger could write each entry separated by record separator control characters. Other loggers may log to a database or key-value store.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I still feel like that violates the principle of least-surprise - Users shouldn't be surprised that they have to do extra work to make our log entries "work" when writing to a file (the "common" use case IMO).

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/routing/router.rs Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch 3 times, most recently from bd6b560 to 15cc91aCompareJune 28, 2021 20:53
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Addressed all feedback, I think.

@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 15cc91a to 29991acCompareJune 28, 2021 20:59
Comment threadlightning/src/ln/peer_handler.rs Outdated
msgs::ErrorAction::IgnoreCommonError => {
log_trace!(self.logger, "Error handling message; ignoring: {}", e.err);
msgs::ErrorAction::IgnoreAndLog(level) => {
log_given_level!(self.logger, cmp::min(Level::Debug, level), "Error handling message; ignoring: {}", e.err);

@jkczyzjkczyzJun 29, 2021

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why is the cmp::min used? Would it make sense to write a custom macro for this so it doesn't need to be repeated elsewhere?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, I thought the "minimum level" there was pretty readable. I could move the cmp::min into the macro, but it felt readable and this is slightly more generic because it would let you do some match or if statement that sets the level?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

To rephrase my first question, why not just use level here? I don't quite understand why we want to use a lower level if IgnoreAndLog gives, say, Warn.

Hmm, I thought the "minimum level" there was pretty readable. I could move the cmp::min into the macro, but it felt readable and this is slightly more generic because it would let you do some match or if statement that sets the level?

I was saying to leave log_given_level as is and add another macro like log_debug_or_lower (or similarly named) to avoid a lot of boilerplate if this pattern will be common.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

To rephrase my first question, why not just use level here? I don't quite understand why we want to use a lower level if IgnoreAndLog gives, say, Warn.

Hmm, right, I guess we could? Its a bit strange to "warn" the user for an error that we "ignored", but I can just drop it.

I was saying to leave log_given_level as is and add another macro like log_debug_or_lower (or similarly named) to avoid a lot of boilerplate if this pattern will be common.

I mean we only handle the ErrorAction stuff in two places... :)

Comment threadlightning/src/util/logger.rs Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 29991ac to 7043607CompareJune 29, 2021 15:18
Comment threadlightning/src/util/logger.rs
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 7043607 to c37e76dCompareJune 29, 2021 16:02
// Note that if the pending_forward_status is not updated here, then it's because we're already failing
// the HTLC, i.e. its status is already set to failing.
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation");
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation in channel {}. Rebalancing is required.", log_bytes!(self.channel_id()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not a big deal but wish we could point people somewhere for expansion on "rebalancing is required" 🤔

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

We'll get there eventually :) #959

We had a client application which provided inconsistent monitor
state when deserializing a ChannelManager, resulting in opaque and
generic "InvalidData" deserialization failures. Instead, we log
some informative (and appropriately scary) warning messages in
such cases.
This makes our logging consistent and somewhat simplifies message
sending code in a few places.
This much more consistently logs information about messages
sent/received, including logging the full messages being
sent/received at the TRACE log level. Many other log messages which
are more often of interest were moved to the DEBUG log level.
For log entries which may have a variable level, we can't call an
arbitrary macro and need to be able to pass an explicit level. This
does so without breaking the compile-time disabling of certain log
levels.
Further, we "fix" the comparison order of log levels to make more
significant levels sort "higher", which implicitly makes more sense
than sorting "lower".
Finally, we remove the "Off" log level as no log entry should ever
be logged at the "Off" level - that would be nonsensical.
We very often receive duplicate gossip messages, which now causes us
to log at the DEBUG level, which is almost certainly not what a
user wants. Instead, we add a new form of ErrorAction which causes
us to only log at the TRACE level.
This updates a number of log sites in channel and channelmanager to
* Be a bit more verbose at the TRACE level,
* Move some error/useful messages to the ERROR/WARN/INFO level,
* Add new logs to always log once at the DEBUG level when we
send/receive a commitment_signed (with some extra data),
* Include the channel id being operated on in more log messages.
ChannelMonitor and related log entries can generally lean towards
being higher log levels than they necessarily need to be, as they
should be exceedingly rare, if only because they require
confirmation of an on-chain transaction.
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from c37e76d to 6d98aedCompareJune 29, 2021 19:36
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Squashed without changes:

$ git diff-tree -U1 c37e76da 6d98aeda
$

@TheBlueMatt
TheBlueMatt merged commit f472907 into lightningdevkit:mainJun 29, 2021
@ariard

Copy link
Copy Markdown

Post-merge Code Review ACK 6d98aed

+1 for the new ErrorAction::IgnoreAndLog API

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@TheBlueMatt@ariard@jkczyz@valentinewallace
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Cleanup logging - #965

Merged
TheBlueMatt merged 14 commits into
lightningdevkit:mainfrom
TheBlueMatt:2021-06-log-cleanups
Jun 29, 2021
Merged

Cleanup logging#965
TheBlueMatt merged 14 commits into
lightningdevkit:mainfrom
TheBlueMatt:2021-06-log-cleanups

Conversation

@TheBlueMatt

@TheBlueMattTheBlueMatt commented Jun 23, 2021

Copy link
Copy Markdown
Collaborator

This is the result of going through almost all of the logging in the library, as well as feedback from a few different users over the past month or so noting lack of logging in a few places.

  • I still need to go through onchaintx.rs and package.rs, but otherwise I think this is good.

These patches have been merged upstream and are in releases now so
we don't need to patch them locally.
When a peer sends us the routing graph, it may include gossip
messages for our channels, despite it not being a party to them.
This is completely fine, but we currently print a somewhat-scary
looking log messages in these cases, eg:
```
ERROR [lightning::ln::channelmanager:4104] Got a message for a channel from the wrong node!
TRACE [lightning::ln::peer_handler:1267] Handling SendErrorMessage HandleError event in peer_handler for node ... with message Got a message for a channel from the wrong node!
```
Instead, we should simply not consider this an "error" condition
and stay silent.
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from f83fa1a to 4a87105CompareJune 23, 2021 16:00
@codecov

codecovBot commented Jun 23, 2021

Copy link
Copy Markdown

Codecov Report

Merging #965 (6d98aed) into main (073afbb) will increase coverage by 1.08%.
The diff coverage is 73.09%.

Impacted file tree graph

@@ Coverage Diff @@## main #965 +/- ##
==========================================
+ Coverage 90.66% 91.75% +1.08% 
==========================================
Files 60 60 Lines 30407 34788 +4381 ==========================================
+ Hits 27568 31919 +4351 - Misses 2839 2869 +30 
Impacted FilesCoverage Δ
lightning/src/ln/msgs.rs90.60% <0.00%> (+2.25%)⬆️
lightning/src/ln/peer_handler.rs46.73% <12.50%> (+0.22%)⬆️
lightning/src/ln/wire.rs53.53% <50.00%> (-10.57%)⬇️
lightning/src/routing/network_graph.rs91.76% <50.00%> (-0.22%)⬇️
lightning/src/util/macro_logger.rs87.87% <50.00%> (-1.19%)⬇️
lightning/src/chain/package.rs93.04% <83.33%> (+0.74%)⬆️
lightning/src/ln/channelmanager.rs86.18% <83.33%> (+2.32%)⬆️
lightning/src/chain/channelmonitor.rs91.90% <100.00%> (+1.14%)⬆️
lightning/src/chain/onchaintx.rs94.19% <100.00%> (+0.04%)⬆️
lightning/src/ln/channel.rs92.51% <100.00%> (+4.22%)⬆️
... and 16 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 073afbb...6d98aed. Read the comment docs.

@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 4a87105 to edd0da5CompareJune 23, 2021 16:20
@TheBlueMattTheBlueMatt added this to the 0.0.99 milestone Jun 23, 2021

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for this cleanup :)

// a scary-looking error message and return Ok instead.
return Ok(());
}
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a channel_update for a channel from the wrong node - it shouldn't know about our private channels!".to_owned(), chan_id));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Though #949 blurs this assertion, a direct peer might learn a channel_update for outbound-from-us payments.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

#949 should only be sending the message directly to the channel counterparty, so I think its still correct. Its true we do tell other nodes about our private channels in invoices, but they still shouldn't remember that, nor should they ever have channel_updates for those messages. Do you have a suggestion for a different concrete wording?

@ariardariardJun 30, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think your comment is right if this peer is applying the same gossip policy than us ? Some weird LN client could not sort discovered gossips according to their sources and treat them uniformly, I don't think that's something the specification is covering (and IMHO it should be strongly opinionated on this).

So as a suggestion maybe prefix "Gossip policy: Got a channel_update for a channel from the wrong node - we consider it shouldn't know about this private channels!" ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

The specification is clear that you should not accept or forward a channel_update unless you've received the corresponding channel_announcement, which we will never generate signatures for, so it cannot exist.

log_error!(args.logger, " The ChannelMonitor for channel {} is at update_id {} but the ChannelManager is at update_id {}.",
log_bytes!(channel.channel_id()), monitor.get_latest_update_id(), channel.get_latest_monitor_update_id());
log_error!(args.logger, " The chain::Watch API *requires* that monitors are persisted durably before returning,");
log_error!(args.logger, " client applications must ensure that ChannelMonitor data is always available and the latest to avoid funds loss!");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Maybe add another line "You can search for a ChannelMonitor update_id matching the ChannelManager", otherwise what the user can do ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, isn't that included in the line two lines up The ChannelMonitor for channel {} is at update_id {} but the ChannelManager is at update_id {}.? I don't really think there is anything the user can do here, the application developer has a critical bug that may result/has resulted in funds loss, that bug needs to be resolved, and then maybe we can chat with them about how to deal directly with ChannelMonitors to close channels and create a new ChannelManager.

@ariardariardJun 30, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Right the update_id is already yielded. Maybe we could have a conventional message "This is a LDK API implementation bug : you can submit a bug report but ultimately solving the issue is on your side" ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

What do you think of #976 ?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Good to me

Comment threadlightning/src/ln/msgs.rs Outdated
IgnoreError,
/// The peer did something harmless (and expected) that we weren't able to meaningfully
/// process. Simply ignore.
IgnoreCommonError,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What do you think about HarmlessError/MinorError, a bit more meaningful w.r.t to IgnoreError ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, part of what I wanted to capture is that it is "common" in that it appears regularly. Ultimately that's the real difference between log_trace and log_debug - debug should still be readable, but trace you probably need to grep to get anything useful :). Maybe drop the Ignore part and just do ExpectedError?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The type indicates an action, though, so the naming is less meaningful without Ignore. Maybe use a single variant IgnoreAndLog with a severity parameter?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I really like that idea, will you kill me if I add a second type - there's a ton of Ignore references in the codebase and updating all of them in this PR seems like it would be a bit large. We can migrate to the explicit variant over time and then clean them all up when the repo is a bit quieter.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Done

Comment threadlightning/src/ln/channelmanager.rs Outdated

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice cleanup! Couldn't find any swapped args or anything

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/wire.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
IgnoreError,
/// The peer did something harmless (and expected) that we weren't able to meaningfully
/// process. Simply ignore.
IgnoreCommonError,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The type indicates an action, though, so the naming is less meaningful without Ignore. Maybe use a single variant IgnoreAndLog with a severity parameter?

Comment on lines +1537 to +1540
log_trace!(logger, "Checking funding_created tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} for channel {}.",
log_bytes!(sig.serialize_compact()[..]), log_bytes!(self.counterparty_funding_pubkey().serialize()),
encode::serialize_hex(&initial_commitment_bitcoin_tx.transaction), log_bytes!(sighash[..]),
encode::serialize_hex(&funding_script), log_bytes!(self.channel_id()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For some of these longer messages, I wonder if they would be easier to read if we logged a struct containing references to the data that implements Debug and used{:#?} to break across lines.

More thinking out loud. Feel free to ignore.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, good question! I wasn't aware that was a thing, but I'm a bit torn on it. I agree its pretty unreadable right now, but at the same time logging is an API not strictly a user-interface thing, so abstractly it feels weird to have linebreaks. More concretely, I currently grep the sample node logs pretty extensively to filter out verbose stuff, which moving towards inserting linebreaks would break. TRACE-level logging isn't really intended for direct human processing without some filtering, I think.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

FWIW, not sure how well supported this would be, but a log entry could theoretically contain new lines and the logger could write each entry separated by record separator control characters. Other loggers may log to a database or key-value store.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I still feel like that violates the principle of least-surprise - Users shouldn't be surprised that they have to do extra work to make our log entries "work" when writing to a file (the "common" use case IMO).

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/routing/router.rs Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch 3 times, most recently from bd6b560 to 15cc91aCompareJune 28, 2021 20:53
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Addressed all feedback, I think.

@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 15cc91a to 29991acCompareJune 28, 2021 20:59
Comment threadlightning/src/ln/peer_handler.rs Outdated
msgs::ErrorAction::IgnoreCommonError => {
log_trace!(self.logger, "Error handling message; ignoring: {}", e.err);
msgs::ErrorAction::IgnoreAndLog(level) => {
log_given_level!(self.logger, cmp::min(Level::Debug, level), "Error handling message; ignoring: {}", e.err);

@jkczyzjkczyzJun 29, 2021

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why is the cmp::min used? Would it make sense to write a custom macro for this so it doesn't need to be repeated elsewhere?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, I thought the "minimum level" there was pretty readable. I could move the cmp::min into the macro, but it felt readable and this is slightly more generic because it would let you do some match or if statement that sets the level?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

To rephrase my first question, why not just use level here? I don't quite understand why we want to use a lower level if IgnoreAndLog gives, say, Warn.

Hmm, I thought the "minimum level" there was pretty readable. I could move the cmp::min into the macro, but it felt readable and this is slightly more generic because it would let you do some match or if statement that sets the level?

I was saying to leave log_given_level as is and add another macro like log_debug_or_lower (or similarly named) to avoid a lot of boilerplate if this pattern will be common.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

To rephrase my first question, why not just use level here? I don't quite understand why we want to use a lower level if IgnoreAndLog gives, say, Warn.

Hmm, right, I guess we could? Its a bit strange to "warn" the user for an error that we "ignored", but I can just drop it.

I was saying to leave log_given_level as is and add another macro like log_debug_or_lower (or similarly named) to avoid a lot of boilerplate if this pattern will be common.

I mean we only handle the ErrorAction stuff in two places... :)

Comment threadlightning/src/util/logger.rs Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 29991ac to 7043607CompareJune 29, 2021 15:18
Comment threadlightning/src/util/logger.rs
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 7043607 to c37e76dCompareJune 29, 2021 16:02
// Note that if the pending_forward_status is not updated here, then it's because we're already failing
// the HTLC, i.e. its status is already set to failing.
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation");
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation in channel {}. Rebalancing is required.", log_bytes!(self.channel_id()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not a big deal but wish we could point people somewhere for expansion on "rebalancing is required" 🤔

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

We'll get there eventually :) #959

We had a client application which provided inconsistent monitor
state when deserializing a ChannelManager, resulting in opaque and
generic "InvalidData" deserialization failures. Instead, we log
some informative (and appropriately scary) warning messages in
such cases.
This makes our logging consistent and somewhat simplifies message
sending code in a few places.
This much more consistently logs information about messages
sent/received, including logging the full messages being
sent/received at the TRACE log level. Many other log messages which
are more often of interest were moved to the DEBUG log level.
For log entries which may have a variable level, we can't call an
arbitrary macro and need to be able to pass an explicit level. This
does so without breaking the compile-time disabling of certain log
levels.
Further, we "fix" the comparison order of log levels to make more
significant levels sort "higher", which implicitly makes more sense
than sorting "lower".
Finally, we remove the "Off" log level as no log entry should ever
be logged at the "Off" level - that would be nonsensical.
We very often receive duplicate gossip messages, which now causes us
to log at the DEBUG level, which is almost certainly not what a
user wants. Instead, we add a new form of ErrorAction which causes
us to only log at the TRACE level.
This updates a number of log sites in channel and channelmanager to
* Be a bit more verbose at the TRACE level,
* Move some error/useful messages to the ERROR/WARN/INFO level,
* Add new logs to always log once at the DEBUG level when we
send/receive a commitment_signed (with some extra data),
* Include the channel id being operated on in more log messages.
ChannelMonitor and related log entries can generally lean towards
being higher log levels than they necessarily need to be, as they
should be exceedingly rare, if only because they require
confirmation of an on-chain transaction.
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from c37e76d to 6d98aedCompareJune 29, 2021 19:36
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Squashed without changes:

$ git diff-tree -U1 c37e76da 6d98aeda
$

@TheBlueMatt
TheBlueMatt merged commit f472907 into lightningdevkit:mainJun 29, 2021
@ariard

Copy link
Copy Markdown

Post-merge Code Review ACK 6d98aed

+1 for the new ErrorAction::IgnoreAndLog API

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@TheBlueMatt@ariard@jkczyz@valentinewallace
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Cleanup logging - #965

Merged
TheBlueMatt merged 14 commits into
lightningdevkit:mainfrom
TheBlueMatt:2021-06-log-cleanups
Jun 29, 2021
Merged

Cleanup logging#965
TheBlueMatt merged 14 commits into
lightningdevkit:mainfrom
TheBlueMatt:2021-06-log-cleanups

Conversation

@TheBlueMatt

@TheBlueMattTheBlueMatt commented Jun 23, 2021

Copy link
Copy Markdown
Collaborator

This is the result of going through almost all of the logging in the library, as well as feedback from a few different users over the past month or so noting lack of logging in a few places.

  • I still need to go through onchaintx.rs and package.rs, but otherwise I think this is good.

These patches have been merged upstream and are in releases now so
we don't need to patch them locally.
When a peer sends us the routing graph, it may include gossip
messages for our channels, despite it not being a party to them.
This is completely fine, but we currently print a somewhat-scary
looking log messages in these cases, eg:
```
ERROR [lightning::ln::channelmanager:4104] Got a message for a channel from the wrong node!
TRACE [lightning::ln::peer_handler:1267] Handling SendErrorMessage HandleError event in peer_handler for node ... with message Got a message for a channel from the wrong node!
```
Instead, we should simply not consider this an "error" condition
and stay silent.
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from f83fa1a to 4a87105CompareJune 23, 2021 16:00
@codecov

codecovBot commented Jun 23, 2021

Copy link
Copy Markdown

Codecov Report

Merging #965 (6d98aed) into main (073afbb) will increase coverage by 1.08%.
The diff coverage is 73.09%.

Impacted file tree graph

@@ Coverage Diff @@## main #965 +/- ##
==========================================
+ Coverage 90.66% 91.75% +1.08% 
==========================================
Files 60 60 Lines 30407 34788 +4381 ==========================================
+ Hits 27568 31919 +4351 - Misses 2839 2869 +30 
Impacted FilesCoverage Δ
lightning/src/ln/msgs.rs90.60% <0.00%> (+2.25%)⬆️
lightning/src/ln/peer_handler.rs46.73% <12.50%> (+0.22%)⬆️
lightning/src/ln/wire.rs53.53% <50.00%> (-10.57%)⬇️
lightning/src/routing/network_graph.rs91.76% <50.00%> (-0.22%)⬇️
lightning/src/util/macro_logger.rs87.87% <50.00%> (-1.19%)⬇️
lightning/src/chain/package.rs93.04% <83.33%> (+0.74%)⬆️
lightning/src/ln/channelmanager.rs86.18% <83.33%> (+2.32%)⬆️
lightning/src/chain/channelmonitor.rs91.90% <100.00%> (+1.14%)⬆️
lightning/src/chain/onchaintx.rs94.19% <100.00%> (+0.04%)⬆️
lightning/src/ln/channel.rs92.51% <100.00%> (+4.22%)⬆️
... and 16 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 073afbb...6d98aed. Read the comment docs.

@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 4a87105 to edd0da5CompareJune 23, 2021 16:20
@TheBlueMattTheBlueMatt added this to the 0.0.99 milestone Jun 23, 2021

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for this cleanup :)

// a scary-looking error message and return Ok instead.
return Ok(());
}
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a channel_update for a channel from the wrong node - it shouldn't know about our private channels!".to_owned(), chan_id));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Though #949 blurs this assertion, a direct peer might learn a channel_update for outbound-from-us payments.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

#949 should only be sending the message directly to the channel counterparty, so I think its still correct. Its true we do tell other nodes about our private channels in invoices, but they still shouldn't remember that, nor should they ever have channel_updates for those messages. Do you have a suggestion for a different concrete wording?

@ariardariardJun 30, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think your comment is right if this peer is applying the same gossip policy than us ? Some weird LN client could not sort discovered gossips according to their sources and treat them uniformly, I don't think that's something the specification is covering (and IMHO it should be strongly opinionated on this).

So as a suggestion maybe prefix "Gossip policy: Got a channel_update for a channel from the wrong node - we consider it shouldn't know about this private channels!" ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

The specification is clear that you should not accept or forward a channel_update unless you've received the corresponding channel_announcement, which we will never generate signatures for, so it cannot exist.

log_error!(args.logger, " The ChannelMonitor for channel {} is at update_id {} but the ChannelManager is at update_id {}.",
log_bytes!(channel.channel_id()), monitor.get_latest_update_id(), channel.get_latest_monitor_update_id());
log_error!(args.logger, " The chain::Watch API *requires* that monitors are persisted durably before returning,");
log_error!(args.logger, " client applications must ensure that ChannelMonitor data is always available and the latest to avoid funds loss!");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Maybe add another line "You can search for a ChannelMonitor update_id matching the ChannelManager", otherwise what the user can do ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, isn't that included in the line two lines up The ChannelMonitor for channel {} is at update_id {} but the ChannelManager is at update_id {}.? I don't really think there is anything the user can do here, the application developer has a critical bug that may result/has resulted in funds loss, that bug needs to be resolved, and then maybe we can chat with them about how to deal directly with ChannelMonitors to close channels and create a new ChannelManager.

@ariardariardJun 30, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Right the update_id is already yielded. Maybe we could have a conventional message "This is a LDK API implementation bug : you can submit a bug report but ultimately solving the issue is on your side" ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

What do you think of #976 ?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Good to me

Comment threadlightning/src/ln/msgs.rs Outdated
IgnoreError,
/// The peer did something harmless (and expected) that we weren't able to meaningfully
/// process. Simply ignore.
IgnoreCommonError,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What do you think about HarmlessError/MinorError, a bit more meaningful w.r.t to IgnoreError ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, part of what I wanted to capture is that it is "common" in that it appears regularly. Ultimately that's the real difference between log_trace and log_debug - debug should still be readable, but trace you probably need to grep to get anything useful :). Maybe drop the Ignore part and just do ExpectedError?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The type indicates an action, though, so the naming is less meaningful without Ignore. Maybe use a single variant IgnoreAndLog with a severity parameter?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I really like that idea, will you kill me if I add a second type - there's a ton of Ignore references in the codebase and updating all of them in this PR seems like it would be a bit large. We can migrate to the explicit variant over time and then clean them all up when the repo is a bit quieter.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Done

Comment threadlightning/src/ln/channelmanager.rs Outdated

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice cleanup! Couldn't find any swapped args or anything

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/wire.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
IgnoreError,
/// The peer did something harmless (and expected) that we weren't able to meaningfully
/// process. Simply ignore.
IgnoreCommonError,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The type indicates an action, though, so the naming is less meaningful without Ignore. Maybe use a single variant IgnoreAndLog with a severity parameter?

Comment on lines +1537 to +1540
log_trace!(logger, "Checking funding_created tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} for channel {}.",
log_bytes!(sig.serialize_compact()[..]), log_bytes!(self.counterparty_funding_pubkey().serialize()),
encode::serialize_hex(&initial_commitment_bitcoin_tx.transaction), log_bytes!(sighash[..]),
encode::serialize_hex(&funding_script), log_bytes!(self.channel_id()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For some of these longer messages, I wonder if they would be easier to read if we logged a struct containing references to the data that implements Debug and used{:#?} to break across lines.

More thinking out loud. Feel free to ignore.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, good question! I wasn't aware that was a thing, but I'm a bit torn on it. I agree its pretty unreadable right now, but at the same time logging is an API not strictly a user-interface thing, so abstractly it feels weird to have linebreaks. More concretely, I currently grep the sample node logs pretty extensively to filter out verbose stuff, which moving towards inserting linebreaks would break. TRACE-level logging isn't really intended for direct human processing without some filtering, I think.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

FWIW, not sure how well supported this would be, but a log entry could theoretically contain new lines and the logger could write each entry separated by record separator control characters. Other loggers may log to a database or key-value store.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I still feel like that violates the principle of least-surprise - Users shouldn't be surprised that they have to do extra work to make our log entries "work" when writing to a file (the "common" use case IMO).

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/routing/router.rs Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch 3 times, most recently from bd6b560 to 15cc91aCompareJune 28, 2021 20:53
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Addressed all feedback, I think.

@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 15cc91a to 29991acCompareJune 28, 2021 20:59
Comment threadlightning/src/ln/peer_handler.rs Outdated
msgs::ErrorAction::IgnoreCommonError => {
log_trace!(self.logger, "Error handling message; ignoring: {}", e.err);
msgs::ErrorAction::IgnoreAndLog(level) => {
log_given_level!(self.logger, cmp::min(Level::Debug, level), "Error handling message; ignoring: {}", e.err);

@jkczyzjkczyzJun 29, 2021

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why is the cmp::min used? Would it make sense to write a custom macro for this so it doesn't need to be repeated elsewhere?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, I thought the "minimum level" there was pretty readable. I could move the cmp::min into the macro, but it felt readable and this is slightly more generic because it would let you do some match or if statement that sets the level?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

To rephrase my first question, why not just use level here? I don't quite understand why we want to use a lower level if IgnoreAndLog gives, say, Warn.

Hmm, I thought the "minimum level" there was pretty readable. I could move the cmp::min into the macro, but it felt readable and this is slightly more generic because it would let you do some match or if statement that sets the level?

I was saying to leave log_given_level as is and add another macro like log_debug_or_lower (or similarly named) to avoid a lot of boilerplate if this pattern will be common.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

To rephrase my first question, why not just use level here? I don't quite understand why we want to use a lower level if IgnoreAndLog gives, say, Warn.

Hmm, right, I guess we could? Its a bit strange to "warn" the user for an error that we "ignored", but I can just drop it.

I was saying to leave log_given_level as is and add another macro like log_debug_or_lower (or similarly named) to avoid a lot of boilerplate if this pattern will be common.

I mean we only handle the ErrorAction stuff in two places... :)

Comment threadlightning/src/util/logger.rs Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 29991ac to 7043607CompareJune 29, 2021 15:18
Comment threadlightning/src/util/logger.rs
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 7043607 to c37e76dCompareJune 29, 2021 16:02
// Note that if the pending_forward_status is not updated here, then it's because we're already failing
// the HTLC, i.e. its status is already set to failing.
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation");
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation in channel {}. Rebalancing is required.", log_bytes!(self.channel_id()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not a big deal but wish we could point people somewhere for expansion on "rebalancing is required" 🤔

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

We'll get there eventually :) #959

We had a client application which provided inconsistent monitor
state when deserializing a ChannelManager, resulting in opaque and
generic "InvalidData" deserialization failures. Instead, we log
some informative (and appropriately scary) warning messages in
such cases.
This makes our logging consistent and somewhat simplifies message
sending code in a few places.
This much more consistently logs information about messages
sent/received, including logging the full messages being
sent/received at the TRACE log level. Many other log messages which
are more often of interest were moved to the DEBUG log level.
For log entries which may have a variable level, we can't call an
arbitrary macro and need to be able to pass an explicit level. This
does so without breaking the compile-time disabling of certain log
levels.
Further, we "fix" the comparison order of log levels to make more
significant levels sort "higher", which implicitly makes more sense
than sorting "lower".
Finally, we remove the "Off" log level as no log entry should ever
be logged at the "Off" level - that would be nonsensical.
We very often receive duplicate gossip messages, which now causes us
to log at the DEBUG level, which is almost certainly not what a
user wants. Instead, we add a new form of ErrorAction which causes
us to only log at the TRACE level.
This updates a number of log sites in channel and channelmanager to
* Be a bit more verbose at the TRACE level,
* Move some error/useful messages to the ERROR/WARN/INFO level,
* Add new logs to always log once at the DEBUG level when we
send/receive a commitment_signed (with some extra data),
* Include the channel id being operated on in more log messages.
ChannelMonitor and related log entries can generally lean towards
being higher log levels than they necessarily need to be, as they
should be exceedingly rare, if only because they require
confirmation of an on-chain transaction.
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from c37e76d to 6d98aedCompareJune 29, 2021 19:36
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Squashed without changes:

$ git diff-tree -U1 c37e76da 6d98aeda
$

@TheBlueMatt
TheBlueMatt merged commit f472907 into lightningdevkit:mainJun 29, 2021
@ariard

Copy link
Copy Markdown

Post-merge Code Review ACK 6d98aed

+1 for the new ErrorAction::IgnoreAndLog API

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@TheBlueMatt@ariard@jkczyz@valentinewallace
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Cleanup logging - #965

Merged
TheBlueMatt merged 14 commits into
lightningdevkit:mainfrom
TheBlueMatt:2021-06-log-cleanups
Jun 29, 2021
Merged

Cleanup logging#965
TheBlueMatt merged 14 commits into
lightningdevkit:mainfrom
TheBlueMatt:2021-06-log-cleanups

Conversation

@TheBlueMatt

@TheBlueMattTheBlueMatt commented Jun 23, 2021

Copy link
Copy Markdown
Collaborator

This is the result of going through almost all of the logging in the library, as well as feedback from a few different users over the past month or so noting lack of logging in a few places.

  • I still need to go through onchaintx.rs and package.rs, but otherwise I think this is good.

These patches have been merged upstream and are in releases now so
we don't need to patch them locally.
When a peer sends us the routing graph, it may include gossip
messages for our channels, despite it not being a party to them.
This is completely fine, but we currently print a somewhat-scary
looking log messages in these cases, eg:
```
ERROR [lightning::ln::channelmanager:4104] Got a message for a channel from the wrong node!
TRACE [lightning::ln::peer_handler:1267] Handling SendErrorMessage HandleError event in peer_handler for node ... with message Got a message for a channel from the wrong node!
```
Instead, we should simply not consider this an "error" condition
and stay silent.
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from f83fa1a to 4a87105CompareJune 23, 2021 16:00
@codecov

codecovBot commented Jun 23, 2021

Copy link
Copy Markdown

Codecov Report

Merging #965 (6d98aed) into main (073afbb) will increase coverage by 1.08%.
The diff coverage is 73.09%.

Impacted file tree graph

@@ Coverage Diff @@## main #965 +/- ##
==========================================
+ Coverage 90.66% 91.75% +1.08% 
==========================================
Files 60 60 Lines 30407 34788 +4381 ==========================================
+ Hits 27568 31919 +4351 - Misses 2839 2869 +30 
Impacted FilesCoverage Δ
lightning/src/ln/msgs.rs90.60% <0.00%> (+2.25%)⬆️
lightning/src/ln/peer_handler.rs46.73% <12.50%> (+0.22%)⬆️
lightning/src/ln/wire.rs53.53% <50.00%> (-10.57%)⬇️
lightning/src/routing/network_graph.rs91.76% <50.00%> (-0.22%)⬇️
lightning/src/util/macro_logger.rs87.87% <50.00%> (-1.19%)⬇️
lightning/src/chain/package.rs93.04% <83.33%> (+0.74%)⬆️
lightning/src/ln/channelmanager.rs86.18% <83.33%> (+2.32%)⬆️
lightning/src/chain/channelmonitor.rs91.90% <100.00%> (+1.14%)⬆️
lightning/src/chain/onchaintx.rs94.19% <100.00%> (+0.04%)⬆️
lightning/src/ln/channel.rs92.51% <100.00%> (+4.22%)⬆️
... and 16 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 073afbb...6d98aed. Read the comment docs.

@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 4a87105 to edd0da5CompareJune 23, 2021 16:20
@TheBlueMattTheBlueMatt added this to the 0.0.99 milestone Jun 23, 2021

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for this cleanup :)

// a scary-looking error message and return Ok instead.
return Ok(());
}
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a channel_update for a channel from the wrong node - it shouldn't know about our private channels!".to_owned(), chan_id));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Though #949 blurs this assertion, a direct peer might learn a channel_update for outbound-from-us payments.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

#949 should only be sending the message directly to the channel counterparty, so I think its still correct. Its true we do tell other nodes about our private channels in invoices, but they still shouldn't remember that, nor should they ever have channel_updates for those messages. Do you have a suggestion for a different concrete wording?

@ariardariardJun 30, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think your comment is right if this peer is applying the same gossip policy than us ? Some weird LN client could not sort discovered gossips according to their sources and treat them uniformly, I don't think that's something the specification is covering (and IMHO it should be strongly opinionated on this).

So as a suggestion maybe prefix "Gossip policy: Got a channel_update for a channel from the wrong node - we consider it shouldn't know about this private channels!" ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

The specification is clear that you should not accept or forward a channel_update unless you've received the corresponding channel_announcement, which we will never generate signatures for, so it cannot exist.

log_error!(args.logger, " The ChannelMonitor for channel {} is at update_id {} but the ChannelManager is at update_id {}.",
log_bytes!(channel.channel_id()), monitor.get_latest_update_id(), channel.get_latest_monitor_update_id());
log_error!(args.logger, " The chain::Watch API *requires* that monitors are persisted durably before returning,");
log_error!(args.logger, " client applications must ensure that ChannelMonitor data is always available and the latest to avoid funds loss!");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Maybe add another line "You can search for a ChannelMonitor update_id matching the ChannelManager", otherwise what the user can do ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, isn't that included in the line two lines up The ChannelMonitor for channel {} is at update_id {} but the ChannelManager is at update_id {}.? I don't really think there is anything the user can do here, the application developer has a critical bug that may result/has resulted in funds loss, that bug needs to be resolved, and then maybe we can chat with them about how to deal directly with ChannelMonitors to close channels and create a new ChannelManager.

@ariardariardJun 30, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Right the update_id is already yielded. Maybe we could have a conventional message "This is a LDK API implementation bug : you can submit a bug report but ultimately solving the issue is on your side" ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

What do you think of #976 ?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Good to me

Comment threadlightning/src/ln/msgs.rs Outdated
IgnoreError,
/// The peer did something harmless (and expected) that we weren't able to meaningfully
/// process. Simply ignore.
IgnoreCommonError,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What do you think about HarmlessError/MinorError, a bit more meaningful w.r.t to IgnoreError ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, part of what I wanted to capture is that it is "common" in that it appears regularly. Ultimately that's the real difference between log_trace and log_debug - debug should still be readable, but trace you probably need to grep to get anything useful :). Maybe drop the Ignore part and just do ExpectedError?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The type indicates an action, though, so the naming is less meaningful without Ignore. Maybe use a single variant IgnoreAndLog with a severity parameter?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I really like that idea, will you kill me if I add a second type - there's a ton of Ignore references in the codebase and updating all of them in this PR seems like it would be a bit large. We can migrate to the explicit variant over time and then clean them all up when the repo is a bit quieter.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Done

Comment threadlightning/src/ln/channelmanager.rs Outdated

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice cleanup! Couldn't find any swapped args or anything

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/wire.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
IgnoreError,
/// The peer did something harmless (and expected) that we weren't able to meaningfully
/// process. Simply ignore.
IgnoreCommonError,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The type indicates an action, though, so the naming is less meaningful without Ignore. Maybe use a single variant IgnoreAndLog with a severity parameter?

Comment on lines +1537 to +1540
log_trace!(logger, "Checking funding_created tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} for channel {}.",
log_bytes!(sig.serialize_compact()[..]), log_bytes!(self.counterparty_funding_pubkey().serialize()),
encode::serialize_hex(&initial_commitment_bitcoin_tx.transaction), log_bytes!(sighash[..]),
encode::serialize_hex(&funding_script), log_bytes!(self.channel_id()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For some of these longer messages, I wonder if they would be easier to read if we logged a struct containing references to the data that implements Debug and used{:#?} to break across lines.

More thinking out loud. Feel free to ignore.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, good question! I wasn't aware that was a thing, but I'm a bit torn on it. I agree its pretty unreadable right now, but at the same time logging is an API not strictly a user-interface thing, so abstractly it feels weird to have linebreaks. More concretely, I currently grep the sample node logs pretty extensively to filter out verbose stuff, which moving towards inserting linebreaks would break. TRACE-level logging isn't really intended for direct human processing without some filtering, I think.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

FWIW, not sure how well supported this would be, but a log entry could theoretically contain new lines and the logger could write each entry separated by record separator control characters. Other loggers may log to a database or key-value store.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I still feel like that violates the principle of least-surprise - Users shouldn't be surprised that they have to do extra work to make our log entries "work" when writing to a file (the "common" use case IMO).

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/routing/router.rs Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch 3 times, most recently from bd6b560 to 15cc91aCompareJune 28, 2021 20:53
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Addressed all feedback, I think.

@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 15cc91a to 29991acCompareJune 28, 2021 20:59
Comment threadlightning/src/ln/peer_handler.rs Outdated
msgs::ErrorAction::IgnoreCommonError => {
log_trace!(self.logger, "Error handling message; ignoring: {}", e.err);
msgs::ErrorAction::IgnoreAndLog(level) => {
log_given_level!(self.logger, cmp::min(Level::Debug, level), "Error handling message; ignoring: {}", e.err);

@jkczyzjkczyzJun 29, 2021

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why is the cmp::min used? Would it make sense to write a custom macro for this so it doesn't need to be repeated elsewhere?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, I thought the "minimum level" there was pretty readable. I could move the cmp::min into the macro, but it felt readable and this is slightly more generic because it would let you do some match or if statement that sets the level?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

To rephrase my first question, why not just use level here? I don't quite understand why we want to use a lower level if IgnoreAndLog gives, say, Warn.

Hmm, I thought the "minimum level" there was pretty readable. I could move the cmp::min into the macro, but it felt readable and this is slightly more generic because it would let you do some match or if statement that sets the level?

I was saying to leave log_given_level as is and add another macro like log_debug_or_lower (or similarly named) to avoid a lot of boilerplate if this pattern will be common.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

To rephrase my first question, why not just use level here? I don't quite understand why we want to use a lower level if IgnoreAndLog gives, say, Warn.

Hmm, right, I guess we could? Its a bit strange to "warn" the user for an error that we "ignored", but I can just drop it.

I was saying to leave log_given_level as is and add another macro like log_debug_or_lower (or similarly named) to avoid a lot of boilerplate if this pattern will be common.

I mean we only handle the ErrorAction stuff in two places... :)

Comment threadlightning/src/util/logger.rs Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 29991ac to 7043607CompareJune 29, 2021 15:18
Comment threadlightning/src/util/logger.rs
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 7043607 to c37e76dCompareJune 29, 2021 16:02
// Note that if the pending_forward_status is not updated here, then it's because we're already failing
// the HTLC, i.e. its status is already set to failing.
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation");
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation in channel {}. Rebalancing is required.", log_bytes!(self.channel_id()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not a big deal but wish we could point people somewhere for expansion on "rebalancing is required" 🤔

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

We'll get there eventually :) #959

We had a client application which provided inconsistent monitor
state when deserializing a ChannelManager, resulting in opaque and
generic "InvalidData" deserialization failures. Instead, we log
some informative (and appropriately scary) warning messages in
such cases.
This makes our logging consistent and somewhat simplifies message
sending code in a few places.
This much more consistently logs information about messages
sent/received, including logging the full messages being
sent/received at the TRACE log level. Many other log messages which
are more often of interest were moved to the DEBUG log level.
For log entries which may have a variable level, we can't call an
arbitrary macro and need to be able to pass an explicit level. This
does so without breaking the compile-time disabling of certain log
levels.
Further, we "fix" the comparison order of log levels to make more
significant levels sort "higher", which implicitly makes more sense
than sorting "lower".
Finally, we remove the "Off" log level as no log entry should ever
be logged at the "Off" level - that would be nonsensical.
We very often receive duplicate gossip messages, which now causes us
to log at the DEBUG level, which is almost certainly not what a
user wants. Instead, we add a new form of ErrorAction which causes
us to only log at the TRACE level.
This updates a number of log sites in channel and channelmanager to
* Be a bit more verbose at the TRACE level,
* Move some error/useful messages to the ERROR/WARN/INFO level,
* Add new logs to always log once at the DEBUG level when we
send/receive a commitment_signed (with some extra data),
* Include the channel id being operated on in more log messages.
ChannelMonitor and related log entries can generally lean towards
being higher log levels than they necessarily need to be, as they
should be exceedingly rare, if only because they require
confirmation of an on-chain transaction.
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from c37e76d to 6d98aedCompareJune 29, 2021 19:36
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Squashed without changes:

$ git diff-tree -U1 c37e76da 6d98aeda
$

@TheBlueMatt
TheBlueMatt merged commit f472907 into lightningdevkit:mainJun 29, 2021
@ariard

Copy link
Copy Markdown

Post-merge Code Review ACK 6d98aed

+1 for the new ErrorAction::IgnoreAndLog API

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@TheBlueMatt@ariard@jkczyz@valentinewallace
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Cleanup logging - #965

Merged
TheBlueMatt merged 14 commits into
lightningdevkit:mainfrom
TheBlueMatt:2021-06-log-cleanups
Jun 29, 2021
Merged

Cleanup logging#965
TheBlueMatt merged 14 commits into
lightningdevkit:mainfrom
TheBlueMatt:2021-06-log-cleanups

Conversation

@TheBlueMatt

@TheBlueMattTheBlueMatt commented Jun 23, 2021

Copy link
Copy Markdown
Collaborator

This is the result of going through almost all of the logging in the library, as well as feedback from a few different users over the past month or so noting lack of logging in a few places.

  • I still need to go through onchaintx.rs and package.rs, but otherwise I think this is good.

These patches have been merged upstream and are in releases now so
we don't need to patch them locally.
When a peer sends us the routing graph, it may include gossip
messages for our channels, despite it not being a party to them.
This is completely fine, but we currently print a somewhat-scary
looking log messages in these cases, eg:
```
ERROR [lightning::ln::channelmanager:4104] Got a message for a channel from the wrong node!
TRACE [lightning::ln::peer_handler:1267] Handling SendErrorMessage HandleError event in peer_handler for node ... with message Got a message for a channel from the wrong node!
```
Instead, we should simply not consider this an "error" condition
and stay silent.
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from f83fa1a to 4a87105CompareJune 23, 2021 16:00
@codecov

codecovBot commented Jun 23, 2021

Copy link
Copy Markdown

Codecov Report

Merging #965 (6d98aed) into main (073afbb) will increase coverage by 1.08%.
The diff coverage is 73.09%.

Impacted file tree graph

@@ Coverage Diff @@## main #965 +/- ##
==========================================
+ Coverage 90.66% 91.75% +1.08% 
==========================================
Files 60 60 Lines 30407 34788 +4381 ==========================================
+ Hits 27568 31919 +4351 - Misses 2839 2869 +30 
Impacted FilesCoverage Δ
lightning/src/ln/msgs.rs90.60% <0.00%> (+2.25%)⬆️
lightning/src/ln/peer_handler.rs46.73% <12.50%> (+0.22%)⬆️
lightning/src/ln/wire.rs53.53% <50.00%> (-10.57%)⬇️
lightning/src/routing/network_graph.rs91.76% <50.00%> (-0.22%)⬇️
lightning/src/util/macro_logger.rs87.87% <50.00%> (-1.19%)⬇️
lightning/src/chain/package.rs93.04% <83.33%> (+0.74%)⬆️
lightning/src/ln/channelmanager.rs86.18% <83.33%> (+2.32%)⬆️
lightning/src/chain/channelmonitor.rs91.90% <100.00%> (+1.14%)⬆️
lightning/src/chain/onchaintx.rs94.19% <100.00%> (+0.04%)⬆️
lightning/src/ln/channel.rs92.51% <100.00%> (+4.22%)⬆️
... and 16 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 073afbb...6d98aed. Read the comment docs.

@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 4a87105 to edd0da5CompareJune 23, 2021 16:20
@TheBlueMattTheBlueMatt added this to the 0.0.99 milestone Jun 23, 2021

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for this cleanup :)

// a scary-looking error message and return Ok instead.
return Ok(());
}
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a channel_update for a channel from the wrong node - it shouldn't know about our private channels!".to_owned(), chan_id));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Though #949 blurs this assertion, a direct peer might learn a channel_update for outbound-from-us payments.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

#949 should only be sending the message directly to the channel counterparty, so I think its still correct. Its true we do tell other nodes about our private channels in invoices, but they still shouldn't remember that, nor should they ever have channel_updates for those messages. Do you have a suggestion for a different concrete wording?

@ariardariardJun 30, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think your comment is right if this peer is applying the same gossip policy than us ? Some weird LN client could not sort discovered gossips according to their sources and treat them uniformly, I don't think that's something the specification is covering (and IMHO it should be strongly opinionated on this).

So as a suggestion maybe prefix "Gossip policy: Got a channel_update for a channel from the wrong node - we consider it shouldn't know about this private channels!" ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

The specification is clear that you should not accept or forward a channel_update unless you've received the corresponding channel_announcement, which we will never generate signatures for, so it cannot exist.

log_error!(args.logger, " The ChannelMonitor for channel {} is at update_id {} but the ChannelManager is at update_id {}.",
log_bytes!(channel.channel_id()), monitor.get_latest_update_id(), channel.get_latest_monitor_update_id());
log_error!(args.logger, " The chain::Watch API *requires* that monitors are persisted durably before returning,");
log_error!(args.logger, " client applications must ensure that ChannelMonitor data is always available and the latest to avoid funds loss!");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Maybe add another line "You can search for a ChannelMonitor update_id matching the ChannelManager", otherwise what the user can do ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, isn't that included in the line two lines up The ChannelMonitor for channel {} is at update_id {} but the ChannelManager is at update_id {}.? I don't really think there is anything the user can do here, the application developer has a critical bug that may result/has resulted in funds loss, that bug needs to be resolved, and then maybe we can chat with them about how to deal directly with ChannelMonitors to close channels and create a new ChannelManager.

@ariardariardJun 30, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Right the update_id is already yielded. Maybe we could have a conventional message "This is a LDK API implementation bug : you can submit a bug report but ultimately solving the issue is on your side" ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

What do you think of #976 ?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Good to me

Comment threadlightning/src/ln/msgs.rs Outdated
IgnoreError,
/// The peer did something harmless (and expected) that we weren't able to meaningfully
/// process. Simply ignore.
IgnoreCommonError,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What do you think about HarmlessError/MinorError, a bit more meaningful w.r.t to IgnoreError ?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, part of what I wanted to capture is that it is "common" in that it appears regularly. Ultimately that's the real difference between log_trace and log_debug - debug should still be readable, but trace you probably need to grep to get anything useful :). Maybe drop the Ignore part and just do ExpectedError?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The type indicates an action, though, so the naming is less meaningful without Ignore. Maybe use a single variant IgnoreAndLog with a severity parameter?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I really like that idea, will you kill me if I add a second type - there's a ton of Ignore references in the codebase and updating all of them in this PR seems like it would be a bit large. We can migrate to the explicit variant over time and then clean them all up when the repo is a bit quieter.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Done

Comment threadlightning/src/ln/channelmanager.rs Outdated

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice cleanup! Couldn't find any swapped args or anything

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/peer_handler.rs Outdated
Comment threadlightning/src/ln/wire.rs Outdated
Comment threadlightning/src/ln/msgs.rs Outdated
IgnoreError,
/// The peer did something harmless (and expected) that we weren't able to meaningfully
/// process. Simply ignore.
IgnoreCommonError,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The type indicates an action, though, so the naming is less meaningful without Ignore. Maybe use a single variant IgnoreAndLog with a severity parameter?

Comment on lines +1537 to +1540
log_trace!(logger, "Checking funding_created tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} for channel {}.",
log_bytes!(sig.serialize_compact()[..]), log_bytes!(self.counterparty_funding_pubkey().serialize()),
encode::serialize_hex(&initial_commitment_bitcoin_tx.transaction), log_bytes!(sighash[..]),
encode::serialize_hex(&funding_script), log_bytes!(self.channel_id()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For some of these longer messages, I wonder if they would be easier to read if we logged a struct containing references to the data that implements Debug and used{:#?} to break across lines.

More thinking out loud. Feel free to ignore.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, good question! I wasn't aware that was a thing, but I'm a bit torn on it. I agree its pretty unreadable right now, but at the same time logging is an API not strictly a user-interface thing, so abstractly it feels weird to have linebreaks. More concretely, I currently grep the sample node logs pretty extensively to filter out verbose stuff, which moving towards inserting linebreaks would break. TRACE-level logging isn't really intended for direct human processing without some filtering, I think.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

FWIW, not sure how well supported this would be, but a log entry could theoretically contain new lines and the logger could write each entry separated by record separator control characters. Other loggers may log to a database or key-value store.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I still feel like that violates the principle of least-surprise - Users shouldn't be surprised that they have to do extra work to make our log entries "work" when writing to a file (the "common" use case IMO).

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/routing/router.rs Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch 3 times, most recently from bd6b560 to 15cc91aCompareJune 28, 2021 20:53
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Addressed all feedback, I think.

@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 15cc91a to 29991acCompareJune 28, 2021 20:59
Comment threadlightning/src/ln/peer_handler.rs Outdated
msgs::ErrorAction::IgnoreCommonError => {
log_trace!(self.logger, "Error handling message; ignoring: {}", e.err);
msgs::ErrorAction::IgnoreAndLog(level) => {
log_given_level!(self.logger, cmp::min(Level::Debug, level), "Error handling message; ignoring: {}", e.err);

@jkczyzjkczyzJun 29, 2021

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why is the cmp::min used? Would it make sense to write a custom macro for this so it doesn't need to be repeated elsewhere?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, I thought the "minimum level" there was pretty readable. I could move the cmp::min into the macro, but it felt readable and this is slightly more generic because it would let you do some match or if statement that sets the level?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

To rephrase my first question, why not just use level here? I don't quite understand why we want to use a lower level if IgnoreAndLog gives, say, Warn.

Hmm, I thought the "minimum level" there was pretty readable. I could move the cmp::min into the macro, but it felt readable and this is slightly more generic because it would let you do some match or if statement that sets the level?

I was saying to leave log_given_level as is and add another macro like log_debug_or_lower (or similarly named) to avoid a lot of boilerplate if this pattern will be common.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

To rephrase my first question, why not just use level here? I don't quite understand why we want to use a lower level if IgnoreAndLog gives, say, Warn.

Hmm, right, I guess we could? Its a bit strange to "warn" the user for an error that we "ignored", but I can just drop it.

I was saying to leave log_given_level as is and add another macro like log_debug_or_lower (or similarly named) to avoid a lot of boilerplate if this pattern will be common.

I mean we only handle the ErrorAction stuff in two places... :)

Comment threadlightning/src/util/logger.rs Outdated
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 29991ac to 7043607CompareJune 29, 2021 15:18
Comment threadlightning/src/util/logger.rs
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from 7043607 to c37e76dCompareJune 29, 2021 16:02
// Note that if the pending_forward_status is not updated here, then it's because we're already failing
// the HTLC, i.e. its status is already set to failing.
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation");
log_info!(logger, "Attempting to fail HTLC due to fee spike buffer violation in channel {}. Rebalancing is required.", log_bytes!(self.channel_id()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not a big deal but wish we could point people somewhere for expansion on "rebalancing is required" 🤔

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

We'll get there eventually :) #959

We had a client application which provided inconsistent monitor
state when deserializing a ChannelManager, resulting in opaque and
generic "InvalidData" deserialization failures. Instead, we log
some informative (and appropriately scary) warning messages in
such cases.
This makes our logging consistent and somewhat simplifies message
sending code in a few places.
This much more consistently logs information about messages
sent/received, including logging the full messages being
sent/received at the TRACE log level. Many other log messages which
are more often of interest were moved to the DEBUG log level.
For log entries which may have a variable level, we can't call an
arbitrary macro and need to be able to pass an explicit level. This
does so without breaking the compile-time disabling of certain log
levels.
Further, we "fix" the comparison order of log levels to make more
significant levels sort "higher", which implicitly makes more sense
than sorting "lower".
Finally, we remove the "Off" log level as no log entry should ever
be logged at the "Off" level - that would be nonsensical.
We very often receive duplicate gossip messages, which now causes us
to log at the DEBUG level, which is almost certainly not what a
user wants. Instead, we add a new form of ErrorAction which causes
us to only log at the TRACE level.
This updates a number of log sites in channel and channelmanager to
* Be a bit more verbose at the TRACE level,
* Move some error/useful messages to the ERROR/WARN/INFO level,
* Add new logs to always log once at the DEBUG level when we
send/receive a commitment_signed (with some extra data),
* Include the channel id being operated on in more log messages.
ChannelMonitor and related log entries can generally lean towards
being higher log levels than they necessarily need to be, as they
should be exceedingly rare, if only because they require
confirmation of an on-chain transaction.
@TheBlueMatt
TheBlueMattforce-pushed the 2021-06-log-cleanups branch from c37e76d to 6d98aedCompareJune 29, 2021 19:36
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Squashed without changes:

$ git diff-tree -U1 c37e76da 6d98aeda
$

@TheBlueMatt
TheBlueMatt merged commit f472907 into lightningdevkit:mainJun 29, 2021
@ariard

Copy link
Copy Markdown

Post-merge Code Review ACK 6d98aed

+1 for the new ErrorAction::IgnoreAndLog API

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@TheBlueMatt@ariard@jkczyz@valentinewallace