支持按时间日期记录和限制文件数量的时间日期记录。

Signed-off-by: rick.chan <cy@haoan119.com>
This commit is contained in:
rick.chan 2025-04-21 21:33:09 +08:00
parent 7f15eb4e36
commit 9a07945f08
3 changed files with 190 additions and 57 deletions

View File

@ -15,8 +15,26 @@ func CreateLog(file string, level simplelog.Level) *simplelog.Log {
}
}
func main() {
log := CreateLog("./log/MS.log", simplelog.LevelInfo)
func test_timed(name string) {
log := new(simplelog.Log).InitTimed(name, simplelog.WhenMinute, 2, simplelog.LevelDebug)
n := time.Now()
for time.Since(n) < 10*time.Minute {
log.Debug("hello world")
time.Sleep(30 * time.Second)
}
}
func test_timedRotating(name string) {
log := new(simplelog.Log).InitTimedRotating(name, simplelog.WhenMinute, 2, 3, simplelog.LevelDebug)
n := time.Now()
for time.Since(n) < 10*time.Minute {
log.Debug("hello world")
time.Sleep(30 * time.Second)
}
}
func test_rotating(name string) {
log := CreateLog(name, simplelog.LevelInfo)
for i := 0; i < 10000000; i++ {
log.Trace("hello world")
log.Debug("hello world")
@ -27,3 +45,9 @@ func main() {
time.Sleep(8 * time.Millisecond)
}
}
func main() {
go test_rotating("./log/demo.log")
go test_timedRotating("./trlog/demo.log")
test_timed("./tlog/demo.log")
}

View File

@ -5,6 +5,8 @@ import (
"io"
"os"
"path"
"path/filepath"
"strings"
"time"
)
@ -53,12 +55,12 @@ type RotatingFileHandler struct {
fd *os.File
fileName string
maxBytes int
curBytes int
backupCount int
maxBytes int64
curBytes int64
backupCount uint
}
func (h *RotatingFileHandler) InitRotating(name string, maxBytes int, backupCount int) (*RotatingFileHandler, error) {
func (h *RotatingFileHandler) InitRotating(name string, maxBytes int64, backupCount uint) (*RotatingFileHandler, error) {
h.fileName = name
h.maxBytes = maxBytes
h.backupCount = backupCount
@ -74,7 +76,7 @@ func (h *RotatingFileHandler) InitRotating(name string, maxBytes int, backupCoun
h.fd.Close()
return nil, err
}
if f.Size() < int64(h.maxBytes) {
if f.Size() < h.maxBytes {
h.fd.Seek(0, io.SeekEnd)
} else {
h._doRollover()
@ -99,7 +101,7 @@ func (h *RotatingFileHandler) InitRotating(name string, maxBytes int, backupCoun
if err != nil {
return nil, err
}
h.curBytes = int(f.Size())
h.curBytes = f.Size()
return h, nil
}
@ -107,7 +109,7 @@ func (h *RotatingFileHandler) InitRotating(name string, maxBytes int, backupCoun
func (h *RotatingFileHandler) Write(p []byte) (n int, err error) {
h.doRollover()
n, err = h.fd.Write(p)
h.curBytes += n
h.curBytes += int64(n)
return
}
@ -132,7 +134,7 @@ func (h *RotatingFileHandler) doRollover() {
if h.maxBytes <= 0 {
return
} else if f.Size() < int64(h.maxBytes) {
h.curBytes = int(f.Size())
h.curBytes = f.Size()
return
}
@ -153,92 +155,156 @@ func (h *RotatingFileHandler) _doRollover() {
dfn := fmt.Sprintf("%s.1", h.fileName)
os.Rename(h.fileName, dfn)
h.fd, _ = os.OpenFile(h.fileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
h.fd, _ = os.OpenFile(h.fileName, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
h.curBytes = 0
} else {
h.fd.Close()
h.fd, _ = os.OpenFile(h.fileName, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
h.curBytes = 0
f, err := h.fd.Stat()
if err != nil {
return
}
h.curBytes = int(f.Size())
}
}
// TimedRotatingFileHandler writes log to a file,
// it will backup current and open a new one, with a period time you sepecified.
//
// refer: http://docs.python.org/2/library/logging.handlers.html.
// same like python TimedRotatingFileHandler.
type TimedRotatingFileHandler struct {
// TimedFileHandler writes log to a file.
type TimedFileHandler struct {
fd *os.File
baseName string
interval int64
dir string
name string
interval time.Duration
suffix string
rolloverAt int64
rolloverAt time.Time
}
type WhenInterval int
const (
WhenSecond = iota
WhenSecond WhenInterval = iota
WhenMinute
WhenHour
WhenDay
)
func (h *TimedRotatingFileHandler) InitTimedRotating(name string, when int8, interval int) (*TimedRotatingFileHandler, error) {
func (h *TimedFileHandler) InitTimed(name string, when WhenInterval, interval int64) (*TimedFileHandler, error) {
dir := path.Dir(name)
os.Mkdir(dir, 0777)
h.baseName = name
h.dir, h.name = filepath.Split(name)
switch when {
case WhenSecond:
h.interval = 1
h.suffix = "2006-01-02_15-04-05"
h.interval = 1 * time.Second
h.suffix = "2006-01-02-15-04-05"
case WhenMinute:
h.interval = 60
h.suffix = "2006-01-02_15-04"
h.interval = 1 * time.Minute
h.suffix = "2006-01-02-15-04"
case WhenHour:
h.interval = 3600
h.suffix = "2006-01-02_15"
h.interval = 1 * time.Hour
h.suffix = "2006-01-02-15"
case WhenDay:
h.interval = 3600 * 24
h.interval = 1 * time.Hour * 24
h.suffix = "2006-01-02"
default:
return nil, fmt.Errorf("invalid when_rotate: %d", when)
}
h.interval = h.interval * int64(interval)
h.interval = time.Duration(interval) * h.interval
h.rolloverAt = time.Now()
var err error
h.fd, err = os.OpenFile(h.baseName, os.O_CREATE|os.O_WRONLY, 0666)
h.fd, err = os.OpenFile(filepath.Join(h.dir, h.rolloverAt.Format(h.suffix)+"_"+h.name), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
return nil, err
}
fInfo, _ := h.fd.Stat()
h.rolloverAt = fInfo.ModTime().Unix() + h.interval
return h, nil
}
func (h *TimedRotatingFileHandler) doRollover() {
//refer http://hg.python.org/cpython/file/2.7/Lib/logging/handlers.py
now := time.Now()
if h.rolloverAt <= now.Unix() {
fName := h.baseName + now.Format(h.suffix)
func (h *TimedFileHandler) doRollover() {
if time.Since(h.rolloverAt) > time.Duration(h.interval) {
h.fd.Close()
e := os.Rename(h.baseName, fName)
if e != nil {
panic(e)
}
h.fd, _ = os.OpenFile(h.baseName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
h.rolloverAt = time.Now().Unix() + h.interval
h.rolloverAt = time.Now()
h.fd, _ = os.OpenFile(filepath.Join(h.dir, h.rolloverAt.Format(h.suffix)+"_"+h.name), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
}
}
func (h *TimedFileHandler) Write(b []byte) (n int, err error) {
h.doRollover()
return h.fd.Write(b)
}
func (h *TimedFileHandler) Close() error {
return h.fd.Close()
}
type TimedRotatingFileHandler struct {
fd *os.File
dir string
name string
interval time.Duration
suffix string
rolloverAt time.Time
backupCount uint
}
func (h *TimedRotatingFileHandler) InitTimedRotating(name string, when WhenInterval, interval int64, backupCount uint) (*TimedRotatingFileHandler, error) {
h.backupCount = backupCount
dir := path.Dir(name)
os.Mkdir(dir, 0777)
h.dir, h.name = filepath.Split(name)
switch when {
case WhenSecond:
h.interval = 1 * time.Second
h.suffix = "2006-01-02-15-04-05"
case WhenMinute:
h.interval = 1 * time.Minute
h.suffix = "2006-01-02-15-04"
case WhenHour:
h.interval = 1 * time.Hour
h.suffix = "2006-01-02-15"
case WhenDay:
h.interval = 1 * time.Hour * 24
h.suffix = "2006-01-02"
default:
return nil, fmt.Errorf("invalid when_rotate: %d", when)
}
h.interval = time.Duration(interval) * h.interval
h.rolloverAt = time.Now()
var err error
h.fd, err = os.OpenFile(filepath.Join(h.dir, h.rolloverAt.Format(h.suffix)+"_"+h.name), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
return nil, err
}
h._doRollover()
return h, nil
}
func (h *TimedRotatingFileHandler) _doRollover() {
fs, err := h.ListDir(h.dir, h.suffix)
if err != nil {
return
}
if len(fs) > int(h.backupCount) {
for i := 0; i < len(fs)-int(h.backupCount); i++ {
os.Remove(fs[i])
}
}
}
func (h *TimedRotatingFileHandler) doRollover() {
if time.Since(h.rolloverAt) > time.Duration(h.interval) {
h.fd.Close()
h.rolloverAt = time.Now()
h.fd, _ = os.OpenFile(filepath.Join(h.dir, h.rolloverAt.Format(h.suffix)+"_"+h.name), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
}
h._doRollover()
}
func (h *TimedRotatingFileHandler) Write(b []byte) (n int, err error) {
h.doRollover()
return h.fd.Write(b)
@ -247,3 +313,37 @@ func (h *TimedRotatingFileHandler) Write(b []byte) (n int, err error) {
func (h *TimedRotatingFileHandler) Close() error {
return h.fd.Close()
}
func (h *TimedRotatingFileHandler) ListDir(dir, suffix string) (files []string, err error) {
files = []string{}
_dir, err := os.ReadDir(dir)
if err != nil {
return nil, err
}
for _, file := range _dir {
if file.IsDir() {
// 不需要递归读取子目录下的文件
continue
}
names := strings.Split(file.Name(), "_")
if len(names) != 2 {
// 文件名格式不对
continue
}
_, err := time.Parse(h.suffix, names[0])
if err != nil {
// 文件名格式不对
continue
}
if h.name != names[1] {
// 文件名格式不对
continue
}
files = append(files, filepath.Join(dir, file.Name()))
}
return files, nil
}

View File

@ -123,7 +123,7 @@ func (l *Log) InitFile(name string, level Level, flag int) *Log {
return l.Init(handler, level, flag)
}
func (l *Log) InitRotating(name string, maxBytes, backupCount int, level Level) *Log {
func (l *Log) InitRotating(name string, maxBytes int64, backupCount uint, level Level) *Log {
handler, e := new(RotatingFileHandler).InitRotating(name, maxBytes, backupCount)
if e != nil {
panic(e)
@ -132,8 +132,17 @@ func (l *Log) InitRotating(name string, maxBytes, backupCount int, level Level)
return l.Init(handler, level, Ltime|Lfile|Llevel)
}
func (l *Log) InitTimedRotating(name string, when int8, interval int, level Level) *Log {
handler, e := new(TimedRotatingFileHandler).InitTimedRotating(name, when, interval)
func (l *Log) InitTimed(name string, when WhenInterval, interval int64, level Level) *Log {
handler, e := new(TimedFileHandler).InitTimed(name, when, interval)
if e != nil {
panic(e)
}
return l.Init(handler, level, Ltime|Lfile|Llevel)
}
func (l *Log) InitTimedRotating(name string, when WhenInterval, interval int64, backupCount uint, level Level) *Log {
handler, e := new(TimedRotatingFileHandler).InitTimedRotating(name, when, interval, backupCount)
if e != nil {
panic(e)
}