280 lines
5.9 KiB
Go
280 lines
5.9 KiB
Go
package lxlog
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"runtime"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
// 异步写日志
|
|
|
|
var MyLog *FileLog
|
|
|
|
const (
|
|
LogSplitTypeHour = iota
|
|
LogSplitTypeSize
|
|
logPath = "myLog"
|
|
logName = "myLog"
|
|
chanSize = 5000
|
|
)
|
|
|
|
type FileLog struct {
|
|
logPath string
|
|
logName string
|
|
file *os.File //普通日志
|
|
warnFile *os.File //错误日志 级别低
|
|
logDataChan chan *LogData
|
|
logSplitType int //分割类型
|
|
logSplitSize int64 //分割体积
|
|
lastSplitHour int //分割时间
|
|
}
|
|
|
|
type LogData struct {
|
|
Message string
|
|
TimeStr string
|
|
LevelStr string
|
|
IsWarn bool
|
|
File string
|
|
}
|
|
|
|
// _ = tools.InitLog()
|
|
func InitLog() (log *FileLog) {
|
|
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"] = strconv.Itoa(1024 * 1024 * 1024) // 1g
|
|
log, err := NewFileLog(config)
|
|
if err != nil {
|
|
panic("init log err")
|
|
}
|
|
MyLog = log
|
|
return log
|
|
}
|
|
|
|
func NewFileLog(config map[string]string) (logFile *FileLog, 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
|
|
}
|
|
}
|
|
//打开日志文件
|
|
exist, err := PathIsExists(logPath)
|
|
if err != nil {
|
|
fmt.Printf("get dir error![%v]\n", err)
|
|
return
|
|
}
|
|
if !exist {
|
|
err = os.Mkdir(logPath, os.ModePerm)
|
|
if err != nil {
|
|
fmt.Printf("mkdir failed![%v]\n", err)
|
|
return
|
|
} else {
|
|
fmt.Printf("mkdir success!\n")
|
|
}
|
|
}
|
|
//正常日志
|
|
fileName := fmt.Sprintf("%s/%s.log", logPath, logName)
|
|
file, err := os.OpenFile(fileName, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0755)
|
|
//错误日志
|
|
fileNameWarn := fmt.Sprintf("%s/%s.log.err", logPath, logName)
|
|
fileWarn, err := os.OpenFile(fileNameWarn, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0755)
|
|
if err != nil {
|
|
return
|
|
}
|
|
logFile = &FileLog{
|
|
logPath: logPath,
|
|
logName: logName,
|
|
logDataChan: make(chan *LogData, chanSize),
|
|
file: file,
|
|
warnFile: fileWarn,
|
|
logSplitType: logSplitType,
|
|
logSplitSize: logSplitSize,
|
|
lastSplitHour: time.Now().Hour(),
|
|
}
|
|
go logFile.writeLogBackGround()
|
|
return
|
|
}
|
|
|
|
// 判断文件夹是否存在
|
|
func PathIsExists(path string) (bool, error) {
|
|
_, err := os.Stat(path)
|
|
if err == nil {
|
|
return true, nil
|
|
}
|
|
if os.IsNotExist(err) {
|
|
return false, nil
|
|
}
|
|
return false, err
|
|
}
|
|
|
|
func (f *FileLog) Info(message string) {
|
|
_, file, line, _ := runtime.Caller(1)
|
|
fi := file + ":" + strconv.Itoa(line)
|
|
f.print(message, "info", fi)
|
|
}
|
|
func (f *FileLog) Debug(message string) {
|
|
_, file, line, _ := runtime.Caller(1)
|
|
fi := file + ":" + strconv.Itoa(line)
|
|
f.print(message, "debug", fi)
|
|
}
|
|
func (f *FileLog) Warn(message string) {
|
|
_, file, line, _ := runtime.Caller(1)
|
|
fi := file + ":" + strconv.Itoa(line)
|
|
f.print(message, "warn", fi)
|
|
}
|
|
func (f *FileLog) Error(message string) {
|
|
_, file, line, _ := runtime.Caller(1)
|
|
fi := file + ":" + strconv.Itoa(line)
|
|
f.print(message, "error", fi)
|
|
}
|
|
|
|
func (f *FileLog) print(message, Type string, file string) {
|
|
isWarn := false
|
|
if Type == "error" {
|
|
isWarn = true
|
|
}
|
|
msg := &LogData{
|
|
Message: message,
|
|
TimeStr: time.Now().Format("2006-01-02 15:04:05"),
|
|
LevelStr: Type,
|
|
IsWarn: isWarn,
|
|
File: file,
|
|
}
|
|
// 怕chan满了插不进去
|
|
select {
|
|
case f.logDataChan <- msg:
|
|
default:
|
|
|
|
}
|
|
}
|
|
|
|
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\n", logData.TimeStr, logData.LevelStr, logData.Message, logData.File)
|
|
}
|
|
}
|
|
|
|
func (f *FileLog) checkSplitFile(isWarn bool) {
|
|
if f.logSplitType == LogSplitTypeHour {
|
|
f.splitHour(isWarn)
|
|
return
|
|
}
|
|
f.splitSize(isWarn)
|
|
}
|
|
|
|
// 根据时间切割
|
|
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.err_%s", f.logPath, f.logName, now.Format("20060102150405"))
|
|
fileName = fmt.Sprintf("%s/%s.log.err", 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 (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.err_%s", f.logPath, f.logName, now.Format("20060102150405"))
|
|
fileName = fmt.Sprintf("%s/%s.log.err", 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
|
|
}
|
|
}
|