feat: comprehensive debug logging across all controller modules
Add detailed [DEBUG] logging to every controller module when logging.level is set to "debug". Each module with stateful debug uses SetDebug(bool) wired from main.go. Covers stacks, backup, cloudflare, integrations, system, monitor, settings, scheduler, web handlers, storage, metrics, API, selfupdate, and assets. Also includes the app export/import (.fab bundles) feature from v0.32.0 and its debug page integration. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -65,6 +65,7 @@ type DiskUsageInfo struct {
|
||||
func GetDiskUsage(path string) *DiskUsageInfo {
|
||||
var stat syscall.Statfs_t
|
||||
if err := syscall.Statfs(path, &stat); err != nil {
|
||||
debugf("[DEBUG] [system] GetDiskUsage: statfs(%q) failed: %v", path, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -84,6 +85,8 @@ func GetDiskUsage(path string) *DiskUsageInfo {
|
||||
}
|
||||
info.TotalHuman = formatGB(info.TotalGB)
|
||||
info.UsedHuman = formatGB(info.UsedGB)
|
||||
debugf("[DEBUG] [system] GetDiskUsage: path=%q total=%s used=%s avail=%.1fGB (%.1f%%)",
|
||||
path, info.TotalHuman, info.UsedHuman, info.AvailGB, info.UsedPercent)
|
||||
return info
|
||||
}
|
||||
|
||||
@@ -105,10 +108,12 @@ type FSInfo struct {
|
||||
func GetFSInfo(path string) *FSInfo {
|
||||
out, err := exec.Command("findmnt", "-n", "-o", "SOURCE,FSTYPE", "--target", path).Output()
|
||||
if err != nil {
|
||||
debugf("[DEBUG] [system] GetFSInfo: findmnt(%q) failed: %v", path, err)
|
||||
return nil
|
||||
}
|
||||
fields := strings.Fields(strings.TrimSpace(string(out)))
|
||||
if len(fields) < 2 {
|
||||
debugf("[DEBUG] [system] GetFSInfo: findmnt(%q) returned unexpected output: %q", path, strings.TrimSpace(string(out)))
|
||||
return nil
|
||||
}
|
||||
info := &FSInfo{
|
||||
@@ -117,6 +122,7 @@ func GetFSInfo(path string) *FSInfo {
|
||||
}
|
||||
// Try to get disk model from sysfs
|
||||
info.Model = diskModel(info.Device)
|
||||
debugf("[DEBUG] [system] GetFSInfo: path=%q device=%s fstype=%s model=%q", path, info.Device, info.FSType, info.Model)
|
||||
return info
|
||||
}
|
||||
|
||||
@@ -136,6 +142,7 @@ type DestinationHealth struct {
|
||||
// CheckBackupDestination performs tiered validation of a cross-drive backup destination.
|
||||
// Returns a DestinationHealth describing any issues found.
|
||||
func CheckBackupDestination(path string) DestinationHealth {
|
||||
debugf("[DEBUG] [system] CheckBackupDestination: path=%q", path)
|
||||
h := DestinationHealth{Severity: "ok"}
|
||||
|
||||
// Tier 1: path must exist
|
||||
@@ -143,6 +150,7 @@ func CheckBackupDestination(path string) DestinationHealth {
|
||||
h.Warning = "A cél tárhely (" + path + ") nem létezik!"
|
||||
h.Blocked = true
|
||||
h.Severity = "critical"
|
||||
debugf("[DEBUG] [system] CheckBackupDestination: path=%q — tier1 FAIL (not exists)", path)
|
||||
return h
|
||||
}
|
||||
h.Exists = true
|
||||
@@ -152,6 +160,7 @@ func CheckBackupDestination(path string) DestinationHealth {
|
||||
h.Warning = "A cél tárhely (" + path + ") nem írható! Ellenőrizd a jogosultságokat."
|
||||
h.Blocked = true
|
||||
h.Severity = "critical"
|
||||
debugf("[DEBUG] [system] CheckBackupDestination: path=%q — tier2 FAIL (not writable)", path)
|
||||
return h
|
||||
}
|
||||
h.Writable = true
|
||||
@@ -165,9 +174,11 @@ func CheckBackupDestination(path string) DestinationHealth {
|
||||
"Meghajtóhiba esetén az eredeti adat és a mentés is elveszhet. " +
|
||||
"Külső meghajtó használata javasolt."
|
||||
h.Severity = "warning"
|
||||
debugf("[DEBUG] [system] CheckBackupDestination: path=%q — tier3 WARN (same block device as /)", path)
|
||||
// Don't return early — also check disk usage
|
||||
} else {
|
||||
h.MountPoint = true
|
||||
debugf("[DEBUG] [system] CheckBackupDestination: path=%q — tier3 OK (different block device)", path)
|
||||
}
|
||||
|
||||
// Tier 4: disk usage checks
|
||||
@@ -199,6 +210,8 @@ func CheckBackupDestination(path string) DestinationHealth {
|
||||
}
|
||||
}
|
||||
|
||||
debugf("[DEBUG] [system] CheckBackupDestination: path=%q — result: severity=%s blocked=%v freeGB=%.1f usedPct=%.1f%%",
|
||||
path, h.Severity, h.Blocked, h.FreeGB, h.UsedPercent)
|
||||
return h
|
||||
}
|
||||
|
||||
@@ -256,8 +269,11 @@ type ProbeResult struct {
|
||||
// ProbeStoragePath checks if a storage path is responsive.
|
||||
// Uses a goroutine with a 3-second timeout to avoid blocking on dead mounts.
|
||||
func ProbeStoragePath(path string) ProbeResult {
|
||||
start := time.Now()
|
||||
|
||||
// Quick check: does the path exist at all?
|
||||
if _, err := os.Lstat(path); os.IsNotExist(err) {
|
||||
debugf("[DEBUG] [system] ProbeStoragePath: path=%q — not exists (%s)", path, time.Since(start).Round(time.Millisecond))
|
||||
return ProbeResult{Status: ProbeDisconnected, Err: err}
|
||||
}
|
||||
|
||||
@@ -273,17 +289,22 @@ func ProbeStoragePath(path string) ProbeResult {
|
||||
|
||||
select {
|
||||
case res := <-ch:
|
||||
elapsed := time.Since(start).Round(time.Millisecond)
|
||||
if res.err == nil {
|
||||
debugf("[DEBUG] [system] ProbeStoragePath: path=%q — connected (%s)", path, elapsed)
|
||||
return ProbeResult{Status: ProbeConnected}
|
||||
}
|
||||
errStr := res.err.Error()
|
||||
if strings.Contains(errStr, "transport endpoint") ||
|
||||
strings.Contains(errStr, "input/output error") ||
|
||||
strings.Contains(errStr, "no such device") {
|
||||
debugf("[DEBUG] [system] ProbeStoragePath: path=%q — disconnected: %v (%s)", path, res.err, elapsed)
|
||||
return ProbeResult{Status: ProbeDisconnected, Err: res.err}
|
||||
}
|
||||
debugf("[DEBUG] [system] ProbeStoragePath: path=%q — disconnected (other error): %v (%s)", path, res.err, elapsed)
|
||||
return ProbeResult{Status: ProbeDisconnected, Err: res.err}
|
||||
case <-time.After(3 * time.Second):
|
||||
debugf("[DEBUG] [system] ProbeStoragePath: path=%q — TIMEOUT (3s)", path)
|
||||
return ProbeResult{Status: ProbeTimeout, Err: fmt.Errorf("stat timed out after 3s")}
|
||||
}
|
||||
}
|
||||
@@ -302,11 +323,11 @@ func IsUSBDevice(devicePath string) bool {
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if strings.Contains(link, "/usb") {
|
||||
return true
|
||||
}
|
||||
return false // found the sysfs entry, but not USB
|
||||
isUSB := strings.Contains(link, "/usb")
|
||||
debugf("[DEBUG] [system] IsUSBDevice: device=%q disk=%q sysfs=%s → usb=%v", devicePath, disk, link, isUSB)
|
||||
return isUSB
|
||||
}
|
||||
debugf("[DEBUG] [system] IsUSBDevice: device=%q disk=%q — no sysfs entry found", devicePath, disk)
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user