package logger import ( "context" "os" "path/filepath" "strings" "time" ) // runCleanup periodically removes log files older than maxAgeDays for the // given agent. It runs until ctx is cancelled. func runCleanup(ctx context.Context, baseDir, agentID string, maxAgeDays int, interval time.Duration) { ticker := time.NewTicker(interval) defer ticker.Stop() // Run once immediately at startup. cleanOldLogs(baseDir, agentID, maxAgeDays) for { select { case <-ctx.Done(): return case <-ticker.C: cleanOldLogs(baseDir, agentID, maxAgeDays) } } } // cleanOldLogs removes .jsonl and .jsonl.gz files older than maxAgeDays. func cleanOldLogs(baseDir, agentID string, maxAgeDays int) { dir := filepath.Join(baseDir, agentID) entries, err := os.ReadDir(dir) if err != nil { return } cutoff := time.Now().UTC().AddDate(0, 0, -maxAgeDays) for _, e := range entries { if e.IsDir() { continue } name := e.Name() if !isLogFile(name) { continue } date := parseDateFromFilename(name) if date.IsZero() { continue } if date.Before(cutoff) { os.Remove(filepath.Join(dir, name)) } } } // isLogFile returns true for .jsonl and .jsonl.gz files. func isLogFile(name string) bool { return strings.HasSuffix(name, ".jsonl") || strings.HasSuffix(name, ".jsonl.gz") } // parseDateFromFilename extracts YYYY-MM-DD from filenames like: // // 2026-03-06.jsonl // 2026-03-06.1.jsonl // 2026-03-06.jsonl.gz func parseDateFromFilename(name string) time.Time { // Strip extensions. base := strings.TrimSuffix(name, ".gz") base = strings.TrimSuffix(base, ".jsonl") // Remove numeric suffix (e.g., ".1" from "2026-03-06.1"). if idx := strings.LastIndex(base, "."); idx >= 0 { candidate := base[:idx] if t, err := time.Parse("2006-01-02", candidate); err == nil { return t } } t, _ := time.Parse("2006-01-02", base) return t }