«

Go日志封装的方法是什么

时间:2024-6-25 14:54     作者:韩俊     分类: Go语言


本篇内容介绍了“Go日志封装的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

Logger 封装的理解

Logger 库主要是一系列方法或接口,提供给应用程序代码调用然后将相关的数据记录到日志记录库中。就是在代码和底层日志库中间的一层。需要实现的功能是能够记录日志,且支持不同日志记录库的切换或添加新的记录库。

封装包,首先需要先定义一些能够描述日志方法的接口,基本的都是你的应用程序所需要的方法。比如,基本的日志接口基本的方法有 Info、Warn、 Error。然后就可以创建此接口的实现,将数据记录到记录库中。定义了接口和实现,就可以创建一个 logger 封装,并将相关的接口方法公开。

简单包封装

以下定义了五个方法:Info, Warn, Error 和 Fatal. 这些方法接口接收 2个参数,一个字符串和一个字段映射map.

type Logger interface {
    Debug(msg string, field map[string]interface{})
    Info(msg string, field map[string]interface{})
    Warn(msg string, field map[string]interface{})
    Error(msg string, field map[string]interface{})
    Fatal(msg string, field map[string]interface{})
}

接下来就是实现啦 Logger 方法,底层的实现主要是依赖使用 Logrus。首先需要创建一个 LLogger 结构体,该结构体包含 Logrus 实例。当然还需要一个 NewLLogger 方法来实例化一个 LLogger。

type LLogger struct {
    logger *logrus.Logger
    ctx    context.Context
}
func NewLLogger(ctx context.Context) *LLogger {
    logger := logrus.New()
    logger.Out = os.Stdout
    return &LLogger{logger: logger, ctx: ctx}
}
func (l *LLogger) Info(msg string, fields map[string]interface{}) {
    l.logger.WithFields(fields).Info(msg)
}
func (l *LLogger) Warn(msg string, fields map[string]interface{}) {
    l.logger.WithFields(fields).Warn(msg)
}
func (l *LLogger) Error(msg string, fields map[string]interface{}) {
    l.logger.WithFields(fields).Error(msg)
}
func (l *LLogger) Fatal(msg string, fields map[string]interface{}) {
    l.logger.WithFields(fields).Fatal(msg)
}

这样一个简单日志封装就完成了,使用时就可以直接使用。

func main() {
    ctx := ... // context 信息
    lg := NewLLogger(ctx)
    fields := map[string]interface{}{
        "userId":    "xiaoxiong",
        "ipAddress": "127.0.0.1",
    }
    lg.Info("这是测试信息", fields)
}

多日志库切换

当底层需要使用的是不同的日志库进行记录日志时,那就需要封装另外的日志,但是在实例化方法时可以增加一种日志类型参数,然后根据不同的类型实例化不同的日志。

比如使用了zap 包,那童养媳与奥实现接口的四个方法 :Info, Warn, Error and Fatal.

type ZapLog struct {
    logger *zap.Logger
    ctx    context.Context
}
func NewZapLog(ctx context.Context) *ZapLog {
    logger, _ := zap.NewProduction()
    return &ZapLog{logger: logger, ctx: ctx}
}
func (l *ZapLog) Info(msg string, fields map[string]interface{}) {
    l.logger.Info(msg, zap.Any("args", fields))
}
func (l *ZapLog) Warn(msg string, fields map[string]interface{}) {
    l.logger.Warn(msg, zap.Any("args", fields))
}
func (l *ZapLog) Error(msg string, fields map[string]interface{}) {
    l.logger.Error(msg, zap.Any("args", fields))
}
func (l *ZapLog) Fatal(msg string, fields map[string]interface{}) {
    l.logger.Fatal(msg, zap.Any("args", fields))
}

定义其他日志库的方法后就只需对这个两个日志库进行封装,根据不同的类型初始化出不同的日志,然后使用日志时候就使用相应的包进行处理。

type LoggerWrapper struct {
    logger Logger
}
func NewLoggerWrapper(loggerType string, ctx context.Context) *LoggerWrapper {
    var logger Logger
    switch loggerType {
    case "logrus":
        logger = NewLLogger(ctx)
    case "zap":
        logger = NewZapLog(ctx)
    default:
        logger = NewLLogger(ctx)
    }
    return &LoggerWrapper{logger: logger}
}

使用中间件记录公共信息

封装中增加了 Context 上下文的内容,主要是为了记录一些公共属性。就像经常在链路追踪时可需要请求ID ,请求IP 等相关的信息。但是日志实例都是在程序启动时进行初始化的,在每次的请求时可能请求ID或者IP 都是不一样,所以要记录这部分信息,可以使用中间件将上下文的信息添加到日志消息中。

标签: golang

热门推荐