1. 程式人生 > >go開發屬於自己的日誌庫-日誌切分

go開發屬於自己的日誌庫-日誌切分

在檔案日誌中,還存在一個問題,就是在日誌寫檔案時間長了以後,日誌檔案肯定會非常大,內容非常多,這個時候如果我們需要去定位一個錯誤,會耗費很長的時間。所以我們需要將日誌檔案進行分割,分割檔案我們可以採用一天分割一次,或者檔案大小達到一個體積進行分割。
log_const.go

const (
	LogSplitTypeHour = iota
	LogSplitTypeSize
)

file.go


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_log

我們日誌庫就已經開發完成了,當然,和目前主流的日誌庫比還顯得簡漏。不過我們的目的不在於寫的多好,而在於寫的過程。也歡迎各位真正裡面的錯誤,謝謝。