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:
@@ -14,9 +14,10 @@ import (
|
||||
// Settings holds customer-modifiable overrides and cached state.
|
||||
// Persisted as a single JSON file (settings.json) in the data directory.
|
||||
type Settings struct {
|
||||
mu sync.RWMutex `json:"-"`
|
||||
path string `json:"-"`
|
||||
log *log.Logger `json:"-"`
|
||||
mu sync.RWMutex `json:"-"`
|
||||
path string `json:"-"`
|
||||
log *log.Logger `json:"-"`
|
||||
debug bool `json:"-"`
|
||||
|
||||
// Auth
|
||||
PasswordHash string `json:"password_hash,omitempty"` // bcrypt hash, overrides controller.yaml
|
||||
@@ -156,6 +157,11 @@ type DBValidationCache struct {
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// SetDebug enables or disables debug logging for settings operations.
|
||||
func (s *Settings) SetDebug(debug bool) {
|
||||
s.debug = debug
|
||||
}
|
||||
|
||||
// Load reads settings from the given file path.
|
||||
// Returns empty Settings if the file doesn't exist (not an error).
|
||||
func Load(path string, logger *log.Logger) (*Settings, error) {
|
||||
@@ -178,6 +184,10 @@ func Load(path string, logger *log.Logger) (*Settings, error) {
|
||||
}
|
||||
|
||||
logger.Printf("[DEBUG] Settings loaded from %s", path)
|
||||
if s.debug {
|
||||
s.log.Printf("[DEBUG] [settings] loaded: storage_paths=%d integrations=%d pending_events=%d",
|
||||
len(s.StoragePaths), len(s.Integrations), len(s.PendingEvents))
|
||||
}
|
||||
s.migrateResticToRsync()
|
||||
return s, nil
|
||||
}
|
||||
@@ -226,7 +236,9 @@ func (s *Settings) save() error {
|
||||
return fmt.Errorf("renaming settings file: %w", err)
|
||||
}
|
||||
|
||||
s.log.Printf("[DEBUG] Settings saved to %s", s.path)
|
||||
if s.debug {
|
||||
s.log.Printf("[DEBUG] [settings] saved to %s (%d bytes)", s.path, len(data))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -435,6 +447,9 @@ func (s *Settings) GetSchedulableStoragePaths() []StoragePath {
|
||||
func (s *Settings) AddStoragePath(sp StoragePath) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.debug {
|
||||
s.log.Printf("[DEBUG] [settings] AddStoragePath path=%q label=%q default=%v", sp.Path, sp.Label, sp.IsDefault)
|
||||
}
|
||||
for _, existing := range s.StoragePaths {
|
||||
if existing.Path == sp.Path {
|
||||
return fmt.Errorf("storage path %q already registered", sp.Path)
|
||||
@@ -453,6 +468,9 @@ func (s *Settings) AddStoragePath(sp StoragePath) error {
|
||||
func (s *Settings) RemoveStoragePath(path string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.debug {
|
||||
s.log.Printf("[DEBUG] [settings] RemoveStoragePath path=%q", path)
|
||||
}
|
||||
var kept []StoragePath
|
||||
for _, sp := range s.StoragePaths {
|
||||
if sp.Path != path {
|
||||
@@ -515,6 +533,10 @@ func (s *Settings) AutoDiscoverStoragePaths(discoveredPaths []string, fallbackHD
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if s.debug {
|
||||
s.log.Printf("[DEBUG] [settings] AutoDiscoverStoragePaths discovered=%v fallback=%q existing=%d", discoveredPaths, fallbackHDDPath, len(s.StoragePaths))
|
||||
}
|
||||
|
||||
if len(s.StoragePaths) > 0 {
|
||||
return // already configured
|
||||
}
|
||||
@@ -572,6 +594,9 @@ func InferStorageLabel(path string) string {
|
||||
func (s *Settings) SetDisconnected(path string, disconnected bool, stoppedStacks []string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.debug {
|
||||
s.log.Printf("[DEBUG] [settings] SetDisconnected path=%q disconnected=%v stopped_stacks=%d", path, disconnected, len(stoppedStacks))
|
||||
}
|
||||
for i := range s.StoragePaths {
|
||||
if s.StoragePaths[i].Path == path {
|
||||
s.StoragePaths[i].Disconnected = disconnected
|
||||
@@ -679,6 +704,9 @@ func (s *Settings) ClearStoppedStacks(path string) error {
|
||||
func (s *Settings) SetDecommissioned(path, migratedTo string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.debug {
|
||||
s.log.Printf("[DEBUG] [settings] SetDecommissioned path=%q migrated_to=%q", path, migratedTo)
|
||||
}
|
||||
for i := range s.StoragePaths {
|
||||
if s.StoragePaths[i].Path == path {
|
||||
s.StoragePaths[i].Decommissioned = true
|
||||
@@ -811,6 +839,9 @@ func (s *Settings) SetRetrievalPassword(password string) error {
|
||||
func (s *Settings) AddPendingEvent(event PendingEvent) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.debug {
|
||||
s.log.Printf("[DEBUG] [settings] AddPendingEvent type=%q severity=%q", event.EventType, event.Severity)
|
||||
}
|
||||
s.PendingEvents = append(s.PendingEvents, event)
|
||||
return s.save()
|
||||
}
|
||||
@@ -822,6 +853,9 @@ func (s *Settings) DrainPendingEvents() []PendingEvent {
|
||||
if len(s.PendingEvents) == 0 {
|
||||
return nil
|
||||
}
|
||||
if s.debug {
|
||||
s.log.Printf("[DEBUG] [settings] DrainPendingEvents count=%d", len(s.PendingEvents))
|
||||
}
|
||||
events := make([]PendingEvent, len(s.PendingEvents))
|
||||
copy(events, s.PendingEvents)
|
||||
s.PendingEvents = nil
|
||||
@@ -862,6 +896,13 @@ func (s *Settings) GetGeoRestriction() *GeoRestriction {
|
||||
func (s *Settings) SetGeoRestriction(geo *GeoRestriction) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.debug {
|
||||
if geo == nil {
|
||||
s.log.Printf("[DEBUG] [settings] SetGeoRestriction geo=nil (clearing)")
|
||||
} else {
|
||||
s.log.Printf("[DEBUG] [settings] SetGeoRestriction enabled=%v countries=%d", geo.Enabled, len(geo.AllowedCountries))
|
||||
}
|
||||
}
|
||||
if geo == nil {
|
||||
s.GeoRestriction = nil
|
||||
return s.save()
|
||||
@@ -953,6 +994,9 @@ func (s *Settings) GetIntegrationState(key string) (IntegrationState, bool) {
|
||||
func (s *Settings) SetIntegrationState(key string, state IntegrationState) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.debug {
|
||||
s.log.Printf("[DEBUG] [settings] SetIntegrationState key=%q status=%q enabled=%v", key, state.Status, state.Enabled)
|
||||
}
|
||||
if s.Integrations == nil {
|
||||
s.Integrations = make(map[string]IntegrationState)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user