From 9caeae391e85e0dbd99e3092ab6ec687c95bb07e Mon Sep 17 00:00:00 2001 From: Yingwen Date: Thu, 6 Nov 2025 16:48:59 +0800 Subject: [PATCH] chore: print root cause in opendal logging interceptor (#7183) * chore: print root cause in opendal Signed-off-by: evenyag * refactor: extract a function root_source() to get the cause Signed-off-by: evenyag --------- Signed-off-by: evenyag --- src/common/error/src/lib.rs | 16 ++++++++++++++++ src/object-store/src/util.rs | 6 ++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/common/error/src/lib.rs b/src/common/error/src/lib.rs index 0052d70cf3..18e6a0c9ae 100644 --- a/src/common/error/src/lib.rs +++ b/src/common/error/src/lib.rs @@ -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 +} diff --git a/src/object-store/src/util.rs b/src/object-store/src/util.rs index 00858eb74a..a402b8237c 100644 --- a/src/object-store/src/util.rs +++ b/src/object-store/src/util.rs @@ -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),