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
+2
View File
@@ -3,6 +3,7 @@ package backup
import (
"context"
"fmt"
"log"
"os"
"os/exec"
"strings"
@@ -105,6 +106,7 @@ func DiscoverAppData(provider StackDataProvider, discoveredDBs []DiscoveredDB) [
result = append(result, info)
}
log.Printf("[INFO] [backup] Discovered app data: %d apps", len(result))
return result
}
+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.
+20 -19
View File
@@ -117,7 +117,7 @@ func (r *CrossDriveRunner) RunAppBackup(ctx context.Context, stackName string) e
})
start := time.Now()
r.logger.Printf("[INFO] Cross-drive backup starting: %s → %s (rsync)",
r.logger.Printf("[INFO] [backup] Cross-drive backup starting: %s → %s (rsync)",
stackName, cfg.DestinationPath)
// Trigger fresh DB dump for this app before cross-drive backup
@@ -126,7 +126,7 @@ func (r *CrossDriveRunner) RunAppBackup(ctx context.Context, stackName string) e
r.logger.Printf("[DEBUG] RunAppBackup: triggering pre-backup DB dump for %s", stackName)
}
if err := r.dbDumper.DumpStackDB(ctx, stackName); err != nil {
r.logger.Printf("[WARN] Pre-backup DB dump failed for %s: %v — proceeding with user data backup", stackName, err)
r.logger.Printf("[WARN] [backup] Pre-backup DB dump failed for %s: %v — proceeding with user data backup", stackName, err)
// Non-fatal: user data backup is still valuable without fresh dump
}
}
@@ -156,7 +156,7 @@ func (r *CrossDriveRunner) RunAppBackup(ctx context.Context, stackName string) e
duration := time.Since(start)
if runErr != nil {
r.logger.Printf("[ERROR] Cross-drive backup failed: %s: %v", stackName, runErr)
r.logger.Printf("[ERROR] [backup] Cross-drive backup failed: %s: %v", stackName, runErr)
r.updateStatus(stackName, "error", runErr.Error(), duration, "")
return runErr
}
@@ -171,7 +171,7 @@ func (r *CrossDriveRunner) RunAppBackup(ctx context.Context, stackName string) e
}
}
r.logger.Printf("[INFO] Cross-drive backup completed: %s (%s)", stackName, duration.Round(time.Second))
r.logger.Printf("[INFO] [backup] Cross-drive backup completed: %s (%s)", stackName, duration.Round(time.Second))
r.updateStatus(stackName, "ok", "", duration, sizeHuman)
return nil
}
@@ -333,14 +333,14 @@ func (r *CrossDriveRunner) ValidateDestination(path string) error {
r.logger.Printf("[DEBUG] ValidateDestination: path=%s, isMountPoint=%v", path, !onSystemDrive)
}
if onSystemDrive {
r.logger.Printf("[WARN] Destination %s is not a separate mount point (system drive) — backup will proceed but data is not protected against drive failure", path)
r.logger.Printf("[WARN] [backup] Destination %s is not a separate mount point (system drive) — backup will proceed but data is not protected against drive failure", path)
}
if !system.IsWritable(path) {
return fmt.Errorf("destination %s is not writable", path)
}
di := system.GetDiskUsage(path)
if di == nil {
r.logger.Printf("[WARN] Cannot determine disk usage for %s — proceeding without space verification", path)
r.logger.Printf("[WARN] [backup] Cannot determine disk usage for %s — proceeding without space verification", path)
return nil
}
if r.debug {
@@ -417,7 +417,9 @@ func (r *CrossDriveRunner) runRsyncBackup(ctx context.Context, stackName, destBa
"--exclude", "backups/*.sql",
"--exclude", "backups/*.dump",
src, dst)
r.logger.Printf("[DEBUG] rsync: %s → %s", src, dst)
if r.debug {
r.logger.Printf("[DEBUG] rsync: %s → %s", src, dst)
}
out, err := cmd.CombinedOutput()
if err != nil {
if r.debug {
@@ -437,7 +439,7 @@ func (r *CrossDriveRunner) runRsyncBackup(ctx context.Context, stackName, destBa
return fmt.Errorf("creating DB dump dest dir: %w", err)
}
if err := r.copyStackDBDumps(stackName, dbDestDir); err != nil {
r.logger.Printf("[WARN] Cross-drive DB dump copy failed for %s: %v", stackName, err)
r.logger.Printf("[WARN] [backup] Cross-drive DB dump copy failed for %s: %v", stackName, err)
// Non-fatal: user data is the primary concern
}
@@ -451,9 +453,11 @@ func (r *CrossDriveRunner) runRsyncBackup(ctx context.Context, stackName, destBa
src := strings.TrimRight(configSrcDir, "/") + "/"
dst := strings.TrimRight(configDestDir, "/") + "/"
cmd := exec.CommandContext(ctx, "rsync", "-a", "--delete", src, dst)
r.logger.Printf("[DEBUG] rsync config: %s → %s", src, dst)
if r.debug {
r.logger.Printf("[DEBUG] rsync config: %s → %s", src, dst)
}
if out, err := cmd.CombinedOutput(); err != nil {
r.logger.Printf("[WARN] Cross-drive config rsync failed for %s: %v (%s)", stackName, err, strings.TrimSpace(string(out)))
r.logger.Printf("[WARN] [backup] Cross-drive config rsync failed for %s: %v (%s)", stackName, err, strings.TrimSpace(string(out)))
// Non-fatal
}
}
@@ -488,9 +492,6 @@ func (r *CrossDriveRunner) copyStackDBDumps(stackName, destDir string) error {
}
copied++
}
if copied > 0 {
r.logger.Printf("[DEBUG] Copied %d DB dump file(s) to %s", copied, destDir)
}
r.logger.Printf("[INFO] [backup] Copied %d DB dumps for %s", copied, stackName)
return nil
}
@@ -514,7 +515,7 @@ func (r *CrossDriveRunner) syncInfraConfig(ctx context.Context) {
for dest := range destDrives {
infraDir := SecondaryInfraPath(dest)
if err := os.MkdirAll(infraDir, 0755); err != nil {
r.logger.Printf("[WARN] Cannot create infra backup dir %s: %v", infraDir, err)
r.logger.Printf("[WARN] [backup] Cannot create infra backup dir %s: %v", infraDir, err)
continue
}
@@ -524,7 +525,7 @@ func (r *CrossDriveRunner) syncInfraConfig(ctx context.Context) {
stacksSrc := strings.TrimRight(r.stacksDir, "/") + "/"
cmd := exec.CommandContext(ctx, "rsync", "-a", "--delete", stacksSrc, stacksDest)
if out, err := cmd.CombinedOutput(); err != nil {
r.logger.Printf("[WARN] Infra rsync (stacks) failed for %s: %v (%s)", dest, err, strings.TrimSpace(string(out)))
r.logger.Printf("[WARN] [backup] Infra rsync (stacks) failed for %s: %v (%s)", dest, err, strings.TrimSpace(string(out)))
}
}
@@ -532,11 +533,11 @@ func (r *CrossDriveRunner) syncInfraConfig(ctx context.Context) {
if _, err := os.Stat(r.controllerYAMLPath); err == nil {
yamlDest := filepath.Join(infraDir, "controller.yaml")
if err := copyFile(r.controllerYAMLPath, yamlDest); err != nil {
r.logger.Printf("[WARN] Cannot copy controller.yaml to %s: %v", yamlDest, err)
r.logger.Printf("[WARN] [backup] Cannot copy controller.yaml to %s: %v", yamlDest, err)
}
}
r.logger.Printf("[INFO] Infrastructure config synced to %s", infraDir)
r.logger.Printf("[INFO] [backup] Infrastructure config synced to %s", infraDir)
}
}
@@ -604,11 +605,11 @@ func (r *CrossDriveRunner) AutoEnableSmallApps() {
Schedule: "daily",
}
if err := r.sett.SetCrossDriveConfig(stack.Name, cfg); err != nil {
r.logger.Printf("[WARN] Auto-enable Tier 2 failed for %s: %v", stack.Name, err)
r.logger.Printf("[WARN] [backup] Auto-enable Tier 2 failed for %s: %v", stack.Name, err)
continue
}
autoEnabled++
r.logger.Printf("[INFO] Auto-enabled Tier 2 backup for %s → %s (no HDD mounts, daily rsync)", stack.Name, destPath)
r.logger.Printf("[INFO] [backup] Auto-enabled Tier 2 backup for %s → %s (no HDD mounts, daily rsync)", stack.Name, destPath)
}
if r.debug && autoEnabled > 0 {
+8 -10
View File
@@ -117,7 +117,7 @@ func DiscoverDatabases(ctx context.Context, logger *log.Logger, debug bool) ([]D
// Get env vars from container
if err := populateDBEnv(ctx, &db); err != nil {
logger.Printf("[WARN] Could not read env vars for %s: %v", name, err)
logger.Printf("[WARN] [backup] Could not read env vars for %s: %v", name, err)
if debug {
logger.Printf("[DEBUG] DiscoverDatabases: skipping %s — env read failed", name)
}
@@ -310,7 +310,7 @@ func DumpOne(ctx context.Context, db DiscoveredDB, dumpDir string, logger *log.L
result.Validation.Valid, result.Validation.TableCount, result.Duration.Round(time.Millisecond))
}
logger.Printf("[INFO] DB dump: %s → %s (%s, %s, %d tables)", db.ContainerName, filename,
logger.Printf("[INFO] [backup] DB dump: %s → %s (%s, %s, %d tables)", db.ContainerName, filename,
humanizeBytes(stat.Size()), result.Duration.Round(time.Millisecond), result.Validation.TableCount)
return result
@@ -318,7 +318,6 @@ func DumpOne(ctx context.Context, db DiscoveredDB, dumpDir string, logger *log.L
// ValidateDump checks a SQL dump file for basic structural integrity.
func ValidateDump(filePath string, dbType DBType) DumpValidation {
log.Printf("[DEBUG] ValidateDump: %s (type=%s)", filePath, dbType)
stat, err := os.Stat(filePath)
if err != nil {
return DumpValidation{Error: fmt.Sprintf("stat failed: %v", err)}
@@ -331,7 +330,7 @@ func ValidateDump(filePath string, dbType DBType) DumpValidation {
if stat.Size() < 100 {
v.Error = "dump file too small (< 100 bytes)"
log.Printf("[WARN] ValidateDump FAIL: %s — %s", filePath, v.Error)
log.Printf("[WARN] [backup] ValidateDump FAIL: %s — %s", filePath, v.Error)
return v
}
@@ -340,7 +339,7 @@ func ValidateDump(filePath string, dbType DBType) DumpValidation {
f, err := os.Open(filePath)
if err != nil {
v.Error = fmt.Sprintf("read failed: %v", err)
log.Printf("[WARN] ValidateDump FAIL: %s — %s", filePath, v.Error)
log.Printf("[WARN] [backup] ValidateDump FAIL: %s — %s", filePath, v.Error)
return v
}
defer f.Close()
@@ -359,7 +358,7 @@ func ValidateDump(filePath string, dbType DBType) DumpValidation {
if err != nil {
if err != io.EOF {
v.Error = fmt.Sprintf("hiba az olvasás közben: %v", err)
log.Printf("[WARN] ValidateDump FAIL: %s — read error: %v", filePath, err)
log.Printf("[WARN] [backup] ValidateDump FAIL: %s — read error: %v", filePath, err)
return v
}
break // EOF
@@ -408,18 +407,17 @@ func ValidateDump(filePath string, dbType DBType) DumpValidation {
case DBTypePostgres:
v.Error = "PostgreSQL dump missing comment header"
}
log.Printf("[WARN] ValidateDump FAIL: %s — %s", filePath, v.Error)
log.Printf("[WARN] [backup] ValidateDump FAIL: %s — %s", filePath, v.Error)
return v
}
if tableCount == 0 {
v.Error = "no CREATE TABLE statements found"
log.Printf("[WARN] ValidateDump FAIL: %s — %s (header was found, scanned %d lines)", filePath, v.Error, lineNum)
log.Printf("[WARN] [backup] ValidateDump FAIL: %s — %s (header was found, scanned %d lines)", filePath, v.Error, lineNum)
return v
}
v.Valid = true
log.Printf("[DEBUG] ValidateDump OK: %s — %d tables, header found", filePath, tableCount)
return v
}
@@ -570,7 +568,7 @@ func cleanupTmpFiles(dumpDir string, logger *log.Logger) {
if info.ModTime().Before(cutoff) {
path := filepath.Join(dumpDir, e.Name())
os.Remove(path)
logger.Printf("[INFO] Cleaned up stale tmp file: %s", e.Name())
logger.Printf("[INFO] [backup] Cleaned up stale tmp file: %s", e.Name())
}
}
}
+12 -12
View File
@@ -88,7 +88,7 @@ func (r *ResticManager) EnsureInitialized(repoPath string) error {
// Check if repo is already initialized
configPath := filepath.Join(repoPath, "config")
if _, err := os.Stat(configPath); err == nil {
r.logger.Printf("[INFO] Restic repo already initialized at %s", repoPath)
r.logger.Printf("[INFO] [backup] Restic repo already initialized at %s", repoPath)
return nil
}
@@ -98,7 +98,7 @@ func (r *ResticManager) EnsureInitialized(repoPath string) error {
}
// Initialize repo
r.logger.Printf("[INFO] Initializing restic repository at %s", repoPath)
r.logger.Printf("[INFO] [backup] Initializing restic repository at %s", repoPath)
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
@@ -108,7 +108,7 @@ func (r *ResticManager) EnsureInitialized(repoPath string) error {
return fmt.Errorf("restic init failed: %v — %s", err, truncate(string(out), 200))
}
r.logger.Printf("[INFO] Restic repository initialized successfully")
r.logger.Printf("[INFO] [backup] Restic repository initialized successfully")
return nil
}
@@ -134,7 +134,7 @@ func (r *ResticManager) Snapshot(repoPath string, paths []string, tags []string)
if _, err := os.Stat(p); err == nil {
existingPaths = append(existingPaths, p)
} else {
r.logger.Printf("[WARN] Backup path does not exist, skipping: %s", p)
r.logger.Printf("[WARN] [backup] Backup path does not exist, skipping: %s", p)
}
}
@@ -155,10 +155,10 @@ func (r *ResticManager) Snapshot(repoPath string, paths []string, tags []string)
errStr += string(exitErr.Stderr)
}
if strings.Contains(errStr, "lock") || strings.Contains(errStr, "locked") {
r.logger.Printf("[WARN] Restic repo locked — attempting unlock")
r.logger.Printf("[WARN] [backup] Restic repo locked — attempting unlock")
unlockCmd := r.command(ctx, repoPath, "unlock")
if unlockErr := unlockCmd.Run(); unlockErr != nil {
r.logger.Printf("[WARN] Restic unlock failed: %v", unlockErr)
r.logger.Printf("[WARN] [backup] Restic unlock failed: %v", unlockErr)
}
// Retry once with a fresh context (H9 fix — original may be nearly expired).
retryCtx, retryCancel := context.WithTimeout(context.Background(), 30*time.Minute)
@@ -239,7 +239,7 @@ func (r *ResticManager) Prune(repoPath string, retention config.RetentionConfig)
if r.debug {
r.logger.Printf("[DEBUG] [restic] Prune: completed in %s, output=%d bytes", time.Since(start), len(out))
}
r.logger.Printf("[INFO] Restic prune completed for %s", repoPath)
r.logger.Printf("[INFO] [backup] Restic prune completed for %s", repoPath)
return nil
}
@@ -420,19 +420,19 @@ func (r *ResticManager) RestoreAppData(repoPath string, snapshotID string, paths
}
start := time.Now()
r.logger.Printf("[WARN] RESTORE started: repo=%s, snapshot=%s, paths=%v", repoPath, snapshotID, paths)
r.logger.Printf("[INFO] [backup] Restore started: repo=%s, snapshot=%s, paths=%v", repoPath, snapshotID, paths)
cmd := r.command(ctx, repoPath, args...)
output, err := cmd.CombinedOutput()
if err != nil {
r.logger.Printf("[ERROR] Restore failed: %v, output: %s", err, truncate(string(output), 500))
r.logger.Printf("[ERROR] [backup] Restore failed: %v, output: %s", err, truncate(string(output), 500))
return fmt.Errorf("restic restore failed: %w", err)
}
if r.debug {
r.logger.Printf("[DEBUG] [restic] RestoreAppData: completed in %s, output=%d bytes", time.Since(start), len(output))
}
r.logger.Printf("[INFO] RESTORE completed: snapshot=%s, paths=%v", snapshotID, paths)
r.logger.Printf("[INFO] [backup] Restore completed: snapshot=%s, paths=%v", snapshotID, paths)
return nil
}
@@ -483,8 +483,8 @@ func (r *ResticManager) generatePassword() error {
return fmt.Errorf("writing password file: %w", err)
}
r.logger.Printf("[INFO] Generated new restic repository password at %s", r.passwordFile)
r.logger.Printf("[WARN] Save this password externally — losing it means losing access to ALL backups")
r.logger.Printf("[INFO] [backup] Generated new restic repository password at %s", r.passwordFile)
r.logger.Printf("[WARN] [backup] Save this password externally — losing it means losing access to ALL backups")
return nil
}