go开发属于本身的日志库-日志切分

在文件日志中,还存在一个问题,就是在日志写文件时间长了之后,日志文件确定会很是大,内容很是多,这个时候若是咱们须要去定位一个错误,会耗费很长的时间。因此咱们须要将日志文件进行分割,分割文件咱们能够采用一天分割一次,或者文件大小达到一个体积进行分割。 log_const.gogit

const (
	LogSplitTypeHour = iota
	LogSplitTypeSize
)
复制代码

file.gogithub

type FileLog struct {
	logPath       string
	logName       string
	file          *os.File
	warnFile      *os.File
	logDataChan   chan *LogData
	logSplitType  int  //分割类型
	logSplitSize  int64 //分割体积
	lastSplitHour int //分割时间
}


func NewFileLog(config map[string]string) (logFile Log, err error) {
	...

	var logSplitType = LogSplitTypeSize
	var logSplitSize int64

	splitType, ok := config["log_split_type"]
	if !ok {
		splitType = "hour"
	} else {
		if splitType == "size" {
			splitSize, ok := config["log_split_size"]
			if !ok {
				splitSize = "104857600" //100M 以文字来说不少了
			}

			logSplitSize, err = strconv.ParseInt(splitSize, 10, 64)
			if err != nil {
				logSplitSize = 104857600
			}

			logSplitType = LogSplitTypeSize
		} else {
			logSplitType = LogSplitTypeHour
		}
	}

	logFile = &FileLog{
		logPath:       logPath,
		logName:       logName,
		logDataChan:   make(chan *LogData, chanSize),
		logSplitType:  logSplitType,
		logSplitSize:  logSplitSize,
		lastSplitHour: time.Now().Hour(),
	}

	logFile.Init()
	return
}

func (f *FileLog) writeLogBackGround() {
	for logData := range f.logDataChan {
		var file = f.file
		if logData.IsWarn {
			file = f.warnFile
		}

		f.checkSplitFile(logData.IsWarn) // 检查文件分割类型

		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) checkSplitFile(isWarn bool) {
	if f.logSplitType == LogSplitTypeHour {
		f.splitHour(isWarn)
		return
	}
	f.splitSize(isWarn)
}

// 根据文件大小来分割
func (f *FileLog) splitSize(isWarn bool) {
	file := f.file
	if isWarn {
		file = f.warnFile
	}

	fileInfo, err := file.Stat() // 能够获得文件的参数
	if err != nil {
		return
	}

	fileSize := fileInfo.Size()
	if fileSize <= f.logSplitSize {
		return
	}

	var backupFileName string
	var fileName string

	now := time.Now()

	if isWarn {
		backupFileName = fmt.Sprintf("%s/%s.log.wf_%s", f.logPath, f.logName, now.Format("20060102150405"))
		fileName = fmt.Sprintf("%s/%s.log.wf", f.logPath, f.logName)
	} else {
		backupFileName = fmt.Sprintf("%s/%s.log_%s", f.logPath, f.logName, now.Format("20060102150405"))
		fileName = fmt.Sprintf("%s/%s.log", f.logPath, f.logName)
	}

	file.Close()
	os.Rename(fileName, backupFileName) // 重命名

	file, err = os.OpenFile(fileName, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0755)
	if err != nil {
		return
	}

	if isWarn {
		f.warnFile = file
	} else {
		f.file = file
	}
}

// 根据时间来进行分割
func (f *FileLog) splitHour(isWarn bool) {

	now := time.Now()
	hour := now.Hour()

	if hour == f.lastSplitHour {
		return
	}

	f.lastSplitHour = hour

	var backupFileName string
	var fileName string

	if isWarn {
		backupFileName = fmt.Sprintf("%s/%s.log.wf_%s", f.logPath, f.logName, now.Format("20060102150405"))
		fileName = fmt.Sprintf("%s/%s.log.wf", f.logPath, f.logName)
	} else {
		backupFileName = fmt.Sprintf("%s/%s.log_%s", f.logPath, f.logName, now.Format("20060102150405"))
		fileName = fmt.Sprintf("%s/%s.log", f.logPath, f.logName)
	}

	file := f.file
	if isWarn {
		file = f.warnFile
	}
	file.Close()
	os.Rename(fileName, backupFileName)

	file, err := os.OpenFile(fileName, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0755)
	if err != nil {
		return
	}

	if isWarn {
		f.warnFile = file
	} else {
		f.file = file
	}
}

复制代码

咱们来测试一下:测试

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 能够不用
	config["log_split_type"] = "size"
	config["log_split_size"] = "104857600" // 100MB
   err := InitLog("file", config)
	 if err != nil {
		 return
	 }
	 
	 for {
		log.Warn("%s", "123")
	}
}
复制代码

等一段时间看看是否进行分割了。 这里是源文件hm_logui

咱们日志库就已经开发完成了,固然,和目前主流的日志库比还显得简漏。不过咱们的目的不在于写的多好,而在于写的过程。也欢迎各位真正里面的错误,谢谢。spa

相关文章
相关标签/搜索