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:
2026-02-26 18:14:43 +01:00
parent f6caea8067
commit 95c821deb2
54 changed files with 5015 additions and 82 deletions
+96
View File
@@ -13,6 +13,7 @@ import (
"strings"
"time"
"gitea.dooplex.hu/admin/felhom-controller/internal/appexport"
"gitea.dooplex.hu/admin/felhom-controller/internal/backup"
"gitea.dooplex.hu/admin/felhom-controller/internal/monitor"
"gitea.dooplex.hu/admin/felhom-controller/internal/report"
@@ -100,6 +101,14 @@ func (s *Server) handleDebugAPI(w http.ResponseWriter, r *http.Request) {
case subpath == "logs" && r.Method == http.MethodGet:
s.debugLogBuffer(w, r)
// Section 9: App Export/Import
case subpath == "appexport/status" && r.Method == http.MethodGet:
s.debugAppExportStatus(w, r)
case subpath == "appexport/bundles" && r.Method == http.MethodGet:
s.debugAppExportBundles(w, r)
case subpath == "appexport/cleanup" && r.Method == http.MethodPost:
s.debugAppExportCleanup(w, r)
default:
http.NotFound(w, r)
}
@@ -725,3 +734,90 @@ func (s *Server) debugLogBuffer(w http.ResponseWriter, r *http.Request) {
"total": total,
})
}
// ── Section 9: App Export/Import ─────────────────────────────────────
func (s *Server) debugAppExportStatus(w http.ResponseWriter, r *http.Request) {
if s.appExporter == nil {
writeDebugJSON(w, http.StatusOK, true, "", map[string]interface{}{
"available": false,
})
return
}
info := s.appExporter.GetDebugInfo()
// Scan for bundles
drives := s.storageDriveList()
bundles := appexport.ScanForBundles(drives)
// Scan for stale temp files
staleFiles := appexport.ScanForStaleTempFiles(drives)
info["bundle_count"] = len(bundles)
info["stale_temp_files"] = staleFiles
info["stale_temp_count"] = len(staleFiles)
info["available"] = true
// Export dirs
exportDirs := make([]map[string]interface{}, 0, len(drives))
for _, d := range drives {
dir := appexport.ExportDir(d.Path)
dirInfo := map[string]interface{}{
"path": dir,
"label": d.Label,
}
if stat, err := os.Stat(dir); err == nil {
dirInfo["exists"] = true
dirInfo["modified"] = stat.ModTime()
} else {
dirInfo["exists"] = false
}
exportDirs = append(exportDirs, dirInfo)
}
info["export_dirs"] = exportDirs
writeDebugJSON(w, http.StatusOK, true, "", info)
}
func (s *Server) debugAppExportBundles(w http.ResponseWriter, r *http.Request) {
if s.appExporter == nil {
writeDebugJSON(w, http.StatusBadRequest, false, "App export not available", nil)
return
}
drives := s.storageDriveList()
bundles := appexport.ScanForBundles(drives)
writeDebugJSON(w, http.StatusOK, true,
fmt.Sprintf("%d csomag található", len(bundles)),
map[string]interface{}{"bundles": bundles})
}
func (s *Server) debugAppExportCleanup(w http.ResponseWriter, r *http.Request) {
if s.appExporter == nil {
writeDebugJSON(w, http.StatusBadRequest, false, "App export not available", nil)
return
}
drives := s.storageDriveList()
staleFiles := appexport.ScanForStaleTempFiles(drives)
if len(staleFiles) == 0 {
writeDebugJSON(w, http.StatusOK, true, "Nincs eltávolítandó temp fájl", nil)
return
}
removed := 0
for _, f := range staleFiles {
if err := os.Remove(f); err != nil {
s.logger.Printf("[WARN] Failed to remove stale temp file %s: %v", f, err)
} else {
s.logger.Printf("[INFO] Removed stale temp file: %s", f)
removed++
}
}
writeDebugJSON(w, http.StatusOK, true,
fmt.Sprintf("%d/%d temp fájl eltávolítva", removed, len(staleFiles)), nil)
}