diff --git a/.env.example b/.env.example index fc58775..ccd0285 100644 --- a/.env.example +++ b/.env.example @@ -79,6 +79,9 @@ RECONCILE_INTERVAL=60s # Coalesces rapid bursts (e.g. rolling restarts) into a single reconcile. DEBOUNCE_DELAY=5s +# Log level for watcher output. Allowed: debug, info, warn, error +LOG_LEVEL=info + # ── Docker ──────────────────────────────────────────────────────────────────── # Docker daemon endpoint. Leave empty to use the default Unix socket. diff --git a/config.go b/config.go index eb9f3f5..1fbd85d 100644 --- a/config.go +++ b/config.go @@ -30,6 +30,7 @@ type Config struct { ReconcileInterval time.Duration DebounceDelay time.Duration + LogLevel string RecordTTL int CloudflareAutoTTL bool @@ -98,6 +99,13 @@ func LoadConfig() (*Config, error) { return nil, fmt.Errorf("CF_AUTO_TTL: invalid boolean %q: %w", autoTTLStr, err) } + cfg.LogLevel = strings.ToLower(envOrDefault("LOG_LEVEL", "info")) + switch cfg.LogLevel { + case "debug", "info", "warn", "error": + default: + return nil, fmt.Errorf("LOG_LEVEL: invalid value %q (allowed: debug, info, warn, error)", cfg.LogLevel) + } + cfg.ExcludeRouters = make(map[string]struct{}) if v := os.Getenv("EXCLUDE_ROUTERS"); v != "" { for _, r := range strings.Split(v, ",") { diff --git a/main.go b/main.go index a0fe7ab..4d198b8 100644 --- a/main.go +++ b/main.go @@ -22,21 +22,28 @@ func main() { return } - slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ - Level: slog.LevelInfo, - }))) - cfg, err := LoadConfig() if err != nil { - slog.Error("configuration error", "error", err) + fmt.Fprintln(os.Stderr, "configuration error:", err) os.Exit(1) } + logLevel, err := parseLogLevel(cfg.LogLevel) + if err != nil { + fmt.Fprintln(os.Stderr, "configuration error:", err) + os.Exit(1) + } + + slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ + Level: logLevel, + }))) + slog.Info("traefik-dns-watcher starting", "traefik_url", cfg.TraefikURL, "zones", cfg.Zones, "repo_path", cfg.RepoPath, "dynamic_dir", cfg.DynamicDir, + "log_level", cfg.LogLevel, "git_https_token_enabled", cfg.GitAuthToken != "", "git_auth_username", cfg.GitAuthUsername, "reconcile_interval", cfg.ReconcileInterval, @@ -115,6 +122,21 @@ func main() { slog.Info("traefik-dns-watcher stopped") } +func parseLogLevel(v string) (slog.Level, error) { + switch strings.ToLower(v) { + case "debug": + return slog.LevelDebug, nil + case "info": + return slog.LevelInfo, nil + case "warn": + return slog.LevelWarn, nil + case "error": + return slog.LevelError, nil + default: + return 0, fmt.Errorf("LOG_LEVEL: invalid value %q (allowed: debug, info, warn, error)", v) + } +} + // maybeHandleGitAskpass serves username/password for git HTTPS auth in non-interactive mode. // This process mode is only enabled for git child processes that set TDW_GIT_ASKPASS=1. func maybeHandleGitAskpass() bool {