Associate logs from log_err with the calling crate (#13617)

Now, when you selectively enable logs from particular crates with
`RUST_LOG=call,worktree`, logs created via `log_err` calls in those
crates get correctly enabled. Previously, they were all attributed to
the `util` crate, because they used the normal logging macros, which
implicitly insert the current crate name.

This relies on the regularity of our directory naming. Rust's
`track_caller` feature allows you to obtain the file system path of the
caller, but not its rust module path, so I'm inferring the crate name
from the file system path (which I believe is always valid, in our
codebase).

Release Notes:

- N/A
This commit is contained in:
Max Brunsfeld 2024-06-27 17:03:47 -07:00 committed by GitHub
parent 0b57df5deb
commit 97159bd88d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -335,7 +335,6 @@ pub trait ResultExt<E> {
/// Assert that this result should never be an error in development or tests.
fn debug_assert_ok(self, reason: &str) -> Self;
fn warn_on_err(self) -> Option<Self::Ok>;
fn inspect_error(self, func: impl FnOnce(&E)) -> Self;
}
impl<T, E> ResultExt<E> for Result<T, E>
@ -349,8 +348,7 @@ where
match self {
Ok(value) => Some(value),
Err(error) => {
let caller = Location::caller();
log::error!("{}:{}: {:?}", caller.file(), caller.line(), error);
log_error_with_caller(*Location::caller(), error, log::Level::Error);
None
}
}
@ -364,24 +362,36 @@ where
self
}
#[track_caller]
fn warn_on_err(self) -> Option<T> {
match self {
Ok(value) => Some(value),
Err(error) => {
log::warn!("{:?}", error);
log_error_with_caller(*Location::caller(), error, log::Level::Warn);
None
}
}
}
}
/// https://doc.rust-lang.org/std/result/enum.Result.html#method.inspect_err
fn inspect_error(self, func: impl FnOnce(&E)) -> Self {
if let Err(err) = &self {
func(err);
}
fn log_error_with_caller<E>(caller: core::panic::Location<'_>, error: E, level: log::Level)
where
E: std::fmt::Debug,
{
// In this codebase, the first segment of the file path is
// the 'crates' folder, followed by the crate name.
let target = caller.file().split('/').nth(1);
self
}
log::logger().log(
&log::Record::builder()
.target(target.unwrap_or(""))
.module_path(target)
.args(format_args!("{:?}", error))
.file(Some(caller.file()))
.line(Some(caller.line()))
.level(level)
.build(),
);
}
pub trait TryFutureExt {
@ -457,13 +467,7 @@ where
Poll::Ready(output) => Poll::Ready(match output {
Ok(output) => Some(output),
Err(error) => {
log::log!(
level,
"{}:{}: {:?}",
location.file(),
location.line(),
error
);
log_error_with_caller(location, error, level);
None
}
}),