@@ -12,6 +12,9 @@ use spin_factors::RuntimeFactors;
1212use spin_factors_executor:: ExecutorHooks ;
1313use tokio:: io:: AsyncWrite ;
1414
15+ pub const STDOUT_LOG_FILE_SUFFIX : & str = "stdout" ;
16+ pub const STDERR_LOG_FILE_SUFFIX : & str = "stderr" ;
17+
1518/// Which components should have their logs followed on stdout/stderr.
1619#[ derive( Clone , Debug , Default ) ]
1720pub enum FollowComponents {
@@ -39,13 +42,19 @@ impl FollowComponents {
3942pub struct StdioLoggingExecutorHooks {
4043 follow_components : FollowComponents ,
4144 log_dir : Option < PathBuf > ,
45+ truncate_log : bool ,
4246}
4347
4448impl StdioLoggingExecutorHooks {
45- pub fn new ( follow_components : FollowComponents , log_dir : Option < PathBuf > ) -> Self {
49+ pub fn new (
50+ follow_components : FollowComponents ,
51+ log_dir : Option < PathBuf > ,
52+ truncate_log : bool ,
53+ ) -> Self {
4654 Self {
4755 follow_components,
4856 log_dir,
57+ truncate_log,
4958 }
5059 }
5160
@@ -86,6 +95,23 @@ impl StdioLoggingExecutorHooks {
8695 _ => Ok ( ( ) ) ,
8796 }
8897 }
98+
99+ fn truncate_log_files ( log_dir : & Path ) {
100+ if let Ok ( entries) = log_dir. read_dir ( ) {
101+ for entry in entries. flatten ( ) {
102+ let path = entry. path ( ) ;
103+ let Some ( name) = path. file_name ( ) . and_then ( |n| n. to_str ( ) ) else {
104+ continue ;
105+ } ;
106+
107+ if name. ends_with ( & format ! ( "{STDOUT_LOG_FILE_SUFFIX}.txt" ) )
108+ || name. ends_with ( & format ! ( "{STDERR_LOG_FILE_SUFFIX}.txt" ) )
109+ {
110+ _ = std:: fs:: File :: create ( path)
111+ }
112+ }
113+ }
114+ }
89115}
90116
91117#[ async_trait]
@@ -95,11 +121,16 @@ impl<F: RuntimeFactors, U> ExecutorHooks<F, U> for StdioLoggingExecutorHooks {
95121 configured_app : & spin_factors:: ConfiguredApp < F > ,
96122 ) -> anyhow:: Result < ( ) > {
97123 self . validate_follows ( configured_app. app ( ) ) ?;
124+
98125 if let Some ( dir) = & self . log_dir {
99126 // Ensure log dir exists if set
100127 std:: fs:: create_dir_all ( dir)
101128 . with_context ( || format ! ( "Failed to create log dir {}" , quoted_path( dir) ) ) ?;
102129
130+ if self . truncate_log {
131+ Self :: truncate_log_files ( dir) ;
132+ }
133+
103134 println ! ( "Logging component stdio to {}" , quoted_path( dir. join( "" ) ) )
104135 }
105136 Ok ( ( ) )
@@ -115,12 +146,12 @@ impl<F: RuntimeFactors, U> ExecutorHooks<F, U> for StdioLoggingExecutorHooks {
115146 } ;
116147 wasi_builder. stdout_pipe ( self . component_stdio_writer (
117148 & component_id,
118- "stdout" ,
149+ STDOUT_LOG_FILE_SUFFIX ,
119150 self . log_dir . as_deref ( ) ,
120151 ) ?) ;
121152 wasi_builder. stderr_pipe ( self . component_stdio_writer (
122153 & component_id,
123- "stderr" ,
154+ STDERR_LOG_FILE_SUFFIX ,
124155 self . log_dir . as_deref ( ) ,
125156 ) ?) ;
126157 Ok ( ( ) )
0 commit comments