[WIP] Replace logrus with slog
This commit is contained in:
@@ -5,8 +5,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"aleesa-telegram-go/internal/log"
|
||||||
|
|
||||||
"github.com/hjson/hjson-go"
|
"github.com/hjson/hjson-go"
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// parseConfig разбирает и валидирует даденный конфиг.
|
// parseConfig разбирает и валидирует даденный конфиг.
|
||||||
|
|||||||
176
internal/log/log.go
Normal file
176
internal/log/log.go
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log/slog"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Handler exposes slog handler struct.
|
||||||
|
var Handler slog.Handler
|
||||||
|
|
||||||
|
// Ctx log context. For now it is just sits here and do nothing.
|
||||||
|
var Ctx = context.Background()
|
||||||
|
|
||||||
|
// Writer go-writer eported for capturing other types of logs, even for std log go facility.
|
||||||
|
var Writer io.Writer
|
||||||
|
|
||||||
|
// reader is required for Writer to work properly. It is connected via io.Pipe() to Writer.
|
||||||
|
var reader io.Reader
|
||||||
|
|
||||||
|
// Init setup logger stuff.
|
||||||
|
// level can be error, warn, info, debug if something other supplied info level selected.
|
||||||
|
// fileDescriptor should be opened before supplying it to Init().
|
||||||
|
func Init(level string, fileDescriptor *os.File) {
|
||||||
|
var loglevel slog.Level
|
||||||
|
|
||||||
|
// no panic, no trace.
|
||||||
|
switch level {
|
||||||
|
case "debug":
|
||||||
|
loglevel = slog.LevelDebug
|
||||||
|
|
||||||
|
case "info":
|
||||||
|
loglevel = slog.LevelInfo
|
||||||
|
|
||||||
|
case "warn":
|
||||||
|
loglevel = slog.LevelWarn
|
||||||
|
|
||||||
|
case "error":
|
||||||
|
loglevel = slog.LevelError
|
||||||
|
|
||||||
|
default:
|
||||||
|
loglevel = slog.LevelInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
opts := &slog.HandlerOptions{ //nolint: exhaustruct
|
||||||
|
// Use the ReplaceAttr function on the handler options
|
||||||
|
// to be able to replace any single attribute in the log output
|
||||||
|
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr { //nolint: revive
|
||||||
|
// check that we are handling the time key
|
||||||
|
if a.Key != slog.TimeKey {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
t := a.Value.Time()
|
||||||
|
|
||||||
|
// change the value from a time.Time to a String
|
||||||
|
// where the string has the correct time format.
|
||||||
|
a.Value = slog.StringValue(t.Format(time.DateTime))
|
||||||
|
|
||||||
|
return a
|
||||||
|
},
|
||||||
|
|
||||||
|
Level: loglevel,
|
||||||
|
}
|
||||||
|
|
||||||
|
Handler = slog.NewTextHandler(fileDescriptor, opts)
|
||||||
|
|
||||||
|
slog.SetDefault(
|
||||||
|
slog.New(Handler),
|
||||||
|
)
|
||||||
|
|
||||||
|
reader, Writer = io.Pipe()
|
||||||
|
|
||||||
|
go readIoPipe()
|
||||||
|
}
|
||||||
|
|
||||||
|
// readIoPipe reads pipe and writes it to slog.
|
||||||
|
func readIoPipe() {
|
||||||
|
scanner := bufio.NewScanner(reader)
|
||||||
|
|
||||||
|
for {
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text() // Get the current line as a string
|
||||||
|
slog.Debug(line)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
// io.EOF is expected when done reading, e.g. on exit.
|
||||||
|
if errors.Is(err, io.EOF) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// something weird happen, we should it log to guess later what it was.
|
||||||
|
Errorf("Error during scanning log writer pipe: %v\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLevel returns current loglevel.
|
||||||
|
func GetLevel() string {
|
||||||
|
switch {
|
||||||
|
case Handler.Enabled(Ctx, slog.LevelDebug):
|
||||||
|
return "debug"
|
||||||
|
|
||||||
|
case Handler.Enabled(Ctx, slog.LevelInfo):
|
||||||
|
return "info"
|
||||||
|
|
||||||
|
case Handler.Enabled(Ctx, slog.LevelWarn):
|
||||||
|
return "warn"
|
||||||
|
|
||||||
|
case Handler.Enabled(Ctx, slog.LevelError):
|
||||||
|
return "error"
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fatal passes message directly to slog.Error() and exits with error code 1.
|
||||||
|
func Fatal(message string) {
|
||||||
|
slog.Error(message)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fatalf logs message on error log level and exits with error code 1. It allows to supply arguments in printf() style .
|
||||||
|
func Fatalf(format string, a ...any) {
|
||||||
|
slog.Error(fmt.Sprintf(format, a...))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error passes message directly to slog.Error().
|
||||||
|
func Error(message string) {
|
||||||
|
slog.Error(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf logs message on error log level and allows to supply arguments in printf() style.
|
||||||
|
func Errorf(format string, a ...any) {
|
||||||
|
slog.Error(fmt.Sprintf(format, a...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warn passes message directly to slog.Warn().
|
||||||
|
func Warn(message string) {
|
||||||
|
slog.Warn(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warnf logs message on warn log level and allows to supply arguments in printf() style.
|
||||||
|
func Warnf(format string, a ...any) {
|
||||||
|
slog.Warn(fmt.Sprintf(format, a...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info passes message directly to slog.Info().
|
||||||
|
func Info(message string) {
|
||||||
|
slog.Info(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infof logs message on info log level and allows to supply arguments in printf() style.
|
||||||
|
func Infof(format string, a ...any) {
|
||||||
|
slog.Info(fmt.Sprintf(format, a...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug passes message directly to slog.Debug().
|
||||||
|
func Debug(message string) {
|
||||||
|
slog.Debug(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugf logs message on debug log level and allows to supply arguments in printf() style.
|
||||||
|
func Debugf(format string, a ...any) {
|
||||||
|
slog.Debug(fmt.Sprintf(format, a...))
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||||
52
main.go
52
main.go
@@ -8,43 +8,21 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"aleesa-telegram-go/internal/log"
|
||||||
|
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/go-redis/redis/v8"
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// init производит некоторую инициализацию перед запуском main().
|
// init производит некоторую инициализацию перед запуском main().
|
||||||
func init() {
|
func init() {
|
||||||
log.SetFormatter(&log.TextFormatter{
|
var (
|
||||||
DisableQuote: true,
|
err error
|
||||||
DisableLevelTruncation: false,
|
)
|
||||||
DisableColors: true,
|
|
||||||
FullTimestamp: true,
|
|
||||||
TimestampFormat: "2006-01-02 15:04:05",
|
|
||||||
})
|
|
||||||
|
|
||||||
// no panic, no trace
|
|
||||||
switch config.Loglevel {
|
|
||||||
case "fatal":
|
|
||||||
log.SetLevel(log.FatalLevel)
|
|
||||||
case "error":
|
|
||||||
log.SetLevel(log.ErrorLevel)
|
|
||||||
case "warn":
|
|
||||||
log.SetLevel(log.WarnLevel)
|
|
||||||
case "info":
|
|
||||||
log.SetLevel(log.InfoLevel)
|
|
||||||
case "debug":
|
|
||||||
log.SetLevel(log.DebugLevel)
|
|
||||||
default:
|
|
||||||
log.SetLevel(log.InfoLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
|
||||||
|
|
||||||
executablePath, err := os.Executable()
|
executablePath, err := os.Executable()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Unable to get current executable path: %s", err)
|
log.Fatalf("Unable to get current executable path: %s", err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
configJSONPath := fmt.Sprintf("%s/data/config.json", filepath.Dir(executablePath))
|
configJSONPath := fmt.Sprintf("%s/data/config.json", filepath.Dir(executablePath))
|
||||||
@@ -72,19 +50,25 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Main context
|
var (
|
||||||
var ctx = context.Background()
|
logfile *os.File
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
// Откроем лог и скормим его логгеру.
|
// Откроем лог и скормим его логгеру.
|
||||||
if config.Log != "" {
|
if config.Log != "" {
|
||||||
logfile, err := os.OpenFile(config.Log, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
|
logfile, err = os.OpenFile(config.Log, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Unable to open log file %s: %s", config.Log, err)
|
log.Errorf("Unable to open log file %s: %s", config.Log, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.SetOutput(logfile)
|
log.Init(config.Loglevel, logfile)
|
||||||
}
|
|
||||||
|
// Main context
|
||||||
|
var ctx = context.Background()
|
||||||
|
|
||||||
// Инициализируем redis-клиента.
|
// Инициализируем redis-клиента.
|
||||||
redisClient = redis.NewClient(&redis.Options{
|
redisClient = redis.NewClient(&redis.Options{
|
||||||
|
|||||||
@@ -8,9 +8,10 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"aleesa-telegram-go/internal/log"
|
||||||
|
|
||||||
"github.com/NicoNex/echotron/v3"
|
"github.com/NicoNex/echotron/v3"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// telego msg parser
|
// telego msg parser
|
||||||
|
|||||||
@@ -6,9 +6,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
|
||||||
|
"aleesa-telegram-go/internal/log"
|
||||||
|
|
||||||
"github.com/cockroachdb/errors/oserror"
|
"github.com/cockroachdb/errors/oserror"
|
||||||
"github.com/cockroachdb/pebble"
|
"github.com/cockroachdb/pebble"
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// StoreKV сохраняет в указанной бд ключ и значение.
|
// StoreKV сохраняет в указанной бд ключ и значение.
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"aleesa-telegram-go/internal/log"
|
||||||
|
|
||||||
"github.com/NicoNex/echotron/v3"
|
"github.com/NicoNex/echotron/v3"
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// telega основная горутинка, реализующая бота.
|
// telega основная горутинка, реализующая бота.
|
||||||
|
|||||||
8
util.go
8
util.go
@@ -4,7 +4,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
"aleesa-telegram-go/internal/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// sigHandler хэндлер сигналов закрывает все бд, все сетевые соединения и сваливает из приложения.
|
// sigHandler хэндлер сигналов закрывает все бд, все сетевые соединения и сваливает из приложения.
|
||||||
@@ -15,11 +15,11 @@ func sigHandler() {
|
|||||||
var s = <-sigChan
|
var s = <-sigChan
|
||||||
switch s {
|
switch s {
|
||||||
case syscall.SIGINT:
|
case syscall.SIGINT:
|
||||||
log.Infoln("Got SIGINT, quitting")
|
log.Info("Got SIGINT, quitting")
|
||||||
case syscall.SIGTERM:
|
case syscall.SIGTERM:
|
||||||
log.Infoln("Got SIGTERM, quitting")
|
log.Info("Got SIGTERM, quitting")
|
||||||
case syscall.SIGQUIT:
|
case syscall.SIGQUIT:
|
||||||
log.Infoln("Got SIGQUIT, quitting")
|
log.Info("Got SIGQUIT, quitting")
|
||||||
|
|
||||||
// Заходим на новую итерацию, если у нас "неинтересный" сигнал.
|
// Заходим на новую итерацию, если у нас "неинтересный" сигнал.
|
||||||
default:
|
default:
|
||||||
|
|||||||
Reference in New Issue
Block a user