支持按时间日期记录和限制文件数量的时间日期记录。
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() {
|
func test_timed(name string) {
|
||||||
log := CreateLog("./log/MS.log", simplelog.LevelInfo)
|
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++ {
|
for i := 0; i < 10000000; i++ {
|
||||||
log.Trace("hello world")
|
log.Trace("hello world")
|
||||||
log.Debug("hello world")
|
log.Debug("hello world")
|
||||||
@ -27,3 +45,9 @@ func main() {
|
|||||||
time.Sleep(8 * time.Millisecond)
|
time.Sleep(8 * time.Millisecond)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
go test_rotating("./log/demo.log")
|
||||||
|
go test_timedRotating("./trlog/demo.log")
|
||||||
|
test_timed("./tlog/demo.log")
|
||||||
|
}
|
||||||
|
198
filehandler.go
198
filehandler.go
@ -5,6 +5,8 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -53,12 +55,12 @@ type RotatingFileHandler struct {
|
|||||||
fd *os.File
|
fd *os.File
|
||||||
|
|
||||||
fileName string
|
fileName string
|
||||||
maxBytes int
|
maxBytes int64
|
||||||
curBytes int
|
curBytes int64
|
||||||
backupCount int
|
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.fileName = name
|
||||||
h.maxBytes = maxBytes
|
h.maxBytes = maxBytes
|
||||||
h.backupCount = backupCount
|
h.backupCount = backupCount
|
||||||
@ -74,7 +76,7 @@ func (h *RotatingFileHandler) InitRotating(name string, maxBytes int, backupCoun
|
|||||||
h.fd.Close()
|
h.fd.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if f.Size() < int64(h.maxBytes) {
|
if f.Size() < h.maxBytes {
|
||||||
h.fd.Seek(0, io.SeekEnd)
|
h.fd.Seek(0, io.SeekEnd)
|
||||||
} else {
|
} else {
|
||||||
h._doRollover()
|
h._doRollover()
|
||||||
@ -99,7 +101,7 @@ func (h *RotatingFileHandler) InitRotating(name string, maxBytes int, backupCoun
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
h.curBytes = int(f.Size())
|
h.curBytes = f.Size()
|
||||||
|
|
||||||
return h, nil
|
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) {
|
func (h *RotatingFileHandler) Write(p []byte) (n int, err error) {
|
||||||
h.doRollover()
|
h.doRollover()
|
||||||
n, err = h.fd.Write(p)
|
n, err = h.fd.Write(p)
|
||||||
h.curBytes += n
|
h.curBytes += int64(n)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +134,7 @@ func (h *RotatingFileHandler) doRollover() {
|
|||||||
if h.maxBytes <= 0 {
|
if h.maxBytes <= 0 {
|
||||||
return
|
return
|
||||||
} else if f.Size() < int64(h.maxBytes) {
|
} else if f.Size() < int64(h.maxBytes) {
|
||||||
h.curBytes = int(f.Size())
|
h.curBytes = f.Size()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,90 +155,154 @@ func (h *RotatingFileHandler) _doRollover() {
|
|||||||
dfn := fmt.Sprintf("%s.1", h.fileName)
|
dfn := fmt.Sprintf("%s.1", h.fileName)
|
||||||
os.Rename(h.fileName, dfn)
|
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
|
h.curBytes = 0
|
||||||
f, err := h.fd.Stat()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
h.curBytes = int(f.Size())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TimedRotatingFileHandler writes log to a file,
|
// TimedFileHandler writes log to a file.
|
||||||
// it will backup current and open a new one, with a period time you sepecified.
|
type TimedFileHandler struct {
|
||||||
//
|
|
||||||
// refer: http://docs.python.org/2/library/logging.handlers.html.
|
|
||||||
// same like python TimedRotatingFileHandler.
|
|
||||||
type TimedRotatingFileHandler struct {
|
|
||||||
fd *os.File
|
fd *os.File
|
||||||
|
|
||||||
baseName string
|
dir string
|
||||||
interval int64
|
name string
|
||||||
|
interval time.Duration
|
||||||
suffix string
|
suffix string
|
||||||
rolloverAt int64
|
rolloverAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type WhenInterval int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
WhenSecond = iota
|
WhenSecond WhenInterval = iota
|
||||||
WhenMinute
|
WhenMinute
|
||||||
WhenHour
|
WhenHour
|
||||||
WhenDay
|
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)
|
dir := path.Dir(name)
|
||||||
os.Mkdir(dir, 0777)
|
os.Mkdir(dir, 0777)
|
||||||
|
|
||||||
h.baseName = name
|
h.dir, h.name = filepath.Split(name)
|
||||||
|
|
||||||
switch when {
|
switch when {
|
||||||
case WhenSecond:
|
case WhenSecond:
|
||||||
h.interval = 1
|
h.interval = 1 * time.Second
|
||||||
h.suffix = "2006-01-02_15-04-05"
|
h.suffix = "2006-01-02-15-04-05"
|
||||||
case WhenMinute:
|
case WhenMinute:
|
||||||
h.interval = 60
|
h.interval = 1 * time.Minute
|
||||||
h.suffix = "2006-01-02_15-04"
|
h.suffix = "2006-01-02-15-04"
|
||||||
case WhenHour:
|
case WhenHour:
|
||||||
h.interval = 3600
|
h.interval = 1 * time.Hour
|
||||||
h.suffix = "2006-01-02_15"
|
h.suffix = "2006-01-02-15"
|
||||||
case WhenDay:
|
case WhenDay:
|
||||||
h.interval = 3600 * 24
|
h.interval = 1 * time.Hour * 24
|
||||||
h.suffix = "2006-01-02"
|
h.suffix = "2006-01-02"
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("invalid when_rotate: %d", when)
|
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
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
fInfo, _ := h.fd.Stat()
|
|
||||||
h.rolloverAt = fInfo.ModTime().Unix() + h.interval
|
|
||||||
|
|
||||||
return h, nil
|
return h, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *TimedRotatingFileHandler) doRollover() {
|
func (h *TimedFileHandler) doRollover() {
|
||||||
//refer http://hg.python.org/cpython/file/2.7/Lib/logging/handlers.py
|
if time.Since(h.rolloverAt) > time.Duration(h.interval) {
|
||||||
now := time.Now()
|
|
||||||
|
|
||||||
if h.rolloverAt <= now.Unix() {
|
|
||||||
fName := h.baseName + now.Format(h.suffix)
|
|
||||||
h.fd.Close()
|
h.fd.Close()
|
||||||
e := os.Rename(h.baseName, fName)
|
h.rolloverAt = time.Now()
|
||||||
if e != nil {
|
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)
|
||||||
panic(e)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.fd, _ = os.OpenFile(h.baseName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
h.interval = time.Duration(interval) * h.interval
|
||||||
|
|
||||||
h.rolloverAt = time.Now().Unix() + 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) {
|
func (h *TimedRotatingFileHandler) Write(b []byte) (n int, err error) {
|
||||||
@ -247,3 +313,37 @@ func (h *TimedRotatingFileHandler) Write(b []byte) (n int, err error) {
|
|||||||
func (h *TimedRotatingFileHandler) Close() error {
|
func (h *TimedRotatingFileHandler) Close() error {
|
||||||
return h.fd.Close()
|
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)
|
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)
|
handler, e := new(RotatingFileHandler).InitRotating(name, maxBytes, backupCount)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
panic(e)
|
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)
|
return l.Init(handler, level, Ltime|Lfile|Llevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Log) InitTimedRotating(name string, when int8, interval int, level Level) *Log {
|
func (l *Log) InitTimed(name string, when WhenInterval, interval int64, level Level) *Log {
|
||||||
handler, e := new(TimedRotatingFileHandler).InitTimedRotating(name, when, interval)
|
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 {
|
if e != nil {
|
||||||
panic(e)
|
panic(e)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user