@@ -23,7 +23,11 @@ use crate::util::directories::logs_dir;
2323
2424/// Arguments for the logdump command that collects logs for support investigation
2525#[ derive( Debug , PartialEq , Args ) ]
26- pub struct LogdumpArgs ;
26+ pub struct LogdumpArgs {
27+ /// Include MCP logs
28+ #[ arg( long) ]
29+ pub mcp : bool ,
30+ }
2731
2832impl LogdumpArgs {
2933 pub async fn execute ( self , session : & mut ChatSession ) -> Result < ChatState , ChatError > {
@@ -73,9 +77,14 @@ impl LogdumpArgs {
7377 let mut zip = ZipWriter :: new ( file) ;
7478 let mut log_count = 0 ;
7579
76- // Only collect qchat.log (keeping current implementation logic)
80+ // Collect qchat.log
7781 log_count += Self :: collect_qchat_log ( & mut zip, & logs_dir) ?;
7882
83+ // Collect mcp.log if --mcp flag is set
84+ if self . mcp {
85+ log_count += Self :: collect_mcp_log ( & mut zip, & logs_dir) ?;
86+ }
87+
7988 zip. finish ( ) ?;
8089 Ok ( log_count)
8190 }
@@ -91,6 +100,17 @@ impl LogdumpArgs {
91100 Ok ( 0 )
92101 }
93102
103+ fn collect_mcp_log (
104+ zip : & mut ZipWriter < std:: fs:: File > ,
105+ logs_dir : & Path ,
106+ ) -> Result < usize , Box < dyn std:: error:: Error > > {
107+ let mcp_log_path = logs_dir. join ( "mcp.log" ) ;
108+ if mcp_log_path. exists ( ) {
109+ return Self :: add_log_file_to_zip ( & mcp_log_path, zip, "logs" ) ;
110+ }
111+ Ok ( 0 )
112+ }
113+
94114 fn add_log_file_to_zip (
95115 path : & Path ,
96116 zip : & mut ZipWriter < std:: fs:: File > ,
@@ -126,7 +146,7 @@ mod tests {
126146 let logs_dir = temp_dir. path ( ) . join ( "logs" ) ;
127147 fs:: create_dir_all ( & logs_dir) . unwrap ( ) ;
128148
129- let logdump = LogdumpArgs ;
149+ let logdump = LogdumpArgs { mcp : false } ;
130150
131151 // Create the zip file (even if no logs are found, it should create an empty zip)
132152 let result = logdump. create_log_dump ( & zip_path, logs_dir) . await ;
@@ -144,7 +164,7 @@ mod tests {
144164 }
145165
146166 #[ tokio:: test]
147- async fn test_logdump_includes_qchat_log_when_present ( ) {
167+ async fn test_logdump_includes_qchat_log ( ) {
148168 let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
149169 let zip_path = temp_dir. path ( ) . join ( "test-logs.zip" ) ;
150170 let logs_dir = temp_dir. path ( ) . join ( "logs" ) ;
@@ -154,7 +174,7 @@ mod tests {
154174 let qchat_log_path = logs_dir. join ( "qchat.log" ) ;
155175 fs:: write ( & qchat_log_path, "test log content" ) . unwrap ( ) ;
156176
157- let logdump = LogdumpArgs ;
177+ let logdump = LogdumpArgs { mcp : false } ;
158178
159179 let result = logdump. create_log_dump ( & zip_path, logs_dir) . await ;
160180
@@ -173,4 +193,46 @@ mod tests {
173193 std:: io:: Read :: read_to_string ( & mut log_file, & mut contents) . unwrap ( ) ;
174194 assert_eq ! ( contents, "test log content" ) ;
175195 }
196+
197+ #[ tokio:: test]
198+ async fn test_logdump_includes_qchat_log_with_mcp_log ( ) {
199+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
200+ let zip_path = temp_dir. path ( ) . join ( "test-logs.zip" ) ;
201+ let logs_dir = temp_dir. path ( ) . join ( "logs" ) ;
202+ fs:: create_dir_all ( & logs_dir) . unwrap ( ) ;
203+
204+ // Create test log files
205+ let qchat_log_path = logs_dir. join ( "qchat.log" ) ;
206+ fs:: write ( & qchat_log_path, "qchat log content" ) . unwrap ( ) ;
207+ let mcp_log_path = logs_dir. join ( "mcp.log" ) ;
208+ fs:: write ( & mcp_log_path, "mcp log content" ) . unwrap ( ) ;
209+
210+ let logdump = LogdumpArgs { mcp : true } ;
211+
212+ let result = logdump. create_log_dump ( & zip_path, logs_dir) . await ;
213+
214+ // The function should succeed and include 2 log files
215+ assert ! ( result. is_ok( ) ) ;
216+ assert_eq ! ( result. unwrap( ) , 2 ) ;
217+ assert ! ( zip_path. exists( ) ) ;
218+
219+ // Verify the zip contains both log files
220+ let file = fs:: File :: open ( & zip_path) . unwrap ( ) ;
221+ let mut archive = zip:: ZipArchive :: new ( file) . unwrap ( ) ;
222+ assert_eq ! ( archive. len( ) , 2 ) ;
223+
224+ {
225+ let mut qchat_file = archive. by_name ( "logs/qchat.log" ) . unwrap ( ) ;
226+ let mut qchat_contents = String :: new ( ) ;
227+ std:: io:: Read :: read_to_string ( & mut qchat_file, & mut qchat_contents) . unwrap ( ) ;
228+ assert_eq ! ( qchat_contents, "qchat log content" ) ;
229+ }
230+
231+ {
232+ let mut mcp_file = archive. by_name ( "logs/mcp.log" ) . unwrap ( ) ;
233+ let mut mcp_contents = String :: new ( ) ;
234+ std:: io:: Read :: read_to_string ( & mut mcp_file, & mut mcp_contents) . unwrap ( ) ;
235+ assert_eq ! ( mcp_contents, "mcp log content" ) ;
236+ }
237+ }
176238}
0 commit comments