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