go-zero的日志源码学习

go-zero的日志处理学习

开始

  1. 读取配置文件

    // MustSetup sets up logging with given config c. It exits on error.
    func MustSetup(c LogConf) {
    	Must(SetUp(c))
    }
    

使用SetUp 来进行判断那种类型的日志记录方式:

  • console
  • volume ——映射,用于 k8s 服务启动
  • file —— 裸机运行,记录日志为文件

使用 Must 进行包裹 error 进行error 判断及逻辑处理

避免了 if error != nil 在方法里面。

  1. (看过一篇文件,写到过,这个种写法,但是我不知道叫什么,有知道的可以告诉我一声)读取配置

    // 定义  
    
    logOptions struct {
    		gzipEnabled           bool
    		logStackCooldownMills int
    		keepDays              int
    	}
    
    	// LogOption defines the method to customize the logging.
    	LogOption func(options *logOptions)
    
    	var opts []LogOption     1
    	var err error
    
    	if len(c.Path) == 0 {
    		return ErrLogPathNotSet
    	}
    
    	opts = append(opts, WithCooldownMillis(c.StackCooldownMillis))  2
    	if c.Compress {
    		opts = append(opts, WithGzip())  3
    	}
    	if c.KeepDays > 0 {
    		opts = append(opts, WithKeepDays(c.KeepDays))  4
    	}
    
    func handleOptions(opts []LogOption) {   5
    	for _, opt := range opts {
    		opt(&options)
    	}
    }
    

    获取文件的配置的优雅写法:

    1. 通过定义发现LogOptions 是一个结构体
    2. 而 LogOption 是类型定义,那个func函数
    3. 增加配置,写到数组里面
    4. 通过方法handleOptions 方法,遍历数组,使用地址 options 覆盖源配置的默认配置。
setupWithConsole 控制台启动
once.Do(func() {
		atomic.StoreUint32(&initialized, 1)
		writeConsole = true
		setupLogLevel(c)

		infoLog = newLogWriter(log.New(os.Stdout, "", flags))
		errorLog = newLogWriter(log.New(os.Stderr, "", flags))
		severeLog = newLogWriter(log.New(os.Stderr, "", flags))
		slowLog = newLogWriter(log.New(os.Stderr, "", flags))
		stackLog = newLessWriter(errorLog, options.logStackCooldownMills)
		statLog = infoLog
	})

全局唯一实例化,使用 once.Do进行方法初始化。

并且通过atomic 存储初始化 initialized 状态

看到go-zero 文档,他将 日志 分为 5 种,分别为 info ,error, servere , slow, stack

而上述的newLogWriter 是 使用log.Logger 进行 包装构造的。

func newLogWriter(logger *log.Logger) logWriter {
	return logWriter{
		logger: logger,
	}
}
setupWithFiles
var opts []LogOption
	var err error

	if len(c.Path) == 0 {
		return ErrLogPathNotSet
	}

	opts = append(opts, WithCooldownMillis(c.StackCooldownMillis))
	if c.Compress {
		opts = append(opts, WithGzip())
	}
	if c.KeepDays > 0 {
		opts = append(opts, WithKeepDays(c.KeepDays))
	}
	// 上面将进行配置读取
	accessFile := path.Join(c.Path, accessFilename)
	errorFile := path.Join(c.Path, errorFilename)
	severeFile := path.Join(c.Path, severeFilename)
	slowFile := path.Join(c.Path, slowFilename)
	statFile := path.Join(c.Path, statFilename)
    // log文件 写入的文件名称
    // 全局执行一次的方法
	once.Do(func() {
		atomic.StoreUint32(&initialized, 1)
		handleOptions(opts)
		setupLogLevel(c)

		if infoLog, err = createOutput(accessFile); err != nil {
			return
		}

		if errorLog, err = createOutput(errorFile); err != nil {
			return
		}

		if severeLog, err = createOutput(severeFile); err != nil {
			return
		}

		if slowLog, err = createOutput(slowFile); err != nil {
			return
		}

		if statLog, err = createOutput(statFile); err != nil {
			return
		}

		stackLog = newLessWriter(errorLog, options.logStackCooldownMills)
	})

	return err
setupWithVolume 在 setupWithFiles 的保存文件的基础上,增加了 主机名称和服务名称
func setupWithVolume(c LogConf) error {
	if len(c.ServiceName) == 0 {
		return ErrLogServiceNameNotSet
	}

	c.Path = path.Join(c.Path, c.ServiceName, sysx.Hostname())
	return setupWithFiles(c)
}

是在写文件的基础上,增加了 主机名称和服务名称

记录

Error 日志打印
// Error writes v into error log.
func Error(v ...interface{}) {
	ErrorCaller(1, v...)
}

// ErrorCaller writes v with context into error log.
func ErrorCaller(callDepth int, v ...interface{}) {
	errorTextSync(fmt.Sprint(v...), callDepth+callerInnerDepth)
}

// ErrorCallerf writes v with context in format into error log.
func ErrorCallerf(callDepth int, format string, v ...interface{}) {
	errorTextSync(fmt.Sprintf(format, v...), callDepth+callerInnerDepth)
}

// Errorf writes v with format into error log.
func Errorf(format string, v ...interface{}) {
	ErrorCallerf(1, format, v...)
}

// ErrorStack writes v along with call stack into error log.
func ErrorStack(v ...interface{}) {
	// there is newline in stack string
	stackSync(fmt.Sprint(v...))
}

// ErrorStackf writes v along with call stack in format into error log.
func ErrorStackf(format string, v ...interface{}) {
	// there is newline in stack string
	stackSync(fmt.Sprintf(format, v...))
}

// Errorv writes v into error log with json content.
// No call stack attached, because not elegant to pack the messages.
func Errorv(v interface{}) {
	errorAnySync(v)
}

首先是继承接口

上述覆写了多种方法,用于使用,函数名称描述函数用途,

info 和 servere 同理

停止

func Close() error {
	if writeConsole {
		return nil
	}

	if atomic.LoadUint32(&initialized) == 0 {
		return ErrLogNotInitialized
	}

	atomic.StoreUint32(&initialized, 0)

	if infoLog != nil {
		if err := infoLog.Close(); err != nil {
			return err
		}
	}

	if errorLog != nil {
		if err := errorLog.Close(); err != nil {
			return err
		}
	}

	if severeLog != nil {
		if err := severeLog.Close(); err != nil {
			return err
		}
	}

	if slowLog != nil {
		if err := slowLog.Close(); err != nil {
			return err
		}
	}

	if statLog != nil {
		if err := statLog.Close(); err != nil {
			return err
		}
	}

	return nil
}

全局使用原子化变量进行状态判断,

停止,只需要关闭文件写入就可以了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值