在文件日誌中,還存在一個問題,就是在日誌寫文件時間長了之後,日誌文件確定會很是大,內容很是多,這個時候若是咱們須要去定位一個錯誤,會耗費很長的時間。因此咱們須要將日誌文件進行分割,分割文件咱們能夠採用一天分割一次,或者文件大小達到一個體積進行分割。 log_const.go
git
const (
LogSplitTypeHour = iota
LogSplitTypeSize
)
複製代碼
file.go
github
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