diff --git a/cmd/homelab-deploy/main.go b/cmd/homelab-deploy/main.go index 4c5bdde..5d03d39 100644 --- a/cmd/homelab-deploy/main.go +++ b/cmd/homelab-deploy/main.go @@ -16,7 +16,7 @@ import ( "github.com/urfave/cli/v3" ) -const version = "0.1.13" +const version = "0.1.14" func main() { app := &cli.Command{ @@ -42,6 +42,10 @@ func listenerCommand() *cli.Command { Name: "listener", Usage: "Run as a deployment listener (systemd service mode)", Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "debug", + Usage: "Enable debug logging for troubleshooting", + }, &cli.StringFlag{ Name: "hostname", Usage: "Hostname for this listener", @@ -125,10 +129,16 @@ func listenerCommand() *cli.Command { MetricsEnabled: c.Bool("metrics-enabled"), MetricsAddr: c.String("metrics-addr"), Version: version, + Debug: c.Bool("debug"), + } + + logLevel := slog.LevelInfo + if c.Bool("debug") { + logLevel = slog.LevelDebug } logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ - Level: slog.LevelInfo, + Level: logLevel, })) l := listener.New(cfg, logger) diff --git a/internal/listener/listener.go b/internal/listener/listener.go index 70b9ee3..36428d9 100644 --- a/internal/listener/listener.go +++ b/internal/listener/listener.go @@ -27,6 +27,7 @@ type Config struct { MetricsEnabled bool MetricsAddr string Version string + Debug bool } // Listener handles deployment requests from NATS. @@ -203,7 +204,14 @@ func (l *Listener) handleDeployRequest(subject string, data []byte) { // Record deployment start for metrics if l.metrics != nil { + l.logger.Debug("recording deployment start metric", + "metrics_enabled", true, + ) l.metrics.RecordDeploymentStart() + } else { + l.logger.Debug("skipping deployment start metric", + "metrics_enabled", false, + ) } startTime := time.Now() @@ -219,9 +227,19 @@ func (l *Listener) handleDeployRequest(subject string, data []byte) { messages.StatusFailed, fmt.Sprintf("revision validation failed: %v", err), ).WithError(messages.ErrorInvalidRevision)) + duration := time.Since(startTime).Seconds() if l.metrics != nil { - duration := time.Since(startTime).Seconds() + l.logger.Debug("recording deployment failure metric (revision validation)", + "action", req.Action, + "error_code", messages.ErrorInvalidRevision, + "duration_seconds", duration, + ) l.metrics.RecordDeploymentFailure(req.Action, messages.ErrorInvalidRevision, duration) + } else { + l.logger.Debug("skipping deployment failure metric", + "metrics_enabled", false, + "duration_seconds", duration, + ) } return } @@ -265,7 +283,17 @@ func (l *Listener) handleDeployRequest(subject string, data []byte) { l.logger.Error("failed to flush completed response", "error", err) } if l.metrics != nil { + l.logger.Debug("recording deployment end metric (success)", + "action", req.Action, + "success", true, + "duration_seconds", duration, + ) l.metrics.RecordDeploymentEnd(req.Action, true, duration) + } else { + l.logger.Debug("skipping deployment end metric", + "metrics_enabled", false, + "duration_seconds", duration, + ) } // After a successful switch, signal restart so we pick up any new version @@ -305,7 +333,17 @@ func (l *Listener) handleDeployRequest(subject string, data []byte) { fmt.Sprintf("deployment failed (exit code %d): %s", result.ExitCode, result.Stderr), ).WithError(errorCode)) if l.metrics != nil { + l.logger.Debug("recording deployment failure metric", + "action", req.Action, + "error_code", errorCode, + "duration_seconds", duration, + ) l.metrics.RecordDeploymentFailure(req.Action, errorCode, duration) + } else { + l.logger.Debug("skipping deployment failure metric", + "metrics_enabled", false, + "duration_seconds", duration, + ) } } } diff --git a/nixos/module.nix b/nixos/module.nix index ee0a77b..7a13e83 100644 --- a/nixos/module.nix +++ b/nixos/module.nix @@ -19,7 +19,8 @@ let ++ lib.optionals cfg.metrics.enable [ "--metrics-enabled" "--metrics-addr ${lib.escapeShellArg cfg.metrics.address}" - ]); + ] + ++ cfg.extraArgs); # Extract port from metrics address for firewall rule metricsPort = let @@ -122,6 +123,13 @@ in description = "Open firewall for metrics port"; }; }; + + extraArgs = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + description = "Extra command line arguments to pass to the listener"; + example = [ "--debug" ]; + }; }; config = lib.mkIf cfg.enable {