Skip to content

Commit 52bf7f6

Browse files
committed
feat: truncates log files on restart
- added flag for clearing log files at restart Signed-off-by: Aminu 'Seun Joshua <[email protected]> - refactor: renaming + login Signed-off-by: Aminu 'Seun Joshua <[email protected]> - refactor: creates instead of delete Signed-off-by: Aminu 'Seun Joshua <[email protected]> - warn of error Signed-off-by: Aminu 'Seun Joshua <[email protected]> - revert format Signed-off-by: Aminu 'Seun Joshua <[email protected]> - some renaming + cleaner code Signed-off-by: Aminu 'Seun Joshua <[email protected]> - clean up Signed-off-by: Aminu 'Seun Joshua <[email protected]> - handled file creation without duplicates Signed-off-by: Aminu 'Seun Joshua <[email protected]> - cleanup Signed-off-by: Aminu 'Seun Joshua <[email protected]> - reduce redundancy Signed-off-by: Aminu 'Seun Joshua <[email protected]> - improved readability Signed-off-by: Aminu 'Seun Joshua <[email protected]>
1 parent 2860166 commit 52bf7f6

File tree

3 files changed

+46
-3
lines changed

3 files changed

+46
-3
lines changed

crates/runtime-factors/src/build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ impl RuntimeFactorsBuilder for FactorsBuilder {
5050
executor.add_hooks(StdioLoggingExecutorHooks::new(
5151
config.follow_components.clone(),
5252
runtime_config.log_dir(),
53+
config.truncate_logs,
5354
));
5455
executor.add_hooks(SqlStatementExecutorHook::new(
5556
args.sqlite_statements.clone(),

crates/trigger/src/cli.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub use stdio::StdioLoggingExecutorHooks;
2727
pub use summary::{KeyValueDefaultStoreSummaryHook, SqliteDefaultStoreSummaryHook};
2828

2929
pub const APP_LOG_DIR: &str = "APP_LOG_DIR";
30+
pub const SPIN_TRUNCATE_LOGS: &str = "SPIN_TRUNCATE_LOGS";
3031
pub const DISABLE_WASMTIME_CACHE: &str = "DISABLE_WASMTIME_CACHE";
3132
pub const FOLLOW_LOG_OPT: &str = "FOLLOW_ID";
3233
pub const WASMTIME_CACHE_FILE: &str = "WASMTIME_CACHE_FILE";
@@ -54,6 +55,13 @@ pub struct FactorsTriggerCommand<T: Trigger<B::Factors>, B: RuntimeFactorsBuilde
5455
)]
5556
pub log: Option<PathBuf>,
5657

58+
/// If set, Spin truncates the log files before starting the application.
59+
#[clap(
60+
name = SPIN_TRUNCATE_LOGS,
61+
long = "truncate-logs",
62+
)]
63+
pub truncate_logs: bool,
64+
5765
/// Disable Wasmtime cache.
5866
#[clap(
5967
name = DISABLE_WASMTIME_CACHE,
@@ -139,6 +147,8 @@ pub struct FactorsConfig {
139147
pub follow_components: FollowComponents,
140148
/// Log directory for component stdout/stderr.
141149
pub log_dir: UserProvidedPath,
150+
/// If set, Spin truncates the log files before starting the application.
151+
pub truncate_logs: bool,
142152
}
143153

144154
/// An empty implementation of clap::Args to be used as TriggerExecutor::RunConfig
@@ -220,6 +230,7 @@ impl<T: Trigger<B::Factors>, B: RuntimeFactorsBuilder> FactorsTriggerCommand<T,
220230
local_app_dir: local_app_dir.clone(),
221231
follow_components,
222232
log_dir,
233+
truncate_logs: self.truncate_logs,
223234
};
224235

225236
let run_fut = builder

crates/trigger/src/cli/stdio.rs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ use spin_factors::RuntimeFactors;
1212
use spin_factors_executor::ExecutorHooks;
1313
use 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)]
1720
pub enum FollowComponents {
@@ -39,13 +42,19 @@ impl FollowComponents {
3942
pub struct StdioLoggingExecutorHooks {
4043
follow_components: FollowComponents,
4144
log_dir: Option<PathBuf>,
45+
truncate_log: bool,
4246
}
4347

4448
impl 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

Comments
 (0)