package logger import ( "fmt" "log/slog" "os" "path/filepath" "strings" "github.com/natefinch/lumberjack" "go.uber.org/zap" "go.uber.org/zap/zapcore" "joylink.club/bj-rtsts-server/config" ) const DefaultLogPath = "/var/logs/bjrtsts_server" func InitSlog() { logging := config.Config.Logging slog.Debug("读取日志配置内容", "logging", logging) // 判断日志路径是否存在,如果不存在就创建 if strings.Trim(logging.Path, " ") == "" { logging.Path = DefaultLogPath } // 日志文件 与 日志切割 配置 if strings.Trim(logging.FileName, " ") == "" { logging.FileName = "server.log" } // 默认Info level := slog.LevelInfo if strings.ToUpper(logging.Level) == "DEBUG" { level = slog.LevelDebug } else if strings.ToUpper(logging.Level) == "WARN" { level = slog.LevelWarn } else if strings.ToUpper(logging.Level) == "ERROR" { level = slog.LevelError } if logging.Stdout { // 日志输出到控制台 slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ Level: level, AddSource: false, }))) } else { // 日志输出到日志文件(自动滚动) lumberJackLogger := &lumberjack.Logger{ Filename: filepath.Join(logging.Path, logging.FileName), // 日志文件路径 MaxSize: logging.FileMaxSize, // 单个日志文件最大多少 mb MaxBackups: logging.FileMaxBackups, // 日志备份数量 MaxAge: logging.MaxAge, // 日志最长保留时间 LocalTime: true, // 日志备份使用本地时间 Compress: logging.Compress, // 是否压缩日志 } slog.SetDefault(slog.New(slog.NewJSONHandler(lumberJackLogger, &slog.HandlerOptions{ Level: level, AddSource: false, }))) } } // 初始化日志 func InitLogger() error { InitSlog() // logLevel := map[string]zapcore.Level{ // "debug": zapcore.DebugLevel, // "info": zapcore.InfoLevel, // "warn": zapcore.WarnLevel, // "error": zapcore.ErrorLevel, // } // // 根据配置创建编码器 // encoder := newEncoder() // level, ok := logLevel[config.Config.Logging.Level] // if !ok { // level = logLevel["info"] // } // writeSyncer, err := newLogWriter() // if err != nil { // return err // } // core := zapcore.NewCore(encoder, writeSyncer, level) // logger := zap.New(core, zap.AddCaller()) // zap.ReplaceGlobals(logger) return nil } // 日志编码器 func newEncoder() zapcore.Encoder { encoderConfig := zap.NewProductionEncoderConfig() encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder encoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder if config.Config.Logging.Format == "json" { return zapcore.NewJSONEncoder(encoderConfig) } return zapcore.NewConsoleEncoder(encoderConfig) } func newLogWriter() (zapcore.WriteSyncer, error) { logging := config.Config.Logging fmt.Println(logging) // 判断日志路径是否存在,如果不存在就创建 if logging.Path == "" { logging.Path = DefaultLogPath } if exist := IsExist(logging.Path); !exist { fmt.Println("不存在", logging.Path) if err := os.MkdirAll(logging.Path, os.ModePerm); err != nil { return nil, err } } // 日志文件 与 日志切割 配置 if logging.FileName == "" { logging.FileName = "server.log" } lumberJackLogger := &lumberjack.Logger{ Filename: filepath.Join(logging.Path, logging.FileName), // 日志文件路径 MaxSize: logging.FileMaxSize, // 单个日志文件最大多少 mb MaxBackups: logging.FileMaxBackups, // 日志备份数量 MaxAge: logging.MaxAge, // 日志最长保留时间 LocalTime: true, // 日志备份使用本地时间 Compress: logging.Compress, // 是否压缩日志 } if logging.Stdout { // 日志同时输出到控制台和日志文件中 return zapcore.NewMultiWriteSyncer(zapcore.AddSync(lumberJackLogger), zapcore.AddSync(os.Stdout)), nil } else { // 日志只输出到日志文件 return zapcore.AddSync(lumberJackLogger), nil } } // IsExist 判断文件或者目录是否存在 func IsExist(path string) bool { _, err := os.Stat(path) fmt.Println(err) return err == nil || os.IsExist(err) } // // GinLogger 接收gin框架默认的日志 // func GinLogger() gin.HandlerFunc { // return func(c *gin.Context) { // start := time.Now() // path := c.Request.URL.Path // 请求路径 eg: /test // query := c.Request.URL.RawQuery //query类型的请求参数:?name=1&password=2 // // 挂起当前中间件,执行下一个中间件 // c.Next() // cost := time.Since(start) // // Field 是 Field 的别名。给这个类型起别名极大地提高了这个包的 API 文档的可导航性。 // // type Field struct { // // Key string // // Type FieldType // 类型,数字对应具体类型,eg: 15--->string // // Integer int64 // // String string // // Interface interface{} // //} // slog.Info("处理请求:", // zap.String("method", c.Request.Method), // 请求方法类型 eg: GET // zap.String("path", path), // 请求路径 eg: /test // zap.Int("status", c.Writer.Status()), // 状态码 eg: 200 // zap.String("query", query), // 请求参数 eg: name=1&password=2 // zap.String("ip", c.ClientIP()), // 返回真实的客户端IP eg: ::1(这个就是本机IP,ipv6地址) // zap.String("user-agent", c.Request.UserAgent()), // 返回客户端的用户代理。 eg: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36 // zap.String("errors", c.Errors.ByType(gin.ErrorTypePrivate).String()), // 返回Errors 切片中ErrorTypePrivate类型的错误 // zap.Duration("cost", cost), // 返回花费时间 // ) // } // }