hostSync/utils/logger.go

228 lines
5.5 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package utils
import (
"fmt"
"os"
"path/filepath"
"sync"
"time"
"github.com/evil7/hostsync/config"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var (
fileLogger *zap.Logger
fileSugar *zap.SugaredLogger
consoleLogger *zap.Logger
consoleSugar *zap.SugaredLogger
debugMode bool
logMutex sync.Mutex
)
// InitLogger 初始化日志系统
func InitLogger() error {
if config.AppConfig == nil {
return nil
}
// 根据配置设置日志级别
level := zapcore.InfoLevel
if config.AppConfig.LogLevel != "" {
switch config.AppConfig.LogLevel {
case "debug":
level = zapcore.DebugLevel
case "info":
level = zapcore.InfoLevel
case "warning", "warn":
level = zapcore.WarnLevel
case "error":
level = zapcore.ErrorLevel
case "silent":
level = zapcore.ErrorLevel + 1 // 静默模式,不记录任何日志
}
}
// 创建控制台logger配置只用于错误输出
consoleConfig := zap.Config{
Level: zap.NewAtomicLevelAt(zapcore.ErrorLevel), // 只显示错误
Development: false,
Encoding: "console",
EncoderConfig: zapcore.EncoderConfig{
MessageKey: "msg",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.CapitalLevelEncoder,
},
OutputPaths: []string{"stderr"},
ErrorOutputPaths: []string{"stderr"},
}
var err error
consoleLogger, err = consoleConfig.Build(zap.AddStacktrace(zapcore.DPanicLevel))
if err != nil {
return fmt.Errorf("创建控制台logger失败: %v", err)
}
consoleSugar = consoleLogger.Sugar()
// 如果配置了文件路径创建文件logger
if config.AppConfig.LogPath != "" {
// 确保日志目录存在
if err := os.MkdirAll(config.AppConfig.LogPath, 0755); err != nil {
return fmt.Errorf("创建日志目录失败: %v", err)
}
logFileName := filepath.Join(config.AppConfig.LogPath, "hostsync.log")
// 检查并轮转日志文件
if err := rotateLogIfNeeded(logFileName); err != nil {
return fmt.Errorf("轮转日志文件失败: %v", err)
}
// 创建文件logger配置
fileConfig := zap.Config{
Level: zap.NewAtomicLevelAt(level),
Development: false,
Encoding: "console",
EncoderConfig: zapcore.EncoderConfig{
TimeKey: "time",
LevelKey: "level",
MessageKey: "msg",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.CapitalLevelEncoder,
EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(t.Format("2006-01-02 15:04:05"))
},
},
OutputPaths: []string{logFileName},
ErrorOutputPaths: []string{logFileName},
}
fileLogger, err = fileConfig.Build(zap.AddStacktrace(zapcore.DPanicLevel))
if err != nil {
return fmt.Errorf("创建文件logger失败: %v", err)
}
fileSugar = fileLogger.Sugar()
}
return nil
}
// rotateLogIfNeeded 检查并轮转日志文件
func rotateLogIfNeeded(logFileName string) error {
info, err := os.Stat(logFileName)
if os.IsNotExist(err) {
return nil
}
if err != nil {
return err
}
// 检查文件大小是否超过10MB
if info.Size() < 10*1024*1024 {
return nil
}
// 轮转日志文件
backupName := fmt.Sprintf("%s.%s", logFileName, time.Now().Format("20060102_150405"))
if err := os.Rename(logFileName, backupName); err != nil {
return err
}
// 异步清理旧日志文件
go cleanOldLogs(filepath.Dir(logFileName))
return nil
}
// cleanOldLogs 清理旧的日志备份文件保留最近5个
func cleanOldLogs(logDir string) {
files, err := filepath.Glob(filepath.Join(logDir, "hostsync.log.*"))
if err != nil || len(files) <= 5 {
return
}
// 删除最旧的文件
for i := 0; i < len(files)-5; i++ {
os.Remove(files[i])
}
}
// SetDebugMode 设置调试模式
func SetDebugMode(debug bool) {
debugMode = debug
}
// CloseLogger 关闭日志系统
func CloseLogger() {
if fileLogger != nil {
fileLogger.Sync()
}
if consoleLogger != nil {
consoleLogger.Sync()
}
}
// LogInfo 记录信息日志(只记录到文件)
func LogInfo(format string, args ...interface{}) {
if fileSugar != nil {
fileSugar.Infof(format, args...)
}
}
// LogError 记录错误日志(记录到文件和控制台)
func LogError(format string, args ...interface{}) {
if fileSugar != nil {
fileSugar.Errorf(format, args...)
}
if consoleSugar != nil {
consoleSugar.Errorf(format, args...)
} else {
fmt.Fprintf(os.Stderr, format+"\n", args...)
}
}
// LogDebug 记录调试日志(只记录到文件)
func LogDebug(format string, args ...interface{}) {
if fileSugar != nil {
fileSugar.Debugf(format, args...)
} else if debugMode {
fmt.Printf("DEBUG: "+format+"\n", args...)
}
}
// LogWarning 记录警告日志(只记录到文件)
func LogWarning(format string, args ...interface{}) {
if fileSugar != nil {
fileSugar.Warnf(format, args...)
}
}
// LogSuccess 记录成功日志(只记录到文件)
func LogSuccess(format string, args ...interface{}) {
if fileSugar != nil {
fileSugar.Infof(format, args...)
}
}
// LogFatal 记录致命错误并退出(记录到文件和控制台)
func LogFatal(format string, args ...interface{}) {
if fileSugar != nil {
fileSugar.Fatalf(format, args...)
} else {
fmt.Fprintf(os.Stderr, format+"\n", args...)
os.Exit(1)
}
}
// LogFileOnly 只记录到文件,不显示在控制台
func LogFileOnly(format string, args ...interface{}) {
if fileSugar != nil {
fileSugar.Infof(format, args...)
}
}
// LogResult 用户界面结果输出(直接输出,不使用日志系统)
func LogResult(format string, args ...interface{}) {
fmt.Printf(format, args...)
}