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:
@@ -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).
|
||||||
|
|||||||
@@ -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
60
logging/logger_test.go
Normal 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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user