claude_code_acp/tracing/
error_ext.rs

1//! Error tracing extensions
2//!
3//! Provides utilities for enriching error handling with tracing context.
4
5use crate::types::AgentError;
6use std::error::Error as StdError;
7
8/// Extension trait for adding tracing context to errors
9pub trait ErrorTraceExt {
10    /// Log error with full context including error code, retryable status, and error chain
11    fn trace_error(&self) -> &Self;
12}
13
14impl ErrorTraceExt for AgentError {
15    fn trace_error(&self) -> &Self {
16        // Check if this error type supports error_code and is_retryable
17        let error_code = self.error_code();
18        let is_retryable = self.is_retryable();
19        let is_client_error = self.is_client_error();
20
21        // Get the error chain
22        let mut error_chain = Vec::new();
23        let mut current_source = self.source();
24        while let Some(source) = current_source {
25            error_chain.push(source.to_string());
26            current_source = source.source();
27        }
28
29        tracing::error!(
30            error = %self,
31            error_code = error_code.code(),
32            error_code_name = ?error_code,
33            is_retryable = is_retryable,
34            is_client_error = is_client_error,
35            error_chain_len = error_chain.len(),
36            error_chain = ?error_chain,
37            "Error occurred with full context"
38        );
39
40        self
41    }
42}
43
44/// Extension trait for Result types
45pub trait ResultTraceExt<T, E>: Sized {
46    /// Convert error to AgentError and log with context
47    fn trace_context(self) -> Result<T, AgentError>
48    where
49        E: StdError + Send + Sync + 'static;
50}
51
52impl<T, E> ResultTraceExt<T, E> for Result<T, E>
53where
54    E: StdError + Send + Sync + 'static,
55    AgentError: From<E>,
56{
57    fn trace_context(self) -> Result<T, AgentError> {
58        self.map_err(|e| {
59            let agent_error = AgentError::from(e);
60            agent_error.trace_error();
61            agent_error
62        })
63    }
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69
70    #[test]
71    fn test_error_trace_ext() {
72        let error = AgentError::connection_failed("Test connection failure");
73        let _ = error.trace_error(); // Should log without panic
74    }
75
76    #[test]
77    fn test_result_trace_ext() {
78        let result: Result<(), std::io::Error> = Err(std::io::Error::new(
79            std::io::ErrorKind::ConnectionRefused,
80            "Connection refused",
81        ));
82
83        // This should convert to AgentError and log
84        drop(result.trace_context());
85    }
86}