1
0
mirror of https://github.com/mgechev/revive.git synced 2025-11-29 22:28:23 +02:00

change: replace log with log/slog for logging (#1280)

* change: replace log with log/slog for logging
* add TODO about slog.DiscardHandler
This commit is contained in:
Oleksandr Redko
2025-03-25 09:47:59 -07:00
committed by GitHub
parent 88e5689475
commit 561c949334
4 changed files with 91 additions and 24 deletions

View File

@@ -19,6 +19,16 @@ make build
The command will produce the `revive` binary in the root of the project. The command will produce the `revive` binary in the root of the project.
## Debug
To enable debug logging, set the `DEBUG` environment variable:
```sh
DEBUG=1 go run main.go
```
This will output debug information to `stderr` and to the log file `revive.log` created in the current working directory.
## Development of rules ## Development of rules
If you want to develop a new rule, follow as an example the already existing rules in the [rule package](https://github.com/mgechev/revive/tree/master/rule). If you want to develop a new rule, follow as an example the already existing rules in the [rule package](https://github.com/mgechev/revive/tree/master/rule).

View File

@@ -3,40 +3,35 @@ package logging
import ( import (
"io" "io"
"log" "log/slog"
"os" "os"
) )
var logger *log.Logger const logFile = "revive.log"
var logger *slog.Logger
// GetLogger retrieves an instance of an application logger which outputs // GetLogger retrieves an instance of an application logger which outputs
// to a file if the debug flag is enabled // to a file if the debug flag is enabled
func GetLogger() (*log.Logger, error) { func GetLogger() (*slog.Logger, error) {
if logger != nil { if logger != nil {
return logger, nil return logger, nil
} }
var writer io.Writer debugModeEnabled := os.Getenv("DEBUG") != ""
var err error
writer = io.Discard // by default, suppress all logging output
debugModeEnabled := os.Getenv("DEBUG") == "1"
if debugModeEnabled {
writer, err = os.Create("revive.log")
if err != nil {
return nil, err
}
}
logger = log.New(writer, "", log.LstdFlags)
if !debugModeEnabled { if !debugModeEnabled {
// Clear all flags to skip log output formatting step to increase // by default, suppress all logging output
// performance somewhat if we're not logging anything return slog.New(slog.NewTextHandler(io.Discard, nil)), nil // TODO: change to slog.New(slog.DiscardHandler) when we switch to Go 1.24
logger.SetFlags(0)
} }
logger.Println("Logger initialized") fileWriter, err := os.Create(logFile)
if err != nil {
return nil, err
}
logger = slog.New(slog.NewTextHandler(io.MultiWriter(os.Stderr, fileWriter), nil))
logger.Info("Logger initialized", "logFile", logFile)
return logger, nil return logger, nil
} }

60
logging/logger_test.go Normal file
View File

@@ -0,0 +1,60 @@
package logging_test
import (
"os"
"testing"
"github.com/mgechev/revive/logging"
)
func TestGetLogger(t *testing.T) {
t.Run("no debug", func(t *testing.T) {
t.Setenv("DEBUG", "")
logger, err := logging.GetLogger()
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if logger == nil {
t.Fatal("expected logger to be non-nil")
}
logger.Info("msg") // no output
})
t.Run("debug", func(t *testing.T) {
t.Setenv("DEBUG", "1")
t.Cleanup(func() { os.Remove("revive.log") })
logger, err := logging.GetLogger()
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if logger == nil {
t.Fatal("expected logger to be non-nil")
}
if _, err := os.Stat("revive.log"); os.IsNotExist(err) {
t.Error("expected revive.log file to be created")
}
})
t.Run("reuse logger", func(t *testing.T) {
t.Setenv("DEBUG", "1")
t.Cleanup(func() { os.Remove("revive.log") })
logger1, err := logging.GetLogger()
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
logger2, err := logging.GetLogger()
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if logger1 != logger2 {
t.Errorf("expected the same logger instance to be returned: logger1=%+v, logger2=%+v", logger1, logger2)
}
})
}

View File

@@ -3,8 +3,10 @@ package revivelib
import ( import (
"fmt" "fmt"
"log" "log/slog"
"maps"
"os" "os"
"slices"
"strings" "strings"
"github.com/mgechev/dots" "github.com/mgechev/dots"
@@ -18,7 +20,7 @@ import (
type Revive struct { type Revive struct {
config *lint.Config config *lint.Config
lintingRules []lint.Rule lintingRules []lint.Rule
logger *log.Logger logger *slog.Logger
maxOpenFiles int maxOpenFiles int
} }
@@ -56,7 +58,7 @@ func New(
return nil, fmt.Errorf("initializing revive - getting lint rules: %w", err) return nil, fmt.Errorf("initializing revive - getting lint rules: %w", err)
} }
logger.Println("Config loaded") logger.Info("Config loaded", "rules", slices.Collect(maps.Keys(conf.Rules)))
return &Revive{ return &Revive{
logger: logger, logger: logger,