From 18d29784992807538a88360d33181cd5e059657c Mon Sep 17 00:00:00 2001 From: Jacquin Antoine Date: Sun, 1 Mar 2026 02:24:51 +0100 Subject: [PATCH] feat: use log_level parameter for Unix socket output Co-authored-by: Qwen-Coder --- README.md | 2 +- config.yml.example | 2 +- internal/output/writers.go | 110 ++++++++++++++++--------------------- 3 files changed, 50 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index 1baa373..b98ee77 100644 --- a/README.md +++ b/README.md @@ -231,7 +231,7 @@ outputs: enabled: true params: socket_path: /var/run/logcorrelator/network.socket - # debug: true # Activer pour logger l'état de connexion et les données envoyées + # log_level: debug # debug, info, warn, error (défaut: error) ``` ### Logging fichier + stdout diff --git a/config.yml.example b/config.yml.example index 3c80d0a..5205096 100644 --- a/config.yml.example +++ b/config.yml.example @@ -36,4 +36,4 @@ outputs: # enabled: false # params: # socket_path: /var/run/logcorrelator/network.socket - # debug: true # Enable debug logging for socket connection state + # log_level: debug # debug, info, warn, error (default: error) diff --git a/internal/output/writers.go b/internal/output/writers.go index f353fa3..9faecf1 100644 --- a/internal/output/writers.go +++ b/internal/output/writers.go @@ -9,6 +9,7 @@ import ( "net" "os" "path/filepath" + "strings" "sync" "time" @@ -198,7 +199,7 @@ type UnixSocketWriter struct { isClosed bool pendingWrites [][]byte pendingMu sync.Mutex - debug bool + logLevel string logger *log.Logger } @@ -209,11 +210,11 @@ func NewUnixSocketWriter(socketPath string) (*UnixSocketWriter, error) { // NewUnixSocketWriterWithConfig creates a new UNIX socket writer with custom configuration func NewUnixSocketWriterWithConfig(socketPath string, dialTimeout, writeTimeout time.Duration, queueSize int) (*UnixSocketWriter, error) { - return NewUnixSocketWriterWithConfigAndDebug(socketPath, dialTimeout, writeTimeout, queueSize, false, nil) + return NewUnixSocketWriterWithConfigAndLogLevel(socketPath, dialTimeout, writeTimeout, queueSize, "error") } -// NewUnixSocketWriterWithConfigAndDebug creates a new UNIX socket writer with debug logging -func NewUnixSocketWriterWithConfigAndDebug(socketPath string, dialTimeout, writeTimeout time.Duration, queueSize int, debug bool, logger *log.Logger) (*UnixSocketWriter, error) { +// NewUnixSocketWriterWithConfigAndLogLevel creates a new UNIX socket writer with log level configuration +func NewUnixSocketWriterWithConfigAndLogLevel(socketPath string, dialTimeout, writeTimeout time.Duration, queueSize int, logLevel string) (*UnixSocketWriter, error) { w := &UnixSocketWriter{ socketPath: socketPath, dialTimeout: dialTimeout, @@ -225,8 +226,8 @@ func NewUnixSocketWriterWithConfigAndDebug(socketPath string, dialTimeout, write queueClose: make(chan struct{}), queueDone: make(chan struct{}), pendingWrites: make([][]byte, 0), - debug: debug, - logger: logger, + logLevel: strings.ToLower(logLevel), + logger: log.New(os.Stderr, "[UnixSocket] ", log.LstdFlags|log.Lmicroseconds), } // Start the queue processor @@ -236,26 +237,39 @@ func NewUnixSocketWriterWithConfigAndDebug(socketPath string, dialTimeout, write conn, err := net.DialTimeout("unix", socketPath, w.dialTimeout) if err == nil { w.conn = conn - if w.logger != nil { - if w.debug { - w.logger.Printf("[DEBUG] UnixSocketWriter: connected to %s", socketPath) - } else { - w.logger.Printf("[INFO] UnixSocketWriter: connected to %s", socketPath) - } - } + w.log("INFO", "connected to %s", socketPath) } else { - if w.logger != nil { - if w.debug { - w.logger.Printf("[DEBUG] UnixSocketWriter: initial connection to %s failed: %v (will retry on write)", socketPath, err) - } else { - w.logger.Printf("[WARNING] UnixSocketWriter: initial connection to %s failed: %v (will retry on write)", socketPath, err) - } - } + w.log("WARNING", "initial connection to %s failed: %v (will retry on write)", socketPath, err) } return w, nil } +// log emits a log message if the level is enabled +func (w *UnixSocketWriter) log(level, format string, args ...interface{}) { + if !w.isLogLevelEnabled(level) { + return + } + w.logger.Printf("[%s] UnixSocketWriter: "+format, append([]interface{}{level}, args...)...) +} + +// isLogLevelEnabled checks if a log level should be emitted +func (w *UnixSocketWriter) isLogLevelEnabled(level string) bool { + level = strings.ToLower(level) + switch w.logLevel { + case "debug": + return true + case "info": + return level != "debug" + case "warn", "warning": + return level != "debug" && level != "info" + case "error": + return level == "error" + default: + return false + } +} + // processQueue handles queued writes with reconnection logic func (w *UnixSocketWriter) processQueue() { defer close(w.queueDone) @@ -281,14 +295,10 @@ func (w *UnixSocketWriter) processQueue() { } w.pendingMu.Unlock() - if w.logger != nil { - if w.debug { - w.logger.Printf("[DEBUG] UnixSocketWriter: write failed to %s: %v (failures: %d)", w.socketPath, err, consecutiveFailures) - } else if consecutiveFailures >= w.maxReconnects { - w.logger.Printf("[ERROR] UnixSocketWriter: max reconnection attempts reached for %s (failures: %d)", w.socketPath, consecutiveFailures) - } else if consecutiveFailures > 1 { - w.logger.Printf("[WARNING] UnixSocketWriter: write failed to %s: %v (attempt %d/%d)", w.socketPath, err, consecutiveFailures, w.maxReconnects) - } + if consecutiveFailures >= w.maxReconnects { + w.log("ERROR", "max reconnection attempts reached for %s (failures: %d)", w.socketPath, consecutiveFailures) + } else if consecutiveFailures > 1 { + w.log("WARNING", "write failed to %s: %v (attempt %d/%d)", w.socketPath, err, consecutiveFailures, w.maxReconnects) } // Exponential backoff @@ -300,9 +310,7 @@ func (w *UnixSocketWriter) processQueue() { } } } else { - if w.debug && w.logger != nil { - w.logger.Printf("[DEBUG] UnixSocketWriter: wrote %d bytes to %s", len(data), w.socketPath) - } + w.log("DEBUG", "wrote %d bytes to %s", len(data), w.socketPath) consecutiveFailures = 0 backoff = w.reconnectBackoff // Try to flush pending data @@ -350,20 +358,12 @@ func (w *UnixSocketWriter) writeWithReconnect(data []byte) error { return fmt.Errorf("failed to connect to socket %s: %w", w.socketPath, err) } w.conn = conn - if w.logger != nil { - if w.debug { - w.logger.Printf("[DEBUG] UnixSocketWriter: reconnected to %s", w.socketPath) - } else { - w.logger.Printf("[INFO] UnixSocketWriter: connected to %s", w.socketPath) - } - } + w.log("INFO", "connected to %s", w.socketPath) return nil } if err := ensureConn(); err != nil { - if w.logger != nil { - w.logger.Printf("[ERROR] UnixSocketWriter: connection failed to %s: %v", w.socketPath, err) - } + w.log("ERROR", "connection failed to %s: %v", w.socketPath, err) return err } @@ -376,13 +376,7 @@ func (w *UnixSocketWriter) writeWithReconnect(data []byte) error { } // Connection failed, try to reconnect - if w.logger != nil { - if w.debug { - w.logger.Printf("[DEBUG] UnixSocketWriter: write failed, attempting reconnect to %s", w.socketPath) - } else { - w.logger.Printf("[WARNING] UnixSocketWriter: write failed, attempting reconnect to %s", w.socketPath) - } - } + w.log("WARNING", "write failed, attempting reconnect to %s", w.socketPath) _ = w.conn.Close() w.conn = nil @@ -441,13 +435,7 @@ func (w *UnixSocketWriter) Close() error { w.isClosed = true if w.conn != nil { - if w.logger != nil { - if w.debug { - w.logger.Printf("[DEBUG] UnixSocketWriter: closing connection to %s", w.socketPath) - } else { - w.logger.Printf("[INFO] UnixSocketWriter: closing connection to %s", w.socketPath) - } - } + w.log("INFO", "closing connection to %s", w.socketPath) w.conn.Close() w.conn = nil } @@ -544,14 +532,12 @@ func (b *BuilderImpl) NewFromConfig(cfg api.AppConfig) (api.Writer, error) { if socketPath == "" { return nil, fmt.Errorf("unix_socket output requires 'socket_path' parameter") } - // Check for debug mode - debug := outputCfg.Params["debug"] == "true" || outputCfg.Params["debug"] == "1" - if debug { - logger := log.New(os.Stderr, "[UnixSocket] ", log.LstdFlags|log.Lmicroseconds) - writer, err = NewUnixSocketWriterWithConfigAndDebug(socketPath, DefaultDialTimeout, DefaultWriteTimeout, DefaultQueueSize, debug, logger) - } else { - writer, err = NewUnixSocketWriter(socketPath) + // Get log level (default: error) + logLevel := outputCfg.Params["log_level"] + if logLevel == "" { + logLevel = "error" } + writer, err = NewUnixSocketWriterWithConfigAndLogLevel(socketPath, DefaultDialTimeout, DefaultWriteTimeout, DefaultQueueSize, logLevel) if err != nil { return nil, err }