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

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

内容简介:日志库基本上写完了,但是就完成了,还没有。目前来说,我们的文件写日志的方式采用同步方式,如果在大量日志写入的时候,同步写入的缺陷就暴露出来了。而且日志跟我们的业务逻辑也没有什么太大的关系,哪怕掉了几条也没什么影响,所以这里可以将同步写改为异步写。这里采用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,我们再来运行一下,日志正常写入,终端也正常打印。


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

查看所有标签

猜你喜欢:

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

HTML5与CSS3基础教程(第7版)

HTML5与CSS3基础教程(第7版)

[美] Elizabeth Castro、[美] Bruce Hyslop / 望以文 / 人民邮电出版社 / 2013-1 / 59.00元

代表下一代网页编写技术的HTML5,为网页提供布局和格式的CSS3,这两者构成了Web开发的基石,也是Web程序员和设计师必须熟练掌握的最基本技能。 本书是风靡全球的HTML和CSS最佳入门教程的最新版,上一版单单英文版的销量就超过100万册,被翻译为十多种语言,并长期雄踞亚马逊书店计算机图书排行榜榜首。 最新的第7版秉承前一版直观、透彻、全面、循序渐进的讲授特色,仍然采用独特的双栏图......一起来看看 《HTML5与CSS3基础教程(第7版)》 这本书的介绍吧!

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具

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

HSV CMYK互换工具