Files
ai_english/serve/internal/logger/logger.go

245 lines
5.5 KiB
Go
Raw Permalink Normal View History

2025-11-17 14:09:17 +08:00
package logger
import (
"fmt"
"io"
"os"
"path/filepath"
"time"
"github.com/sirupsen/logrus"
"gopkg.in/natefinch/lumberjack.v2"
)
var Logger *logrus.Logger
// LogConfig 日志配置
type LogConfig struct {
Level string `json:"level"` // 日志级别
Format string `json:"format"` // 日志格式 json/text
Output string `json:"output"` // 输出方式 console/file/both
FilePath string `json:"file_path"` // 日志文件路径
MaxSize int `json:"max_size"` // 单个日志文件最大大小(MB)
MaxBackups int `json:"max_backups"` // 保留的旧日志文件数量
MaxAge int `json:"max_age"` // 日志文件保留天数
Compress bool `json:"compress"` // 是否压缩旧日志文件
}
// InitLogger 初始化日志系统
func InitLogger(config LogConfig) {
Logger = logrus.New()
// 设置日志级别
setLogLevel(config.Level)
// 设置日志格式
setLogFormat(config.Format)
// 设置日志输出
setLogOutput(config)
// 添加钩子
addHooks()
Logger.Info("Logger initialized successfully")
}
// setLogLevel 设置日志级别
func setLogLevel(level string) {
switch level {
case "debug":
Logger.SetLevel(logrus.DebugLevel)
case "info":
Logger.SetLevel(logrus.InfoLevel)
case "warn":
Logger.SetLevel(logrus.WarnLevel)
case "error":
Logger.SetLevel(logrus.ErrorLevel)
case "fatal":
Logger.SetLevel(logrus.FatalLevel)
case "panic":
Logger.SetLevel(logrus.PanicLevel)
default:
Logger.SetLevel(logrus.InfoLevel)
}
}
// setLogFormat 设置日志格式
func setLogFormat(format string) {
switch format {
case "json":
Logger.SetFormatter(&logrus.JSONFormatter{
TimestampFormat: time.RFC3339,
})
case "text":
Logger.SetFormatter(&logrus.TextFormatter{
FullTimestamp: true,
TimestampFormat: "2006-01-02 15:04:05",
})
default:
Logger.SetFormatter(&logrus.JSONFormatter{
TimestampFormat: time.RFC3339,
})
}
}
// setLogOutput 设置日志输出
func setLogOutput(config LogConfig) {
switch config.Output {
case "console":
Logger.SetOutput(os.Stdout)
case "file":
setFileOutput(config)
case "both":
setBothOutput(config)
default:
Logger.SetOutput(os.Stdout)
}
}
// setFileOutput 设置文件输出
func setFileOutput(config LogConfig) {
// 确保日志目录存在
logDir := filepath.Dir(config.FilePath)
if err := os.MkdirAll(logDir, 0755); err != nil {
fmt.Printf("Failed to create log directory: %v\n", err)
return
}
// 配置日志轮转
lumberjackLogger := &lumberjack.Logger{
Filename: config.FilePath,
MaxSize: config.MaxSize,
MaxBackups: config.MaxBackups,
MaxAge: config.MaxAge,
Compress: config.Compress,
}
Logger.SetOutput(lumberjackLogger)
}
// setBothOutput 设置同时输出到控制台和文件
func setBothOutput(config LogConfig) {
// 确保日志目录存在
logDir := filepath.Dir(config.FilePath)
if err := os.MkdirAll(logDir, 0755); err != nil {
fmt.Printf("Failed to create log directory: %v\n", err)
Logger.SetOutput(os.Stdout)
return
}
// 配置日志轮转
lumberjackLogger := &lumberjack.Logger{
Filename: config.FilePath,
MaxSize: config.MaxSize,
MaxBackups: config.MaxBackups,
MaxAge: config.MaxAge,
Compress: config.Compress,
}
// 同时输出到控制台和文件,避免嵌套/转义问题
Logger.SetOutput(io.MultiWriter(os.Stdout, lumberjackLogger))
}
// addHooks 添加日志钩子
func addHooks() {
// 添加调用者信息钩子
Logger.AddHook(&CallerHook{})
}
// FileHook 文件输出钩子
type FileHook struct {
Writer *lumberjack.Logger
}
func (hook *FileHook) Fire(entry *logrus.Entry) error {
line, err := entry.String()
if err != nil {
return err
}
_, err = hook.Writer.Write([]byte(line))
return err
}
func (hook *FileHook) Levels() []logrus.Level {
return logrus.AllLevels
}
// CallerHook 调用者信息钩子
type CallerHook struct{}
func (hook *CallerHook) Fire(entry *logrus.Entry) error {
if entry.HasCaller() {
entry.Data["file"] = fmt.Sprintf("%s:%d", filepath.Base(entry.Caller.File), entry.Caller.Line)
entry.Data["function"] = entry.Caller.Function
}
return nil
}
func (hook *CallerHook) Levels() []logrus.Level {
return logrus.AllLevels
}
// 便捷方法
func Debug(args ...interface{}) {
Logger.Debug(args...)
}
func Debugf(format string, args ...interface{}) {
Logger.Debugf(format, args...)
}
func Info(args ...interface{}) {
Logger.Info(args...)
}
func Infof(format string, args ...interface{}) {
Logger.Infof(format, args...)
}
func Warn(args ...interface{}) {
Logger.Warn(args...)
}
func Warnf(format string, args ...interface{}) {
Logger.Warnf(format, args...)
}
func Error(args ...interface{}) {
Logger.Error(args...)
}
func Errorf(format string, args ...interface{}) {
Logger.Errorf(format, args...)
}
func Fatal(args ...interface{}) {
Logger.Fatal(args...)
}
func Fatalf(format string, args ...interface{}) {
Logger.Fatalf(format, args...)
}
func Panic(args ...interface{}) {
Logger.Panic(args...)
}
func Panicf(format string, args ...interface{}) {
Logger.Panicf(format, args...)
}
// WithFields 创建带字段的日志条目
func WithFields(fields logrus.Fields) *logrus.Entry {
return Logger.WithFields(fields)
}
// WithField 创建带单个字段的日志条目
func WithField(key string, value interface{}) *logrus.Entry {
return Logger.WithField(key, value)
}
// WithError 创建带错误信息的日志条目
func WithError(err error) *logrus.Entry {
return Logger.WithError(err)
}