v0.24.0 — Pre-testing observability: debug logging, diagnostic dump, startup self-test
- Add [DEBUG] logging across all modules (backup, storage, sync, selfupdate, monitor, notify, report, assets, setup) gated behind logging.level: "debug" - Add /api/debug/dump endpoint returning full controller state JSON (debug only) - Add startup self-test validating 9 subsystems (Docker, dirs, storage, hub, restic repos, metrics DB) with pass/warn/fail summary - New packages: internal/selftest, internal/util - Constructor/signature changes: debug bool params, logger params on RunHealthCheck and BuildReport, smart watchdog probe logging Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -29,7 +30,13 @@ func BuildReport(
|
||||
metricsStore *metrics.MetricsStore,
|
||||
version string,
|
||||
storagePaths []settings.StoragePath,
|
||||
logger *log.Logger,
|
||||
) *Report {
|
||||
debug := cfg.Logging.Level == "debug"
|
||||
if debug && logger != nil {
|
||||
logger.Printf("[DEBUG] BuildReport: starting — version=%s, storagePaths=%d", version, len(storagePaths))
|
||||
}
|
||||
|
||||
r := &Report{
|
||||
Version: 1,
|
||||
CustomerID: cfg.Customer.ID,
|
||||
@@ -48,6 +55,9 @@ func BuildReport(
|
||||
if data, err := os.ReadFile(configPath); err == nil {
|
||||
h := sha256.Sum256(data)
|
||||
r.ConfigHash = hex.EncodeToString(h[:])
|
||||
if debug && logger != nil {
|
||||
logger.Printf("[DEBUG] BuildReport: configHash=%s (%d bytes)", r.ConfigHash[:12]+"...", len(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,6 +121,12 @@ func BuildReport(
|
||||
})
|
||||
}
|
||||
|
||||
if debug && logger != nil {
|
||||
logger.Printf("[DEBUG] BuildReport: system info collected — cpu=%.1f%%, mem=%d/%dMB, temp=%.1fC",
|
||||
sysInfo.CPUPercent, sysInfo.UsedMemMB, sysInfo.TotalMemMB, sysInfo.TemperatureCelsius)
|
||||
logger.Printf("[DEBUG] BuildReport: storage entries=%d", len(r.Storage))
|
||||
}
|
||||
|
||||
// Containers
|
||||
r.Containers = buildContainerReport(stackMgr, metricsStore)
|
||||
|
||||
@@ -118,7 +134,7 @@ func BuildReport(
|
||||
r.Backup = buildBackupReport(cfg, backupMgr)
|
||||
|
||||
// Health
|
||||
healthReport := monitor.RunHealthCheck(cfg, cpuCollector, storagePaths)
|
||||
healthReport := monitor.RunHealthCheck(cfg, cpuCollector, storagePaths, logger)
|
||||
r.Health = HealthReport{
|
||||
Status: healthReport.Status,
|
||||
Issues: healthReport.Issues,
|
||||
@@ -134,6 +150,11 @@ func BuildReport(
|
||||
// Stacks
|
||||
r.Stacks = buildStacksReport(stackMgr)
|
||||
|
||||
if debug && logger != nil {
|
||||
logger.Printf("[DEBUG] BuildReport: complete — containers=%d, health=%s, deployed=%d, available=%d",
|
||||
r.Containers.Total, r.Health.Status, len(r.Stacks.Deployed), len(r.Stacks.Available))
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ type Pusher struct {
|
||||
httpClient *http.Client
|
||||
logger *log.Logger
|
||||
enabled bool
|
||||
debug bool
|
||||
|
||||
statusMu sync.RWMutex
|
||||
status PushStatus
|
||||
@@ -45,7 +46,7 @@ type Pusher struct {
|
||||
}
|
||||
|
||||
// NewPusher creates a new report pusher from hub configuration.
|
||||
func NewPusher(cfg *config.HubConfig, logger *log.Logger) *Pusher {
|
||||
func NewPusher(cfg *config.HubConfig, logger *log.Logger, debug bool) *Pusher {
|
||||
return &Pusher{
|
||||
hubURL: strings.TrimRight(cfg.URL, "/"),
|
||||
apiKey: cfg.APIKey,
|
||||
@@ -54,6 +55,7 @@ func NewPusher(cfg *config.HubConfig, logger *log.Logger) *Pusher {
|
||||
},
|
||||
logger: logger,
|
||||
enabled: cfg.Enabled,
|
||||
debug: debug,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +71,9 @@ func (p *Pusher) Push(report *Report) error {
|
||||
}
|
||||
|
||||
url := p.hubURL + "/api/v1/report"
|
||||
if p.debug {
|
||||
p.logger.Printf("[DEBUG] Push: url=%s payload=%d bytes", url, len(data))
|
||||
}
|
||||
|
||||
p.statusMu.Lock()
|
||||
p.status.LastAttempt = time.Now()
|
||||
@@ -143,6 +148,9 @@ func (p *Pusher) PushInfraBackup(data []byte) error {
|
||||
}
|
||||
|
||||
url := p.hubURL + "/api/v1/infra-backup"
|
||||
if p.debug {
|
||||
p.logger.Printf("[DEBUG] PushInfraBackup: url=%s payload=%d bytes", url, len(data))
|
||||
}
|
||||
|
||||
var lastErr error
|
||||
for attempt := 0; attempt < 3; attempt++ {
|
||||
@@ -173,6 +181,9 @@ func (p *Pusher) PushInfraBackup(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
lastErr = fmt.Errorf("HTTP %d", resp.StatusCode)
|
||||
if p.debug {
|
||||
p.logger.Printf("[DEBUG] PushInfraBackup: attempt %d failed — HTTP %d", attempt+1, resp.StatusCode)
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("infra backup push failed after 3 attempts: %w", lastErr)
|
||||
|
||||
Reference in New Issue
Block a user