100 lines
2.4 KiB
Go
100 lines
2.4 KiB
Go
package logging
|
|
|
|
import (
|
|
"errors"
|
|
"log/slog"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/lmittmann/tint"
|
|
)
|
|
|
|
// ---------- Standard log handling (terminal or file based) ----------
|
|
|
|
// Logger state shared by the terminal and file loggers.
|
|
var (
|
|
// logLevel is the minimum level logged, read by whichever handler is
|
|
// installed, so changing it takes effect immediately.
|
|
logLevel slog.LevelVar
|
|
// fileLogger is the log file opened by LogToFile, or nil when logging
|
|
// to the terminal.
|
|
fileLogger *os.File
|
|
)
|
|
|
|
// SetLevel sets the logging level without logging the change.
|
|
func SetLevel(level slog.Level) {
|
|
logLevel.Set(level)
|
|
}
|
|
|
|
// EnableDebug lowers the logging level to debug, if it isn't already, and
|
|
// logs that it did.
|
|
func EnableDebug() {
|
|
if logLevel.Level() > slog.LevelDebug {
|
|
logLevel.Set(slog.LevelDebug)
|
|
slog.Debug("Debug logging enabled")
|
|
}
|
|
}
|
|
|
|
// LogToFile sends all logging to logfile as JSON, replacing the default slog
|
|
// logger. The file is created if needed and appended to; any log file opened
|
|
// by an earlier call is closed.
|
|
func LogToFile(logfile string) error {
|
|
closeErr := Shutdown()
|
|
|
|
// Open the log file
|
|
var err error
|
|
fileLogger, err = os.OpenFile(
|
|
filepath.Clean(logfile), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o600,
|
|
)
|
|
if err != nil {
|
|
return errors.Join(err, closeErr)
|
|
}
|
|
|
|
opts := &slog.HandlerOptions{
|
|
Level: &logLevel,
|
|
}
|
|
handler := slog.NewJSONHandler(fileLogger, opts)
|
|
logger := slog.New(handler)
|
|
slog.SetDefault(logger)
|
|
|
|
return closeErr
|
|
}
|
|
|
|
// Shutdown closes the log file opened by LogToFile, if any.
|
|
func Shutdown() error {
|
|
var err error = nil
|
|
if fileLogger != nil {
|
|
err = (*fileLogger).Close()
|
|
fileLogger = nil
|
|
}
|
|
return err
|
|
}
|
|
|
|
// LogToTerminal sends all logging to stdout as coloured text, replacing the
|
|
// default slog logger.
|
|
func LogToTerminal() {
|
|
opts := &tint.Options{
|
|
Level: &logLevel,
|
|
TimeFormat: "*",
|
|
}
|
|
handler := tint.NewTextHandler(os.Stdout, opts)
|
|
logger := slog.New(handler)
|
|
slog.SetDefault(logger)
|
|
}
|
|
|
|
// IsJSONHandler reports whether h writes JSON, as the file logger does.
|
|
func IsJSONHandler(h slog.Handler) bool {
|
|
_, ok := h.(*slog.JSONHandler)
|
|
return ok
|
|
}
|
|
|
|
// IsFileLogger reports whether logging currently goes to a file.
|
|
func IsFileLogger() bool {
|
|
return fileLogger != nil
|
|
}
|
|
|
|
// IsDebugEnabled reports whether debug messages are logged.
|
|
func IsDebugEnabled() bool {
|
|
return logLevel.Level() <= slog.LevelDebug
|
|
}
|