1 Star 0 Fork 0

木桩 / utils.log.go

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
file.rotate.go 3.93 KB
一键复制 编辑 原始数据 按行查看 历史
qiaozhu@hypergryph.com 提交于 2022-07-10 14:20 . [DEV] move from old respo
package log
import (
"fmt"
"os"
"path/filepath"
"sync"
"sync/atomic"
"time"
)
var _ = Target(&TargetFileRotate{})
//RotateConfig 滚动配置
type RotateConfig struct {
Dir string
Prefix string
Ext string
//seconds
RotateDuring int64
//bytes
RotateSize int64
}
//TargetFileRotate file target with rotation.
type TargetFileRotate struct {
cfg *RotateConfig
levels []int
using int32
file *os.File
locker sync.Mutex
lastRotateTime int64
rotateDuring int64
stackSize int64
rotateSize int64
sizeIndex int64
}
//MakeTargetFileRotate make a TargetFileRotate instance.
func MakeTargetFileRotate(cfg *RotateConfig) (*TargetFileRotate, error) {
t := &TargetFileRotate{
cfg: cfg,
levels: append([]int{}, allLevels...),
using: 0,
file: nil,
lastRotateTime: 0,
rotateDuring: cfg.RotateDuring,
stackSize: 0,
rotateSize: cfg.RotateSize,
sizeIndex: 0,
}
now := time.Now()
today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
t.lastRotateTime = now.Unix() - ((now.Unix() - today.Unix()) % cfg.RotateDuring)
fn := t.genFileName(t.lastRotateTime)
f, oldSize, err := t.openFile(fn)
if nil != err {
return nil, fmt.Errorf("can't open or create log file [%s]", fn)
}
t.file = f
t.stackSize = oldSize
return t, nil
}
//Name implement for Target.Name()
func (t *TargetFileRotate) Name() string {
return "file." + t.cfg.Prefix
}
//IncrUsing implement for Target.IncrUsing()
func (t *TargetFileRotate) IncrUsing() {
atomic.AddInt32(&t.using, 1)
}
//IsIgnore implement for Target.IsIgnore()
func (t *TargetFileRotate) IsIgnore(l int) bool {
for _, s := range t.levels {
if s == l {
return false
}
}
return true
}
//SetLevels set levels this target should output.
func (t *TargetFileRotate) SetLevels(ls []int) {
t.levels = append([]int{}, ls...)
}
//Put implement for Target.Put()
func (t *TargetFileRotate) Put(msg string) {
t.locker.Lock()
defer t.locker.Unlock()
//try trigger file rotate, +1 for '\n'
t.tryRotateFile(int64(len(msg)) + 1)
//output log message to file
fmt.Fprintln(t.file, msg)
}
//Close close file
func (t *TargetFileRotate) Close() {
if atomic.AddInt32(&t.using, -1) != 0 {
return
}
t.locker.Lock()
defer t.locker.Unlock()
t.file.Sync()
t.file.Close()
}
//genFileName generate file name as current status
func (t *TargetFileRotate) genFileName(ts int64) string {
return fmt.Sprintf("%s.%s.%d.%s",
t.cfg.Prefix, time.Unix(ts, 0).Format("2006-01-02-150405"), t.sizeIndex, t.cfg.Ext)
}
//tryRotateFile try rotate log file, must in locked block
func (t *TargetFileRotate) tryRotateFile(delta int64) {
sizeFull := false
timeFull := false
//check size rotation
if t.stackSize+delta >= t.cfg.RotateSize {
sizeFull = true
}
//check time rotation
now := time.Now()
nowTs := now.Unix()
if t.lastRotateTime+t.cfg.RotateDuring <= nowTs {
timeFull = true
}
if !sizeFull && !timeFull {
t.stackSize += delta
return
}
if timeFull {
rn := (nowTs - t.lastRotateTime) / t.cfg.RotateDuring
t.lastRotateTime += t.cfg.RotateDuring * rn
t.sizeIndex = 0
} else if sizeFull {
t.sizeIndex++
}
t.stackSize = delta
//generate new file
fn := t.genFileName(t.lastRotateTime)
f, oldSize, err := t.openFile(fn)
if nil != err {
fmt.Printf("TargetFileRotate Error: can't open or create log file [%s]\n, %v", fn, err)
return
}
//change file
t.file.Sync()
t.file.Close()
t.file = f
t.stackSize += oldSize
}
//openFile open new log file
func (t *TargetFileRotate) openFile(fn string) (*os.File, int64, error) {
path := filepath.Join(t.cfg.Dir, fn)
f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
if nil != err {
return nil, 0, err
}
stat, err := f.Stat()
if nil != err {
return nil, 0, err
}
return f, stat.Size(), nil
}
Go
1
https://gitee.com/woodpile/utils.log.go.git
git@gitee.com:woodpile/utils.log.go.git
woodpile
utils.log.go
utils.log.go
v0.4.0

搜索帮助

53164aa7 5694891 3bd8fe86 5694891