use crate::types::AgentError;
use std::error::Error as StdError;
pub trait ErrorTraceExt {
fn trace_error(&self) -> &Self;
}
impl ErrorTraceExt for AgentError {
fn trace_error(&self) -> &Self {
let error_code = self.error_code();
let is_retryable = self.is_retryable();
let is_client_error = self.is_client_error();
let mut error_chain = Vec::new();
let mut current_source = self.source();
while let Some(source) = current_source {
error_chain.push(source.to_string());
current_source = source.source();
}
tracing::error!(
error = %self,
error_code = error_code.code(),
error_code_name = ?error_code,
is_retryable = is_retryable,
is_client_error = is_client_error,
error_chain_len = error_chain.len(),
error_chain = ?error_chain,
"Error occurred with full context"
);
self
}
}
pub trait ResultTraceExt<T, E>: Sized {
fn trace_context(self) -> Result<T, AgentError>
where
E: StdError + Send + Sync + 'static;
}
impl<T, E> ResultTraceExt<T, E> for Result<T, E>
where
E: StdError + Send + Sync + 'static,
AgentError: From<E>,
{
fn trace_context(self) -> Result<T, AgentError> {
self.map_err(|e| {
let agent_error = AgentError::from(e);
agent_error.trace_error();
agent_error
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_trace_ext() {
let error = AgentError::connection_failed("Test connection failure");
let _ = error.trace_error(); }
#[test]
fn test_result_trace_ext() {
let result: Result<(), std::io::Error> = Err(std::io::Error::new(
std::io::ErrorKind::ConnectionRefused,
"Connection refused",
));
drop(result.trace_context());
}
}