diff --git a/cmd/kepler/main.go b/cmd/kepler/main.go index 4d320ae3c0..1fd41e34c2 100644 --- a/cmd/kepler/main.go +++ b/cmd/kepler/main.go @@ -13,6 +13,7 @@ import ( "github.com/alecthomas/kingpin/v2" "github.com/oklog/run" "github.com/sustainable-computing-io/kepler/internal/config" + "github.com/sustainable-computing-io/kepler/internal/logger" "github.com/sustainable-computing-io/kepler/internal/version" ) @@ -22,7 +23,7 @@ func main() { if err != nil { os.Exit(1) } - logger := setupLogger(cfg.Log.Level, cfg.Log.Format) + logger := logger.New(cfg.Log.Level, cfg.Log.Format) logVersionInfo(logger) printConfigInfo(logger, cfg) @@ -110,7 +111,7 @@ func parseArgsAndConfig() (*config.Config, error) { updateConfig := config.RegisterFlags(app) kingpin.MustParse(app.Parse(os.Args[1:])) - logger := setupLogger("info", "text") + logger := logger.New("info", "text") cfg := config.DefaultConfig() if *configFile != "" { logger.Info("Loading configuration file", "path", *configFile) diff --git a/cmd/kepler/logger.go b/internal/logger/logger.go similarity index 95% rename from cmd/kepler/logger.go rename to internal/logger/logger.go index c06865a2b3..a7cdb8584c 100644 --- a/cmd/kepler/logger.go +++ b/internal/logger/logger.go @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: 2025 The Kepler Authors // SPDX-License-Identifier: Apache-2.0 -package main +package logger import ( "fmt" @@ -11,7 +11,7 @@ import ( "strings" ) -func setupLogger(level, format string) *slog.Logger { +func New(level, format string) *slog.Logger { logLevel := parseLogLevel(level) return slog.New(handlerForFormat(format, logLevel)) } diff --git a/cmd/kepler/logger_test.go b/internal/logger/logger_test.go similarity index 76% rename from cmd/kepler/logger_test.go rename to internal/logger/logger_test.go index 969903e35c..a574066718 100644 --- a/cmd/kepler/logger_test.go +++ b/internal/logger/logger_test.go @@ -1,11 +1,12 @@ // SPDX-FileCopyrightText: 2025 The Kepler Authors // SPDX-License-Identifier: Apache-2.0 -package main +package logger import ( "bytes" "encoding/json" + "log/slog" "os" "strings" "testing" @@ -65,7 +66,7 @@ func TestSetupLogger(t *testing.T) { t.Run(tt.name, func(t *testing.T) { if tt.expectPanic { assert.Panics(t, func() { - _ = setupLogger(tt.format, tt.logLevel) + _ = New(tt.logLevel, tt.format) }, "Expected setupLogger to panic with invalid format") // return @@ -77,7 +78,7 @@ func TestSetupLogger(t *testing.T) { r, w, _ := os.Pipe() os.Stdout = w - logger := setupLogger(tt.logLevel, tt.format) + logger := New(tt.logLevel, tt.format) logger.Info("test message", "key", "value") // Restore stdout @@ -120,3 +121,49 @@ func TestSetupLogger(t *testing.T) { }) } } + +func TestParseLogLevel(t *testing.T) { + tests := []struct { + name string + level string + expected slog.Level + }{ + { + name: "debug level", + level: "debug", + expected: slog.LevelDebug, + }, + { + name: "info level", + level: "info", + expected: slog.LevelInfo, + }, + { + name: "warn level", + level: "warn", + expected: slog.LevelWarn, + }, + { + name: "error level", + level: "error", + expected: slog.LevelError, + }, + { + name: "invalid level defaults to info", + level: "invalid", + expected: slog.LevelInfo, + }, + { + name: "empty level defaults to info", + level: "", + expected: slog.LevelInfo, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := parseLogLevel(tt.level) + assert.Equal(t, tt.expected, result, "parseLogLevel(%q) = %v, want %v", tt.level, result, tt.expected) + }) + } +}