chore: print root cause in opendal logging interceptor (#7183)

* chore: print root cause in opendal

Signed-off-by: evenyag <realevenyag@gmail.com>

* refactor: extract a function root_source() to get the cause

Signed-off-by: evenyag <realevenyag@gmail.com>

---------

Signed-off-by: evenyag <realevenyag@gmail.com>
This commit is contained in:
Yingwen
2025-11-06 16:48:59 +08:00
committed by GitHub
parent 35951afff9
commit 9caeae391e
2 changed files with 20 additions and 2 deletions

View File

@@ -45,3 +45,19 @@ pub fn from_err_code_msg_to_header(code: u32, msg: &str) -> HeaderMap {
header.insert(GREPTIME_DB_HEADER_ERROR_MSG, msg);
header
}
/// Returns the external root cause of the source error (exclude the current error).
pub fn root_source(err: &dyn std::error::Error) -> Option<&dyn std::error::Error> {
// There are some divergence about the behavior of the `sources()` API
// in https://github.com/rust-lang/rust/issues/58520
// So this function iterates the sources manually.
let mut root = err.source();
while let Some(r) = root {
if let Some(s) = r.source() {
root = Some(s);
} else {
break;
}
}
root
}

View File

@@ -16,6 +16,7 @@ use std::fmt::Display;
use std::path;
use std::time::Duration;
use common_error::root_source;
use common_telemetry::{debug, error, info, warn};
use opendal::layers::{
LoggingInterceptor, LoggingLayer, RetryInterceptor, RetryLayer, TracingLayer,
@@ -174,11 +175,12 @@ impl LoggingInterceptor for DefaultLoggingInterceptor {
err: Option<&opendal::Error>,
) {
if let Some(err) = err {
let root = root_source(err);
// Print error if it's unexpected, otherwise in error.
if err.kind() == ErrorKind::Unexpected {
error!(
target: LOGGING_TARGET,
"service={} name={} {}: {operation} {message} {err:#?}",
"service={} name={} {}: {operation} {message} {err:#?}, root={root:#?}",
info.scheme(),
info.name(),
LoggingContext(context),
@@ -186,7 +188,7 @@ impl LoggingInterceptor for DefaultLoggingInterceptor {
} else {
debug!(
target: LOGGING_TARGET,
"service={} name={} {}: {operation} {message} {err}",
"service={} name={} {}: {operation} {message} {err}, root={root:?}",
info.scheme(),
info.name(),
LoggingContext(context),