Skip to content

More cleanup related to error logging#9942

Merged
smklein merged 56 commits into
oxidecomputer:mainfrom
sruggier:pr/error-logging-fixes
Mar 16, 2026
Merged

More cleanup related to error logging#9942
smklein merged 56 commits into
oxidecomputer:mainfrom
sruggier:pr/error-logging-fixes

Conversation

@sruggier

@sruggier sruggier commented Feb 27, 2026

Copy link
Copy Markdown
Contributor

This is a bit of a grab bag of error logging related fixes, carefully ordered (as described in #9804) to err on the side of potentially logging source error messages multiple times, rather than not at all.

This is related to #9804.

@sruggier
sruggier force-pushed the pr/error-logging-fixes branch 6 times, most recently from 2bbd201 to e731217 Compare March 6, 2026 22:35
@sruggier
sruggier force-pushed the pr/error-logging-fixes branch 3 times, most recently from 0175e1b to d61c890 Compare March 9, 2026 22:21
@sruggier
sruggier force-pushed the pr/error-logging-fixes branch from c675dd0 to 88b2f30 Compare March 12, 2026 15:01

@smklein smklein left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The structure overall looks great here. Thanks for doing this cleanup; hopefully this makes our errors more sensible. LGTM modulo a few comments below.

Comment thread nexus/src/app/background/tasks/support_bundle/steps/host_info.rs Outdated
Comment thread illumos-utils/src/zfs.rs
@@ -244,19 +246,21 @@ pub struct UnloadKeyError {

#[derive(Debug, thiserror::Error)]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should this one derive SlogInlineError too?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is a bit of an open question, and I think it mostly depends on organizational culture, so I'm going to throw it back to you, to some extent.

The code will fail to compile if one tries to use an error type after the semicolon in a logging macro, without having derived SlogInlineError, so it's reasonably convenient, and not very error-prone, I think, to plan to add the derive at the time one is adding code that relies on it. Because of that, I opted not to add derive calls in the changes unless they were needed.

On the other hand, the added friction of having to add the derive can be costly to others, and it's occurring to me now that it could be a useful way to mark an error as being transitioned to rely on the source function instead of echoing source error messages in its Display implementation.

So I could go either way on this one, depending on what you think. Otherwise, I lean toward being lazy about it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm totally fine punting it - there's sorta a distinction between "error structs annotating with Derive" vs "callers expecting underlying errors to have already added the derive". Makes sense that the latter would be a bit onerous, since it requires everyone to be converted already.

I think adding the derive more universally would be a reasonable long-term goal, but I'm okay preventing this PR from getting larger!

@sruggier sruggier Mar 13, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks again for looking at this!

Yeah, another part of my thought process here was that I'm a bit uncertain about whether this might be revisited later on. There could be some observability-related motivation to switch to something more structured than what SlogInlineError does, like ArrayInlineError, so I also didn't want to go out of my way to do something that might never be used before it gets replaced.

To add to the analysis paralysis, I also had made an open PR on slog-error-chain, which adds blanket trait implementations that make it ever so slightly more convenient to create one of these adapters. At some point shortly after, I saw display_error_chain mentioned in the omicron codebase, and noticed that it also has blanket traits for Errors and Results.

One can achieve almost the same convenience by adding a postfix snippet to their rust-analyzer config, but I feel like the method call is a bit more readable, and it's one less thing for each developer to have to configure in their own editing setup.

I don't have strong opinions about this in general, though - it's much safer and easier to switch between these options than the initial cleanup is, and it's more important to preserve the source information in some form than to get the reporting of it exactly right up front.

Comment thread illumos-utils/src/running_zone.rs
Comment thread sled-agent/src/services.rs Outdated
@sruggier
sruggier force-pushed the pr/error-logging-fixes branch from 88b2f30 to c91eb7b Compare March 12, 2026 19:15
@sruggier

sruggier commented Mar 12, 2026

Copy link
Copy Markdown
Contributor Author

My push reset the workflow, but it looks like the last one was green, at least:
https://github.com/oxidecomputer/omicron/actions/runs/23008552688

I wasn't expecting it to be finished so quickly. I guess #10018 is working.

sruggier added 16 commits March 13, 2026 11:58
This change updates all handlers of omicron_sled_agent::Error to use the
InlineErrorChain adapter, removes all duplicate source error messages
from its Display implementation, and adds the #[source] attribute to all
applicable source errors.
It looks like all code paths that handle ConfigError are already
attaching it to error types that will log the full chain of sources, so
there's nothing to do for this type, save for cleaning up its
implementation of `Display`.
Previously, only the next level down would be logged, which could
discard source information in case of NodeRequestError::Fsm and
NodeRequestError::Recv error types. This commit links
bootstore::NodeRequestError as a source instead of formatting it as a
string, which would drop the rest of the chain.
This commit updates handle_start_sled_agent_request to log the full
error chain in case a SledAgentServerStartError is returned. Previously,
one level of cause would be logged for the FailedLearnerInit variant,
and CommitToLedger errors were logged without any information about the
source.
The main consumer of this error type seems to be
omicron_sled_agent::sled_agent::Error, so this commit has the effect of
fixing duplication in error logging that was introduced by a previous
commit within the same PR.
This change modifies all of the code paths that handle
omicron_sled_agent::instance::Error so they use the InlineErrorChain
adapter before logging error messages, and then updates the enum
definition to avoid duplicate error emission from its `Display`
implementation.
Similar to previous commits, this updates all handlers of
omicron_sled_agent::services::Error such that they recurse into sources
instead of relying on the duplication of source error messages in its
`Display` implementation. It then also removes all duplicated error
strings from its `Display` implementation, defining sources instead,
where applicable.
sruggier added 24 commits March 13, 2026 11:58
In many cases, this will be overkill, because io::Error variants
generally don't have linked sources. Unfortunately, there is one corner
case, which is the Other variant, and in general, there's no easy way to
know an io::Error isn't going to be that variant, so this change updates
most code paths that handle io::Error.
@sruggier
sruggier force-pushed the pr/error-logging-fixes branch from c91eb7b to 0e40cc3 Compare March 13, 2026 16:04
@sruggier

Copy link
Copy Markdown
Contributor Author

@smklein Thanks for the review, this is ready for you to look at again. I'm wondering how you'd want to address the question about where to derive SlogInlineError, but the other feedback has been addressed.

If once a day is too frequent to remind about this, please let me know. It's nice to have hit a merge conflict that resulted from someone else independently improving an overlapping code path, though – I kind of like it when that happens 🙂

@smklein

smklein commented Mar 13, 2026

Copy link
Copy Markdown
Collaborator

This looks good to me - if CI is happy, I'll merge for you. Thanks for making this change! Looking forward to our clearer error chains!

(As an FYI for future changes - we generally try to avoid force-pushing, especially after reviews have started, because Github makes it pretty painful to see diffs between commits if any force-pushing has occurred. I will re-review the entire PR if there are any force-pushes, as a matter of completeness -- but I obviously don't need to do that for non-force-pushed incremental changes)

@sruggier

Copy link
Copy Markdown
Contributor Author

As an FYI for future changes - we generally try to avoid force-pushing, especially after reviews have started, because Github makes it pretty painful to see diffs between commits if any force-pushing has occurred

Oh, sorry about that - it was mostly to rebase on the main branch and fix conflicts, but I did also slip a few changes in there. At times, I've coped with this pain (in GitLab, which behaves in the same sad way) by leaving explanatory comments next to each push, and trying to make separate pushes for rebases and other changes, so the compare link actually does something meaningful. I wasn't sure how important that would be for anyone's review workflow, though, so I didn't bother here. I wish I had, though: I hate to impose any extra review effort 😅

On the reviewing side, I've also sometimes found it useful to work around this by diffing the diffs (using git merge-base to calculate the base of each version of the branch), to filter out the noise from rebasing. It's not perfect (various changes to hunk line numbers clutter the diff), but it's still readable enough in cases where the branch hasn't changed much. I have to assume that jj somehow offers better primitives for dealing with this, but haven't explored that yet. I suppose one could also rebase the version they reviewed, and then diff it with the newly pushed version, but that's a bit much when there are conflicts involved.

@smklein
smklein merged commit 59903f0 into oxidecomputer:main Mar 16, 2026
17 checks passed
@sruggier

Copy link
Copy Markdown
Contributor Author

@smklein Thanks for remembering to merge this! I'm so used to having to remind people, sadly, that it was a bit of a pleasant surprise.

Sign up for free to 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.

2 participants