package logger import ( "fmt" "os" "path/filepath" "github.com/natefinch/lumberjack" "go.uber.org/zap" "go.uber.org/zap/zapcore" "joylink.club/bj-rtsts-server/config" ) const DefaultLogPath = "/var/logs" // 初始化日志 func InitLogger() error { 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{} // //} // zap.S().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), // 返回花费时间 // ) // } // }