logurs
logurs 是个很受欢迎的日志库,github上的star 8000+ 。功能也很强大。但是却没有日志文件管理的功能。颇感遗憾。自己就想简单的封装一下,看能不能实现对日志文件管理的功能。
思路
思路如下。
1. 实现io.Writer 接口。 里面实现把数据写入到文件和对文件大小的计算。
2. 把logurs的输出重定向到1实现的io.Writer中
实现io.Writer
io.Writer 只有一个方法
type interface Writer{ Write(p []byte) (n int, err error }
很简单。 下面实现这个接口
type logFileWriter struct {
file *os.File
size int64
}
func (p *logFileWriter) Write(data []byte) (n int, err error) {
if p == nil {
return 0, errors.New("logFileWriter is nil")
}
if p.file == nil {
return 0, errors.New("file not opened")
}
n, e := p.file.Write(data)
p.size += int64(n)
//文件最大 64 K byte
if p.size > 1024*64 {
p.file.Close()
fmt.Println("log file full")
p.file, _ = os.OpenFile("./mylog"+strconv.FormatInt(time.Now().Unix(), 10), os.O_WRONLY|os.O_APPEND|os.O_CREATE|os.O_SYNC, 0600)
p.size = 0
}
return n, e
}
实现logrus的输出重定向
logrus 提供了相应的接口,直接调用
log.SetOutput(&fileWriter)
完整代码
package main
import (
"errors"
"fmt"
_ "github.com/go-sql-driver/mysql"
log "github.com/sirupsen/logrus"
"os"
"strconv"
"sync"
"time"
)
type logFileWriter struct {
file *os.File
//write count
size int64
}
var wg sync.WaitGroup
func main() {
//log.SetFormatter(&log.JSONFormatter{})
file, err := os.OpenFile("./mylog"+strconv.FormatInt(time.Now().Unix(), 10), os.O_WRONLY|os.O_APPEND|os.O_CREATE|os.O_SYNC, 0600)
if err != nil {
log.Fatal("log init failed")
}
info, err := file.Stat()
if err != nil {
log.Fatal(err)
}
fileWriter := logFileWriter{file, info.Size()}
log.SetOutput(&fileWriter)
log.Info("start.....")
for i := 0; i < 100; i++ {
wg.Add(1)
go logTest(i)
}
log.Warn("waitting...")
wg.Wait()
}
func (p *logFileWriter) Write(data []byte) (n int, err error) {
if p == nil {
return 0, errors.New("logFileWriter is nil")
}
if p.file == nil {
return 0, errors.New("file not opened")
}
n, e := p.file.Write(data)
p.size += int64(n)
//文件最大 64K byte
if p.size > 1024*64 {
p.file.Close()
fmt.Println("log file full")
p.file, _ = os.OpenFile("./mylog"+strconv.FormatInt(time.Now().Unix(), 10), os.O_WRONLY|os.O_APPEND|os.O_CREATE|os.O_SYNC, 0600)
p.size = 0
}
return n, e
}
func logTest(id int) {
for i := 0; i < 100; i++ {
log.Info("Thread:", id, " value:", i)
time.Sleep(10 * time.Millisecond)
}
wg.Done()
}
测试结果
文件大了一点点,但是日志对于这种差别并不敏感,所以没有关系了
关于日志回滚的思路
logrus 虽然强大,但是还是没有实现日志的回滚功能。 想必仔细看的朋友也可以想到,使用以上类似的思路也是可以实现日志的回滚的:通过实现io.Writer 接口,里面添加必要的对日志文件管理的功能,重定向输出到自定义的io.Writer接口。其实相比自动分文件,日志回滚就是加多了对日志文件的管理,就可以达到了。