支持按时间日期记录和限制文件数量的时间日期记录。
Signed-off-by: rick.chan <cy@haoan119.com>
This commit is contained in:
parent
7f15eb4e36
commit
9a07945f08
28
demo/main.go
28
demo/main.go
@ -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")
|
||||
}
|
||||
|
204
filehandler.go
204
filehandler.go
@ -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
|
||||
}
|
||||
|
15
simplelog.go
15
simplelog.go
@ -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)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user