claude_code_acp/tracing/
error_ext.rs1use crate::types::AgentError;
6use std::error::Error as StdError;
7
8pub trait ErrorTraceExt {
10 fn trace_error(&self) -> &Self;
12}
13
14impl ErrorTraceExt for AgentError {
15 fn trace_error(&self) -> &Self {
16 let error_code = self.error_code();
18 let is_retryable = self.is_retryable();
19 let is_client_error = self.is_client_error();
20
21 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
44pub trait ResultTraceExt<T, E>: Sized {
46 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(); }
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 drop(result.trace_context());
85 }
86}