fix: standardize log prefixes, remove duplicates, add missing module tags

Second-pass logging cleanup: consistent [LEVEL] [module] format across
all 41 files. Remove stale prefixes ([CF], [SYNC], [SCHED], [API],
[STORAGE], [HEALTH], [ROLLBACK]). Remove 5 duplicate log lines. Gate
ungated DEBUG lines. Fix wrong log levels (restore start WARN→INFO).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-26 21:20:09 +01:00
parent 8e61cd7ec4
commit af1dd14933
41 changed files with 477 additions and 473 deletions
+45 -45
View File
@@ -150,7 +150,7 @@ type BackupStatus struct {
// NewManager creates a new backup manager.
func NewManager(cfg *config.Config, pinger *monitor.Pinger, sett *settings.Settings, logger *log.Logger) *Manager {
if cfg.Paths.SystemDataPath == "" {
logger.Printf("[WARN] SystemDataPath is empty in config — SSD-only apps will not have correct backup paths")
logger.Printf("[WARN] [backup] SystemDataPath is empty in config — SSD-only apps will not have correct backup paths")
}
dataDir := cfg.Paths.DataDir
if dataDir == "" {
@@ -178,7 +178,7 @@ func (m *Manager) GetAppDrivePath(stackName string) string {
}
}
if m.systemDataPath == "" {
m.logger.Printf("[ERROR] systemDataPath is empty — cannot determine drive for %s", stackName)
m.logger.Printf("[ERROR] [backup] systemDataPath is empty — cannot determine drive for %s", stackName)
}
return m.systemDataPath
}
@@ -238,16 +238,16 @@ func (m *Manager) RunDBDumps(ctx context.Context) error {
// runDBDumpsInternal is the implementation of RunDBDumps. Caller must hold the running flag.
func (m *Manager) runDBDumpsInternal(ctx context.Context) error {
start := time.Now()
m.logger.Printf("[INFO] Starting database dump run")
m.logger.Printf("[INFO] [backup] Starting database dump run")
dbs, err := DiscoverDatabases(ctx, m.logger, m.isDebug())
if err != nil {
m.logger.Printf("[ERROR] Database discovery failed: %v", err)
m.logger.Printf("[ERROR] [backup] Database discovery failed: %v", err)
return err
}
if len(dbs) == 0 {
m.logger.Printf("[INFO] No database containers found")
m.logger.Printf("[INFO] [backup] No database containers found")
m.mu.Lock()
m.lastDBDump = &DBDumpStatus{
LastRun: time.Now(),
@@ -258,7 +258,7 @@ func (m *Manager) runDBDumpsInternal(ctx context.Context) error {
return nil
}
m.logger.Printf("[INFO] Discovered %d database(s): %s", len(dbs), dbNames(dbs))
m.logger.Printf("[INFO] [backup] Discovered %d database(s): %s", len(dbs), dbNames(dbs))
// Dump each DB to its app's drive path
var results []DumpResult
@@ -271,12 +271,12 @@ func (m *Manager) runDBDumpsInternal(ctx context.Context) error {
// Skip if drive is disconnected or decommissioned
if m.settings != nil && m.settings.IsDisconnected(drivePath) {
m.logger.Printf("[WARN] Skipping DB dump for %s — drive disconnected: %s", db.StackName, drivePath)
m.logger.Printf("[WARN] [backup] Skipping DB dump for %s — drive disconnected: %s", db.StackName, drivePath)
summary = append(summary, fmt.Sprintf("SKIP %s (drive disconnected)", db.ContainerName))
continue
}
if m.settings != nil && m.settings.IsDecommissioned(drivePath) {
m.logger.Printf("[WARN] Skipping DB dump for %s — drive decommissioned: %s", db.StackName, drivePath)
m.logger.Printf("[WARN] [backup] Skipping DB dump for %s — drive decommissioned: %s", db.StackName, drivePath)
summary = append(summary, fmt.Sprintf("SKIP %s (drive decommissioned)", db.ContainerName))
continue
}
@@ -289,7 +289,7 @@ func (m *Manager) runDBDumpsInternal(ctx context.Context) error {
if result.Error != nil {
allOK = false
summary = append(summary, fmt.Sprintf("FAIL %s: %v", result.DB.ContainerName, result.Error))
m.logger.Printf("[ERROR] DB dump failed for %s: %v", result.DB.ContainerName, result.Error)
m.logger.Printf("[ERROR] [backup] DB dump failed for %s: %v", result.DB.ContainerName, result.Error)
} else {
totalSize += result.Size
summary = append(summary, fmt.Sprintf("OK %s (%s)", result.DB.ContainerName, humanizeBytes(result.Size)))
@@ -306,7 +306,7 @@ func (m *Manager) runDBDumpsInternal(ctx context.Context) error {
cache.Error = result.Validation.Error
}
if err := m.settings.SetDBValidation(filename, cache); err != nil {
m.logger.Printf("[WARN] Failed to cache validation for %s: %v", filename, err)
m.logger.Printf("[WARN] [backup] Failed to cache validation for %s: %v", filename, err)
}
}
}
@@ -329,7 +329,7 @@ func (m *Manager) runDBDumpsInternal(ctx context.Context) error {
if allOK {
m.pinger.Ping(uuid, body)
m.logger.Printf("[INFO] DB dump completed: %d databases, %s total (%s)",
m.logger.Printf("[INFO] [backup] DB dump completed: %d databases, %s total (%s)",
len(results), humanizeBytes(totalSize), duration.Round(time.Millisecond))
} else {
m.pinger.Fail(uuid, body)
@@ -352,16 +352,16 @@ func (m *Manager) RunBackup(ctx context.Context) error {
func (m *Manager) runBackupInternal(ctx context.Context) error {
// Skip if a full drive migration is in progress
if m.MigrationActiveCheck != nil && m.MigrationActiveCheck() {
m.logger.Printf("[WARN] Skipping nightly backup — drive migration in progress")
m.logger.Printf("[WARN] [backup] Skipping nightly backup — drive migration in progress")
return nil
}
start := time.Now()
m.logger.Printf("[INFO] Starting restic backup (per-drive)")
m.logger.Printf("[INFO] [backup] Starting restic backup (per-drive)")
driveStacks := m.groupStacksByDrive()
if len(driveStacks) == 0 {
m.logger.Printf("[INFO] No deployed stacks — skipping backup")
m.logger.Printf("[INFO] [backup] No deployed stacks — skipping backup")
return nil
}
@@ -436,7 +436,7 @@ func (m *Manager) runBackupInternal(ctx context.Context) error {
duration.Round(time.Second))
m.pinger.Ping(m.cfg.Monitoring.PingUUIDs.Backup, body)
m.logger.Printf("[INFO] Restic backup completed: %d drives, snapshot %s, %d new, %d changed, %s added (%s)",
m.logger.Printf("[INFO] [backup] Restic backup completed: %d drives, snapshot %s, %d new, %d changed, %s added (%s)",
driveCount, lastResult.SnapshotID, lastResult.FilesNew, lastResult.FilesChanged, lastResult.DataAdded,
duration.Round(time.Millisecond))
}
@@ -454,11 +454,11 @@ func (m *Manager) runBackupInternal(ctx context.Context) error {
func (m *Manager) backupDrive(ctx context.Context, drivePath string, stacks []StackSummary, infraPaths []string) (*SnapshotResult, error) {
// Skip disconnected or decommissioned drives
if m.settings != nil && m.settings.IsDisconnected(drivePath) {
m.logger.Printf("[WARN] Skipping backup for drive %s — disconnected", drivePath)
m.logger.Printf("[WARN] [backup] Skipping backup for drive %s — disconnected", drivePath)
return nil, nil
}
if m.settings != nil && m.settings.IsDecommissioned(drivePath) {
m.logger.Printf("[WARN] Skipping backup for drive %s — decommissioned", drivePath)
m.logger.Printf("[WARN] [backup] Skipping backup for drive %s — decommissioned", drivePath)
return nil, nil
}
@@ -466,7 +466,7 @@ func (m *Manager) backupDrive(ctx context.Context, drivePath string, stacks []St
// Ensure repo is initialized
if err := m.restic.EnsureInitialized(repoPath); err != nil {
m.logger.Printf("[ERROR] Restic init failed for %s: %v", repoPath, err)
m.logger.Printf("[ERROR] [backup] Restic init failed for %s: %v", repoPath, err)
return nil, err
}
@@ -506,19 +506,19 @@ func (m *Manager) backupDrive(ctx context.Context, drivePath string, stacks []St
}
tags := []string{"felhom", m.cfg.Customer.ID, filepath.Base(drivePath)}
m.logger.Printf("[INFO] Backing up drive %s (%d apps, %d paths)", drivePath, len(stacks), len(paths))
m.logger.Printf("[INFO] [backup] Backing up drive %s (%d apps, %d paths)", drivePath, len(stacks), len(paths))
result, err := m.restic.Snapshot(repoPath, paths, tags)
if err != nil {
m.logger.Printf("[ERROR] Restic backup failed for drive %s: %v", drivePath, err)
m.logger.Printf("[ERROR] [backup] Restic backup failed for drive %s: %v", drivePath, err)
return nil, err
}
// Prune check (weekly — Sunday)
if shouldPrune(m.cfg.Backup.PruneSchedule) {
m.logger.Printf("[INFO] Running weekly prune for %s", repoPath)
m.logger.Printf("[INFO] [backup] Running weekly prune for %s", repoPath)
if err := m.restic.Prune(repoPath, m.cfg.Backup.Retention); err != nil {
m.logger.Printf("[WARN] Restic prune failed for %s: %v", repoPath, err)
m.logger.Printf("[WARN] [backup] Restic prune failed for %s: %v", repoPath, err)
}
}
@@ -548,7 +548,7 @@ func (m *Manager) TryRunDriveBackup(ctx context.Context, drivePath string) error
driveStacks := m.groupStacksByDrive()
stacks, ok := driveStacks[drivePath]
if !ok || len(stacks) == 0 {
m.logger.Printf("[INFO] No deployed stacks on drive %s — skipping backup", drivePath)
m.logger.Printf("[INFO] [backup] No deployed stacks on drive %s — skipping backup", drivePath)
return nil
}
@@ -563,7 +563,7 @@ func (m *Manager) TryRunDriveBackup(ctx context.Context, drivePath string) error
}
if result != nil {
m.logger.Printf("[INFO] Single-drive backup for %s: snapshot %s, %d new, %d changed, %s added",
m.logger.Printf("[INFO] [backup] Single-drive backup for %s: snapshot %s, %d new, %d changed, %s added",
drivePath, result.SnapshotID, result.FilesNew, result.FilesChanged, result.DataAdded)
}
@@ -572,12 +572,12 @@ func (m *Manager) TryRunDriveBackup(ctx context.Context, drivePath string) error
// RunIntegrityCheck runs restic check on all primary repos and pings healthchecks.
func (m *Manager) RunIntegrityCheck(ctx context.Context) error {
m.logger.Printf("[INFO] Starting restic integrity check")
m.logger.Printf("[INFO] [backup] Starting restic integrity check")
start := time.Now()
drives := m.activeDrives()
if len(drives) == 0 {
m.logger.Printf("[INFO] No active drives — skipping integrity check")
m.logger.Printf("[INFO] [backup] No active drives — skipping integrity check")
return nil
}
@@ -598,7 +598,7 @@ func (m *Manager) RunIntegrityCheck(ctx context.Context) error {
m.logger.Printf("[DEBUG] RunIntegrityCheck: checking repo %s", repoPath)
}
if err := m.restic.Check(repoPath); err != nil {
m.logger.Printf("[ERROR] Restic check failed for %s: %v", repoPath, err)
m.logger.Printf("[ERROR] [backup] Restic check failed for %s: %v", repoPath, err)
checkErr = err
} else if m.isDebug() {
m.logger.Printf("[DEBUG] RunIntegrityCheck: repo %s OK", repoPath)
@@ -614,12 +614,12 @@ func (m *Manager) RunIntegrityCheck(ctx context.Context) error {
m.mu.Unlock()
if checkErr != nil {
m.logger.Printf("[ERROR] Restic integrity check failed (%s): %v", duration.Round(time.Second), checkErr)
m.logger.Printf("[ERROR] [backup] Restic integrity check failed (%s): %v", duration.Round(time.Second), checkErr)
m.pinger.Fail(uuid, fmt.Sprintf("restic check failed: %v", checkErr))
return checkErr
}
m.logger.Printf("[INFO] Restic integrity check passed (%d repos, %s)", len(drives), duration.Round(time.Second))
m.logger.Printf("[INFO] [backup] Restic integrity check passed (%d repos, %s)", len(drives), duration.Round(time.Second))
m.pinger.Ping(uuid, fmt.Sprintf("restic check passed (%d repos, %s)", len(drives), duration.Round(time.Second)))
return nil
}
@@ -646,7 +646,7 @@ func (m *Manager) RunFullBackup(ctx context.Context) error {
m.logger.Printf("[DEBUG] RunFullBackup: phase 1 — database dumps")
}
if err := m.runDBDumpsInternal(ctx); err != nil {
m.logger.Printf("[WARN] DB dump had errors, continuing with backup anyway")
m.logger.Printf("[WARN] [backup] DB dump had errors, continuing with backup anyway")
}
// Step 2: Restic backup
@@ -713,7 +713,7 @@ func (m *Manager) ListSnapshots(limit int) ([]SnapshotInfo, error) {
}
snapshots, err := m.restic.ListSnapshots(repoPath, 0)
if err != nil {
m.logger.Printf("[WARN] Could not list snapshots from %s: %v", repoPath, err)
m.logger.Printf("[WARN] [backup] Could not list snapshots from %s: %v", repoPath, err)
continue
}
for i := range snapshots {
@@ -744,7 +744,7 @@ func (m *Manager) ListAllSnapshots(limit int) ([]SnapshotInfo, error) {
}
snapshots, err := m.restic.ListSnapshots(repoPath, 0)
if err != nil {
m.logger.Printf("[WARN] Could not list snapshots from %s: %v", repoPath, err)
m.logger.Printf("[WARN] [backup] Could not list snapshots from %s: %v", repoPath, err)
continue
}
for i := range snapshots {
@@ -782,7 +782,7 @@ func (m *Manager) UnlockRepo(ctx context.Context, repoPath string) error {
if err != nil {
return fmt.Errorf("restic unlock: %v (%s)", err, strings.TrimSpace(string(out)))
}
m.logger.Printf("[INFO] Restic repo unlocked: %s", repoPath)
m.logger.Printf("[INFO] [backup] Restic repo unlocked: %s", repoPath)
return nil
}
@@ -819,14 +819,14 @@ func (m *Manager) DumpStackDB(ctx context.Context, stackName string) error {
}
dumpDir := AppDBDumpPath(drivePath, stackName)
m.logger.Printf("[INFO] Running pre-backup DB dump for %s (%d database(s)) → %s", stackName, len(stackDBs), dumpDir)
m.logger.Printf("[INFO] [backup] Running pre-backup DB dump for %s (%d database(s)) → %s", stackName, len(stackDBs), dumpDir)
for _, db := range stackDBs {
result := DumpOne(ctx, db, dumpDir, m.logger, m.isDebug())
if result.Error != nil {
return fmt.Errorf("DB dump failed for %s: %w", result.DB.ContainerName, result.Error)
}
m.logger.Printf("[INFO] Pre-backup DB dump OK: %s (%s)", result.DB.ContainerName, humanizeBytes(result.Size))
m.logger.Printf("[INFO] [backup] Pre-backup DB dump OK: %s (%s)", result.DB.ContainerName, humanizeBytes(result.Size))
// Persist validation to settings
if m.settings != nil && result.FilePath != "" {
@@ -973,16 +973,16 @@ func (m *Manager) saveSnapshotHistory() {
}
data, err := json.Marshal(m.snapshotHistory)
if err != nil {
m.logger.Printf("[WARN] Could not marshal snapshot history: %v", err)
m.logger.Printf("[WARN] [backup] Could not marshal snapshot history: %v", err)
return
}
tmp := m.snapshotHistoryFile + ".tmp"
if err := os.WriteFile(tmp, data, 0644); err != nil {
m.logger.Printf("[WARN] Could not write snapshot history tmp file: %v", err)
m.logger.Printf("[WARN] [backup] Could not write snapshot history tmp file: %v", err)
return
}
if err := os.Rename(tmp, m.snapshotHistoryFile); err != nil {
m.logger.Printf("[WARN] Could not rename snapshot history file: %v", err)
m.logger.Printf("[WARN] [backup] Could not rename snapshot history file: %v", err)
return
}
m.logger.Printf("[INFO] [backup] Saved snapshot history (%d entries)", len(m.snapshotHistory))
@@ -997,13 +997,13 @@ func (m *Manager) loadSnapshotHistoryFromFile() []SnapshotRecord {
data, err := os.ReadFile(m.snapshotHistoryFile)
if err != nil {
if !os.IsNotExist(err) {
m.logger.Printf("[WARN] Could not read snapshot history file: %v", err)
m.logger.Printf("[WARN] [backup] Could not read snapshot history file: %v", err)
}
return nil
}
var records []SnapshotRecord
if err := json.Unmarshal(data, &records); err != nil {
m.logger.Printf("[WARN] Could not parse snapshot history file: %v", err)
m.logger.Printf("[WARN] [backup] Could not parse snapshot history file: %v", err)
return nil
}
return records
@@ -1033,7 +1033,7 @@ func (m *Manager) LoadSnapshotHistory() {
}
snapshots, err := m.restic.ListSnapshots(repoPath, 20)
if err != nil {
m.logger.Printf("[WARN] Could not load snapshot history from %s: %v", repoPath, err)
m.logger.Printf("[WARN] [backup] Could not load snapshot history from %s: %v", repoPath, err)
continue
}
allSnapshots = append(allSnapshots, snapshots...)
@@ -1064,7 +1064,7 @@ func (m *Manager) LoadSnapshotHistory() {
sort.Slice(m.snapshotHistory, func(i, j int) bool {
return m.snapshotHistory[i].Time.Before(m.snapshotHistory[j].Time)
})
m.logger.Printf("[INFO] Loaded %d snapshots from persisted history (merged with %d restic entries)", len(persisted), len(allSnapshots))
m.logger.Printf("[INFO] [backup] Loaded %d snapshots from persisted history (merged with %d restic entries)", len(persisted), len(allSnapshots))
} else {
// No persisted file — fall back to restic-only loading (first run)
for _, s := range allSnapshots {
@@ -1075,7 +1075,7 @@ func (m *Manager) LoadSnapshotHistory() {
Success: true,
})
}
m.logger.Printf("[INFO] Loaded %d historical snapshots from %d restic repos (no persisted history)", len(m.snapshotHistory), len(drives))
m.logger.Printf("[INFO] [backup] Loaded %d historical snapshots from %d restic repos (no persisted history)", len(m.snapshotHistory), len(drives))
}
if len(m.snapshotHistory) > 20 {
@@ -1139,7 +1139,7 @@ func (m *Manager) RefreshCache(nextDBDump, nextBackup time.Time) {
filename := filepath.Base(r.FilePath)
if fv, ok := fileValidation[filename]; ok {
m.lastDBDump.Results[i].Validation = fv
m.logger.Printf("[INFO] Re-validated %s from disk: valid=%v tables=%d",
m.logger.Printf("[INFO] [backup] Re-validated %s from disk: valid=%v tables=%d",
filename, fv.Valid, fv.TableCount)
}
}
@@ -1155,7 +1155,7 @@ func (m *Manager) RefreshCache(nextDBDump, nextBackup time.Time) {
m.cacheTime = time.Now()
m.mu.Unlock()
m.logger.Printf("[INFO] Backup status cache refreshed")
m.logger.Printf("[INFO] [backup] Backup status cache refreshed")
}
// GetFullStatus returns the cached backup status for page rendering.