Go 即时通讯系统:日志模块重构,并从main函数开始

06-02 1318阅读

重构logger

上次写的logger.go过于繁琐,有很多没用到的功能;重构后只提供了简洁的日志接口,支持日志轮转、多级别日志记录等功能,并采用单例模式确保全局只有一个日志实例

全局变量

var (
    once    sync.Once        // 用于实现单例模式的同步控制
    Logger  *zap.Logger      // 全局日志实例
    String  = zap.String     // 导出常用的 zap.Field 构造方法
    Any     = zap.Any
    Err     = zap.Error
    Int     = zap.Int
    Float32 = zap.Float32
)

默认配置常量

const (
    defaultLogPath    = "./logs"      // 默认日志存储目录
    defaultLogLevel   = "debug"        // 默认日志级别
    defaultMaxSize    = 100           // 单个日志文件最大大小(MB)
    defaultMaxBackups = 30            // 保留的旧日志文件数量
    defaultMaxAge     = 7             // 日志保留天数
    defaultCompress   = true          // 是否压缩旧日志
)

初始化日志记录器

// Init 初始化日志记录器(单例模式)
func Init() *zap.Logger {
	once.Do(func() {
		// 确保日志目录存在
		if err := os.MkdirAll(defaultLogPath, 0755); err != nil {
			panic(err)
		}
		// 设置日志级别
		level := getLogLevel(defaultLogLevel)
		// 日志文件路径
		logFile := getDatedLogFilename(defaultLogPath)
		// 设置日志轮转
		writer := zapcore.AddSync(&lumberjack.Logger{
			Filename:   logFile,
			MaxSize:    defaultMaxSize,    // MB
			MaxBackups: defaultMaxBackups, // 保留的旧日志文件数量
			MaxAge:     defaultMaxAge,     // 保留天数
			Compress:   defaultCompress,   // 是否压缩
		})
		// 编码器配置
		encoderConfig := zap.NewProductionEncoderConfig()
		encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
		encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder // 不带颜色
		// 核心配置
		core := zapcore.NewCore(
			// zapcore.NewJSONEncoder(encoderConfig), // json格式
			zapcore.NewConsoleEncoder(encoderConfig), // 使用 Console 编码器
			writer,
			level,
		)
		// 创建Logger
		Logger = zap.New(core)
	})
	return Logger
}

获取日志实例

func GetLogger() *zap.Logger {
    if Logger == nil {
        Init() // 自动初始化
    }
    return Logger
}

直接可用的日志方法

func Debug(msg string, fields ...zap.Field) {
    GetLogger().Debug(msg, fields...)
}
func Info(msg string, fields ...zap.Field) {
    GetLogger().Info(msg, fields...)
}
func Warn(msg string, fields ...zap.Field) {
    GetLogger().Warn(msg, fields...)
}
func Error(msg string, fields ...zap.Field) {
    GetLogger().Error(msg, fields...)
}
func Fatal(msg string, fields ...zap.Field) {
    GetLogger().Fatal(msg, fields...)
}
func Sync() error {
    return GetLogger().Sync()
}

代码地址:logger.go

从main函数开始

Go 即时通讯系统:日志模块重构,并从main函数开始

func main() {
	defer log.Sync() // 记录日志
	log.Info("start chat server...")
	newRouter := router.NewRouter()
	go chat.MyServer.Start()
	s := &http.Server{
        Addr:           ":8080",
		Handler:        newRouter,
		ReadTimeout:    10 * time.Second,
		WriteTimeout:   10 * time.Second,
		MaxHeaderBytes: 1 
		log.Error("server start error", log.Err(err))
	}
}

	gin.SetMode(gin.ReleaseMode)
	server := gin.Default()
	server.Use(Cors())
	server.Use(Recovery)
	socket := RunSocket
	
	group := server.Group("")
	{
		// 用户管理功能
		group.GET("/user", api.GetUserList)
		group.GET("/user/:uuid", api.GetUserDetails)
		group.GET("/user/name", api.GetUserOrGroupByName)
		group.POST("/user/register", api.Register)
		group.POST("/user/login", api.Login)
		group.PUT("/user", api.ModifyUserInfo)
		group.POST("/friend", api.AddFriend)
		group.GET("/message", api.GetMessage)
		group.GET("/file/:fileName", api.GetFile)
		group.POST("/file", api.SaveFile)
		group.GET("/group/:uuid", api.GetGroup)
		group.POST("/group/:uuid", api.SaveGroup)
		group.POST("/group/join/:userUuid/:groupUuid", api.JoinGroup)
		group.GET("/group/user/:uuid", api.GetGroupUsers)
		group.GET("/socket.io", socket)
	}
	return server
}

    return func(c *gin.Context) {
        method := c.Request.Method
        origin := c.Request.Header.Get("Origin")
        if origin != "" {
            // 设置跨域响应头
            c.Header("Access-Control-Allow-Origin", "*")
            c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
            c.Header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization")
            c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Cache-Control, Content-Language, Content-Type")
            c.Header("Access-Control-Allow-Credentials", "true")
        }
        
        // 处理 OPTIONS 预检请求
        if method == "OPTIONS" {
            c.JSON(http.StatusOK, "ok!")
            return
        }
        // 异常捕获
        defer func() {
            if err := recover(); err != nil {
                log.Error("HttpError", log.Any("HttpError", err))
            }
        }()
        c.Next() // 处理请求
    }
}

    defer func() {
        if r := recover(); r != nil {
            log.Error("gin catch error", log.Any("error", r))
            c.JSON(http.StatusOK, response.FailMsg("系统内部错误"))
        }
    }()
    c.Next()
}

    CheckOrigin: func(r *http.Request) bool {
        return true // 允许所有跨域 WebSocket 连接
    },
}
func RunSocket(c *gin.Context) {
    user := c.Query("user") // 获取用户标识
    if user == "" {
        return // 无用户标识则拒绝连接
    }
    log.Info("newUser", log.String("newUser", user))
    // 升级 HTTP 连接为 WebSocket 连接
    ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
    if err != nil {
        return
    }
    // 创建客户端对象
    client := &server.Client{
        Name: user,
        Conn: ws,
        Send: make(chan []byte),
    }
    // 注册客户端到服务器
    server.MyServer.Register 
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码