Refactor logging to use slog package across the application

- Replaced standard log package with log/slog in httpclient, nginx manager, sync service, updater, and other components for structured logging.
- Introduced environment variable `LOG_LEVEL` to control logging levels (debug, info, warn, error).
- Updated documentation to reflect changes in logging configuration and requirements.
- Added a new logging setup function in the ats_agent internal package to initialize the slog logger.
This commit is contained in:
ryan
2026-03-13 14:53:51 +08:00
parent 06d4831d55
commit aeb7118b30
17 changed files with 321 additions and 209 deletions
+2 -3
View File
@@ -3,7 +3,6 @@ package common
import (
"flag"
"fmt"
"log"
"os"
"path/filepath"
"strings"
@@ -59,12 +58,12 @@ func init() {
var err error
*LogDir, err = filepath.Abs(*LogDir)
if err != nil {
log.Fatal(err)
FatalLog(err)
}
if _, err := os.Stat(*LogDir); os.IsNotExist(err) {
err = os.Mkdir(*LogDir, 0777)
if err != nil {
log.Fatal(err)
FatalLog(err)
}
}
}
+117 -60
View File
@@ -1,15 +1,14 @@
package common
import (
"fmt"
"github.com/gin-gonic/gin"
"io"
"log"
"os"
"path/filepath"
"strings"
"time"
)
package common
import (
"context"
"github.com/gin-gonic/gin"
"io"
"log/slog"
"os"
"path/filepath"
"strings"
)
type logLevel int
@@ -20,19 +19,76 @@ const (
logLevelError
)
var currentLogLevel = logLevelInfo
var currentLogLevelName = "info"
var commonLogWriter io.Writer = os.Stdout
var errorLogWriter io.Writer = os.Stderr
var currentLogLevel = logLevelInfo
var currentLogLevelName = "info"
var commonLogWriter io.Writer = os.Stdout
var errorLogWriter io.Writer = os.Stderr
var defaultLogger *slog.Logger
type levelRouterHandler struct {
commonHandler slog.Handler
errorHandler slog.Handler
}
func (h *levelRouterHandler) Enabled(ctx context.Context, level slog.Level) bool {
return h.commonHandler.Enabled(ctx, level) || h.errorHandler.Enabled(ctx, level)
}
func (h *levelRouterHandler) Handle(ctx context.Context, record slog.Record) error {
if record.Level >= slog.LevelError {
return h.errorHandler.Handle(ctx, record)
}
return h.commonHandler.Handle(ctx, record)
}
func (h *levelRouterHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
return &levelRouterHandler{
commonHandler: h.commonHandler.WithAttrs(attrs),
errorHandler: h.errorHandler.WithAttrs(attrs),
}
}
func (h *levelRouterHandler) WithGroup(name string) slog.Handler {
return &levelRouterHandler{
commonHandler: h.commonHandler.WithGroup(name),
errorHandler: h.errorHandler.WithGroup(name),
}
}
func configureGinWriters() {
if shouldLog(logLevelDebug) {
gin.DefaultWriter = commonLogWriter
func configureGinWriters() {
if shouldLog(logLevelDebug) {
gin.DefaultWriter = commonLogWriter
} else {
gin.DefaultWriter = io.Discard
}
gin.DefaultErrorWriter = errorLogWriter
}
gin.DefaultErrorWriter = errorLogWriter
}
func slogLevel() slog.Level {
switch currentLogLevel {
case logLevelDebug:
return slog.LevelDebug
case logLevelWarn:
return slog.LevelWarn
case logLevelError:
return slog.LevelError
default:
return slog.LevelInfo
}
}
func ensureLogger() *slog.Logger {
if defaultLogger != nil {
return defaultLogger
}
handlerOptions := &slog.HandlerOptions{Level: slogLevel()}
defaultLogger = slog.New(&levelRouterHandler{
commonHandler: slog.NewTextHandler(commonLogWriter, handlerOptions),
errorHandler: slog.NewTextHandler(errorLogWriter, handlerOptions),
})
slog.SetDefault(defaultLogger)
return defaultLogger
}
func SetLogLevel(level string) {
normalized := strings.TrimSpace(strings.ToLower(level))
@@ -61,42 +117,43 @@ func shouldLog(level logLevel) bool {
return level >= currentLogLevel
}
func SetupGinLog() {
if *LogDir != "" {
commonLogPath := filepath.Join(*LogDir, "common.log")
errorLogPath := filepath.Join(*LogDir, "error.log")
commonFd, err := os.OpenFile(commonLogPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal("failed to open log file")
}
errorFd, err := os.OpenFile(errorLogPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal("failed to open log file")
}
commonLogWriter = io.MultiWriter(os.Stdout, commonFd)
errorLogWriter = io.MultiWriter(os.Stderr, errorFd)
}
configureGinWriters()
}
func SysLog(s string) {
if !shouldLog(logLevelInfo) {
return
}
t := time.Now()
_, _ = fmt.Fprintf(commonLogWriter, "[SYS] %v | %s \n", t.Format("2006/01/02 - 15:04:05"), s)
}
func SysError(s string) {
if !shouldLog(logLevelError) {
return
}
t := time.Now()
_, _ = fmt.Fprintf(errorLogWriter, "[SYS] %v | %s \n", t.Format("2006/01/02 - 15:04:05"), s)
}
func FatalLog(v ...any) {
t := time.Now()
_, _ = fmt.Fprintf(errorLogWriter, "[FATAL] %v | %v \n", t.Format("2006/01/02 - 15:04:05"), v)
os.Exit(1)
}
func SetupGinLog() {
if *LogDir != "" {
commonLogPath := filepath.Join(*LogDir, "common.log")
errorLogPath := filepath.Join(*LogDir, "error.log")
commonFd, err := os.OpenFile(commonLogPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
_, _ = io.WriteString(os.Stderr, "failed to open common log file\n")
os.Exit(1)
}
errorFd, err := os.OpenFile(errorLogPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
_, _ = io.WriteString(os.Stderr, "failed to open error log file\n")
os.Exit(1)
}
commonLogWriter = io.MultiWriter(os.Stdout, commonFd)
errorLogWriter = io.MultiWriter(os.Stderr, errorFd)
}
configureGinWriters()
defaultLogger = nil
ensureLogger()
}
func SysLog(s string) {
if !shouldLog(logLevelInfo) {
return
}
ensureLogger().Info(s)
}
func SysError(s string) {
if !shouldLog(logLevelError) {
return
}
ensureLogger().Error(s)
}
func FatalLog(v ...any) {
ensureLogger().Error("fatal error", "details", v)
os.Exit(1)
}
+2 -3
View File
@@ -4,7 +4,6 @@ import (
"fmt"
"github.com/google/uuid"
"html/template"
"log"
"net"
"os/exec"
"runtime"
@@ -24,14 +23,14 @@ func OpenBrowser(url string) {
err = exec.Command("open", url).Start()
}
if err != nil {
log.Println(err)
SysError(err.Error())
}
}
func GetIp() (ip string) {
ips, err := net.InterfaceAddrs()
if err != nil {
log.Println(err)
SysError(err.Error())
return ip
}
+1 -2
View File
@@ -12,7 +12,6 @@ import (
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-contrib/sessions/redis"
"github.com/gin-gonic/gin"
"log"
"os"
"strconv"
)
@@ -87,7 +86,7 @@ func main() {
common.SysLog(fmt.Sprintf("server listening on :%s", port))
err = server.Run(":" + port)
if err != nil {
log.Println(err)
common.SysError(err.Error())
}
}
+3 -4
View File
@@ -3,7 +3,6 @@ package middleware
import (
"atsflare/common"
"context"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"time"
@@ -19,7 +18,7 @@ func redisRateLimiter(c *gin.Context, maxRequestNum int, duration int64, mark st
key := "rateLimit:" + mark + c.ClientIP()
listLength, err := rdb.LLen(ctx, key).Result()
if err != nil {
fmt.Println(err.Error())
common.SysError(err.Error())
c.Status(http.StatusInternalServerError)
c.Abort()
return
@@ -31,7 +30,7 @@ func redisRateLimiter(c *gin.Context, maxRequestNum int, duration int64, mark st
oldTimeStr, _ := rdb.LIndex(ctx, key, -1).Result()
oldTime, err := time.Parse(timeFormat, oldTimeStr)
if err != nil {
fmt.Println(err)
common.SysError(err.Error())
c.Status(http.StatusInternalServerError)
c.Abort()
return
@@ -39,7 +38,7 @@ func redisRateLimiter(c *gin.Context, maxRequestNum int, duration int64, mark st
nowTimeStr := time.Now().Format(timeFormat)
nowTime, err := time.Parse(timeFormat, nowTimeStr)
if err != nil {
fmt.Println(err)
common.SysError(err.Error())
c.Status(http.StatusInternalServerError)
c.Abort()
return
+2 -3
View File
@@ -8,7 +8,6 @@ import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
"os/exec"
@@ -137,7 +136,7 @@ func ScheduleServerUpgrade(channel string) (*LatestServerRelease, error) {
go func(task *preparedServerUpgrade) {
time.Sleep(serverUpgradeDispatchDelay)
if err := executeServerUpgrade(task); err != nil {
log.Printf("server self-update failed: %v", err)
common.SysError(fmt.Sprintf("server self-update failed: %v", err))
serverUpgradeState.Lock()
serverUpgradeState.inProgress = false
serverUpgradeState.Unlock()
@@ -251,7 +250,7 @@ func ConfirmManualServerUpgrade(uploadToken string) (*UploadedServerBinary, erro
go func(task *manualServerBinaryCandidate) {
time.Sleep(serverUpgradeDispatchDelay)
if err := executeManualServerUpgrade(task); err != nil {
log.Printf("server manual upgrade failed: %v", err)
common.SysError(fmt.Sprintf("server manual upgrade failed: %v", err))
serverUpgradeState.Lock()
serverUpgradeState.inProgress = false
serverUpgradeState.Unlock()