Keep rotated log files for a set number of days
Personal-data catalog spec, default D1 (settled 2026-09-28): log files were never deleted. inbuxa:LogSettings.keepForDays says how many days rotated log files are kept; unset (null) keeps every file, as before, and a new install sets 30 days. It is a fork-owned setting, stored under T + l as audit retention is, not a field on x:TracerLog: that object is also stored inside x:Bootstrap with a field after it, so a new field would change x:Bootstrap's stored format. Server-level, with the tracers' permissions (sysTracerGet, sysTracerUpdate); changes are in the audit log, before and after. Log files are local, so every node deletes its own: hourly, and at once when the setting changes on that node. Only regular files named <prefix>.<something> in each enabled log tracer's directory, last changed more than the limit ago, are removed; the file being written is never that old, and nothing else in the directory is touched. Minimum one day. The catalog classifies inbuxa:LogSettings and points the log file's retention at it. Tested: unit tests for the file rule (only this log's old files; the current file, other files and directories stay) and a purge on disk; the system suite, which reads, sets, refuses zero, restores null and checks the audit records; fork checks.
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Coffey Labs
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
//! Deletes rotated log files past `inbuxa:LogSettings.keepForDays`
|
||||
//! (personal-data catalog spec, D1). Log files are local, so every node
|
||||
//! cleans its own: hourly, and at once when the settings change here.
|
||||
|
||||
use common::{BuildServer, Inner, Server};
|
||||
use inbuxa_features::security::log_files;
|
||||
use registry::schema::structs::Tracer;
|
||||
use std::{path::PathBuf, sync::Arc, time::Duration};
|
||||
|
||||
const EVERY: Duration = Duration::from_secs(3600);
|
||||
|
||||
pub fn spawn_log_retention(inner: Arc<Inner>) {
|
||||
tokio::spawn(async move {
|
||||
loop {
|
||||
let server = inner.build_server();
|
||||
if let Err(err) = purge(&server).await {
|
||||
trc::error!(err.details("Failed to delete old log files"));
|
||||
}
|
||||
tokio::select! {
|
||||
_ = tokio::time::sleep(EVERY) => {}
|
||||
_ = log_files::CHANGED.notified() => {}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async fn purge(server: &Server) -> trc::Result<()> {
|
||||
let Some(days) = log_files::get(&server.core.storage.data)
|
||||
.await?
|
||||
.keep_for_days
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
let keep = Duration::from_secs(days.max(log_files::MIN_KEEP_DAYS) * 86_400);
|
||||
for tracer in server.registry().list::<Tracer>().await? {
|
||||
let Tracer::Log(log) = tracer.object else {
|
||||
continue;
|
||||
};
|
||||
if !log.enable || log.path.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let (dir, prefix) = (PathBuf::from(&log.path), log.prefix.clone());
|
||||
let result = tokio::task::spawn_blocking(move || log_files::purge(&dir, &prefix, keep))
|
||||
.await
|
||||
.map_err(|err| trc::EventType::Server(trc::ServerEvent::ThreadError).reason(err))?;
|
||||
if let Err(err) = result {
|
||||
trc::event!(
|
||||
Telemetry(trc::TelemetryEvent::LogError),
|
||||
Details = "Failed to delete old log files",
|
||||
Path = log.path.clone(),
|
||||
Reason = err.to_string(),
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -25,6 +25,7 @@ use crate::task_manager::{manager::spawn_task_manager, scheduler::spawn_task_sch
|
||||
pub mod broadcast;
|
||||
// inbuxa: AL-5, delegations end at their date
|
||||
pub mod inbuxa_lock_expiry;
|
||||
pub mod inbuxa_log_retention; // inbuxa: personal-data catalog, D1
|
||||
pub mod state_manager;
|
||||
pub mod task_manager;
|
||||
|
||||
@@ -70,6 +71,9 @@ impl SpawnServices for IpcReceivers {
|
||||
// inbuxa: AL-5, end delegations at their `until`
|
||||
inbuxa_lock_expiry::spawn_lock_expiry(inner.clone());
|
||||
|
||||
// inbuxa: personal-data catalog, D1: old log files go, per node
|
||||
inbuxa_log_retention::spawn_log_retention(inner.clone());
|
||||
|
||||
// Spawn task scheduler
|
||||
spawn_task_scheduler(inner);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user