From 930ad20921024835f239678b0cfed4108d9bf26f Mon Sep 17 00:00:00 2001 From: rcourtman Date: Wed, 5 Nov 2025 19:48:00 +0000 Subject: [PATCH] Add configurable log level for pulse-sensor-proxy Users can now control logging verbosity through: - YAML config file: log_level: "debug|info|warn|error" - Environment variable: PULSE_SENSOR_PROXY_LOG_LEVEL Default log level is set to "info" instead of debug, reducing verbose output. Supported levels: trace, debug, info, warn, error, fatal, panic, disabled Related to #629 --- cmd/pulse-sensor-proxy/config.go | 8 ++++++++ cmd/pulse-sensor-proxy/main.go | 32 +++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/cmd/pulse-sensor-proxy/config.go b/cmd/pulse-sensor-proxy/config.go index aa779af..70878bf 100644 --- a/cmd/pulse-sensor-proxy/config.go +++ b/cmd/pulse-sensor-proxy/config.go @@ -21,6 +21,7 @@ type RateLimitConfig struct { type Config struct { AllowedSourceSubnets []string `yaml:"allowed_source_subnets"` MetricsAddress string `yaml:"metrics_address"` + LogLevel string `yaml:"log_level"` AllowIDMappedRoot bool `yaml:"allow_idmapped_root"` AllowedPeerUIDs []uint32 `yaml:"allowed_peer_uids"` @@ -35,6 +36,7 @@ func loadConfig(configPath string) (*Config, error) { cfg := &Config{ AllowIDMappedRoot: true, AllowedIDMapUsers: []string{"root"}, + LogLevel: "info", // Default log level } // Try to load config file if it exists @@ -166,6 +168,12 @@ func loadConfig(configPath string) (*Config, error) { Msg("Rate limit configuration loaded from config file") } + // Log level from environment variable + if envLogLevel := os.Getenv("PULSE_SENSOR_PROXY_LOG_LEVEL"); envLogLevel != "" { + cfg.LogLevel = strings.ToLower(strings.TrimSpace(envLogLevel)) + log.Info().Str("log_level", cfg.LogLevel).Msg("Log level set from environment") + } + return cfg, nil } diff --git a/cmd/pulse-sensor-proxy/main.go b/cmd/pulse-sensor-proxy/main.go index 34857ab..6a17d1d 100644 --- a/cmd/pulse-sensor-proxy/main.go +++ b/cmd/pulse-sensor-proxy/main.go @@ -85,6 +85,31 @@ func main() { } } +// parseLogLevel converts a string log level to zerolog.Level +func parseLogLevel(levelStr string) zerolog.Level { + switch strings.ToLower(strings.TrimSpace(levelStr)) { + case "trace": + return zerolog.TraceLevel + case "debug": + return zerolog.DebugLevel + case "info": + return zerolog.InfoLevel + case "warn", "warning": + return zerolog.WarnLevel + case "error": + return zerolog.ErrorLevel + case "fatal": + return zerolog.FatalLevel + case "panic": + return zerolog.PanicLevel + case "disabled", "none": + return zerolog.Disabled + default: + log.Warn().Str("level", levelStr).Msg("Unknown log level, defaulting to info") + return zerolog.InfoLevel + } +} + type userSpec struct { name string uid int @@ -276,7 +301,7 @@ type RPCResponse struct { type handlerFunc func(ctx context.Context, req *RPCRequest, logger zerolog.Logger) (interface{}, error) func runProxy() { - // Initialize logger + // Initialize logger with default level (will be configured after loading config) zerolog.TimeFieldFormat = zerolog.TimeFormatUnix log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) @@ -305,6 +330,10 @@ func runProxy() { log.Fatal().Err(err).Msg("Failed to load configuration") } + // Apply configured log level + level := parseLogLevel(cfg.LogLevel) + zerolog.SetGlobalLevel(level) + runAsUser := os.Getenv("PULSE_SENSOR_PROXY_USER") if runAsUser == "" { runAsUser = defaultRunAsUser @@ -339,6 +368,7 @@ func runProxy() { Str("ssh_key_dir", sshKeyPath). Str("config_path", cfgPath). Str("audit_log", auditPath). + Str("log_level", cfg.LogLevel). Str("version", Version). Msg("Starting pulse-sensor-proxy")