go开发属于自己的日志库-日志库优化

栏目: Go · 发布时间: 7年前

内容简介:日志库基本上写完了,但是就完成了,还没有。目前来说,我们的文件写日志的方式采用同步方式,如果在大量日志写入的时候,同步写入的缺陷就暴露出来了。而且日志跟我们的业务逻辑也没有什么太大的关系,哪怕掉了几条也没什么影响,所以这里可以将同步写改为异步写。这里采用go的channel进行异步写日志。首先,我们定义一个channel的结构体用来传递日志数据,在

日志库基本上写完了,但是就完成了,还没有。目前来说,我们的文件写日志的方式采用同步方式,如果在大量日志写入的时候,同步写入的缺陷就暴露出来了。而且日志跟我们的业务逻辑也没有什么太大的关系,哪怕掉了几条也没什么影响,所以这里可以将同步写改为异步写。

这里采用 go 的channel进行异步写日志。

  1. 在业务调用写日志时,将日志数据写入channel中
  2. 起一个后台线程不断的从channel中取日志,然后写入到文件中。

首先,我们定义一个channel的结构体用来传递日志数据,在 util.go 中新建一个结构体:

type LogData struct {
	Message  string
	TimeStr  string
	LevelStr string
	FileName string
	FuncName string
	LineNo   int
	IsWarn   bool //是否写入错误日志文件
}
复制代码

有些这个数据后,我们就可以定义一个channel来进行操作。在 file.go 中增加一个channel:

type FileLog struct {
	logPath       string
	logName       string
	file          *os.File
	warnFile      *os.File
	logDataChan   chan *LogData
}

func NewFileLog(config map[string]string) (logFile Log, err error) {
	...
	
	logChanSize, ok := config["log_chan_size"]
	if !ok {
		logChanSize = "50000"
	}
	
	chanSize, e := strconv.Atoi(logChanSize) // string to int
	if e != nil {
		chanSize = 50000 // channel最大容量
	}

	logFile = &FileLog{
		logPath:       logPath,
		logName:       logName,
		logDataChan:   make(chan *LogData, chanSize),// 初始化channel
	}

	logFile.Init()
	return
}

func (f *FileLog) Init() {
	...

	go f.writeLogBackGround() // go 关键字启动一个线程
}

func (f *FileLog) writeLogBackGround() {
	for logData := range f.logDataChan {
		var file = f.file
		// 切换日志文件
		if logData.IsWarn {
			file = f.warnFile
		}

		fmt.Fprintf(file, "%s %s [%s/%s:%d] %s\n", logData.TimeStr, logData.LevelStr,
			logData.FileName, logData.FuncName, logData.LineNo, logData.Message)
	}
}

func (f *FileLog) Debug(format string, args ...interface{}) {
	logData := writeLog(DebugLevel, format, args)
	select {
	case f.logDataChan <- logData: // 将logData放入f.logDataChan中
	default:
	}
}
...
func (f *FileLog) Info(format string, args ...interface{}) {
	logData := writeLog(InfoLevel, format, args)
	select {
	case f.logDataChan <- logData:
	default:
	}
}
...

复制代码

将之前的writeLog改进一下.

func writeLog(level int, format string, args ...interface{}) *LogData {
	now := time.Now()
	nowStr := now.Format("2006-01-02 15:04:05.999")
	levelStr := LogLevelString(level)
	fileName, funcName, lineNo := GetLineInfo()
	fileName = path.Base(fileName)
	funcName = path.Base(funcName)
	msg := fmt.Sprintf(format, args...)
  isWarn := level >= WarnLevel && level <= FatalLevel
	return &LogData{
		Message:  msg,
		TimeStr:  nowStr,
		LevelStr: levelStr,
		FileName: fileName,
		FuncName: funcName,
		LineNo:   lineNo,
		IsWarn:   isWarn,
	}
}
复制代码

这样就把同步改为了异步,我们日志库又健壮了一些。 由于writeLog有改动,所以还需要修改一下 console.go 的内容。

func (c *ConsoleLog) Debug(format string, args ...interface{}) {
	logData := MsgInfo(DebugLevel, format, args)
	fmt.Fprintf(os.Stdout, "%s %s [%s/%s:%d] %s\n", logData.TimeStr, logData.LevelStr, logData.FileName, logData.FuncName, logData.LineNo, logData.Message)
}
...
func (c *ConsoleLog) Error(format string, args ...interface{}) {
	logData := MsgInfo(ErrorLevel, format, args)
	fmt.Fprintf(os.Stdout, "%s %s [%s/%s:%d] %s\n", logData.TimeStr, logData.LevelStr, logData.FileName, logData.FuncName, logData.LineNo, logData.Message)
}
...
复制代码

虽然我们修改了那么多,但是在使用日志库的时候没有什么不同,只是我们的日志库更完善了一下。

func initLog(logPath, logName string) {
   //log := hm_log.NewFileLog(logPath, logName)
	config := make(map[string]string, 8)
	config["log_path"] = "."
	config["log_name"] = "server"
	config["log_chan_size"] = "50000" //chan size 可以不用
   err := InitLog("file", config)
	 if err != nil {
		 return
	 }
}

复制代码

OK,我们再来运行一下,日志正常写入,终端也正常打印。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Algorithms for Image Processing and Computer Vision

Algorithms for Image Processing and Computer Vision

Parker, J. R. / 2010-12 / 687.00元

A cookbook of algorithms for common image processing applications Thanks to advances in computer hardware and software, algorithms have been developed that support sophisticated image processing with......一起来看看 《Algorithms for Image Processing and Computer Vision》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具