diff --git a/log/handler.go b/log/handler.go index 87b835a..af4acb4 100644 --- a/log/handler.go +++ b/log/handler.go @@ -32,6 +32,21 @@ func (h *StreamHandler) Close() error { return nil } +type NullHandler struct { +} + +func NewNullHandler() (*NullHandler, error) { + return new(NullHandler), nil +} + +func (h *NullHandler) Write(b []byte) (n int, err error) { + return len(b), nil +} + +func (h *NullHandler) Close() { + +} + type FileHandler struct { fd *os.File } @@ -57,6 +72,71 @@ func (h *FileHandler) Close() error { return h.fd.Close() } +type RotatingFileHandler struct { + fd *os.File + + fileName string + maxBytes int + backupCount int +} + +func NewRotatingFileHandler(fileName string, maxBytes int, backupCount int) (*RotatingFileHandler, error) { + h := new(RotatingFileHandler) + + h.fileName = fileName + h.maxBytes = maxBytes + h.backupCount = backupCount + + var err error + h.fd, err = os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) + if err != nil { + return nil, err + } + + return h, nil +} + +func (h *RotatingFileHandler) Write(p []byte) (n int, err error) { + h.doRollover() + return h.fd.Write(p) +} + +func (h *RotatingFileHandler) Close() error { + if h.fd != nil { + return h.fd.Close() + } + return nil +} + +func (h *RotatingFileHandler) doRollover() { + f, err := h.fd.Stat() + if err != nil { + return + } + + if h.maxBytes <= 0 { + return + } else if f.Size() < int64(h.maxBytes) { + return + } + + if h.backupCount > 0 { + h.fd.Close() + + for i := h.backupCount - 1; i > 0; i-- { + sfn := fmt.Sprintf("%s.%d", h.fileName, i) + dfn := fmt.Sprintf("%s.%d", h.fileName, i+1) + + os.Rename(sfn, dfn) + } + + 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) + } +} + //refer: http://docs.python.org/2/library/logging.handlers.html //same like python TimedRotatingFileHandler diff --git a/log/log_test.go b/log/log_test.go index e5e022b..67d3b0b 100644 --- a/log/log_test.go +++ b/log/log_test.go @@ -14,3 +14,39 @@ func TestStdStreamLog(t *testing.T) { Info("hello world") } + +func TestRotatingFileLog(t *testing.T) { + path := "./test_log" + os.RemoveAll(path) + + os.Mkdir(path, 0777) + fileName := path + "/test" + + h, err := NewRotatingFileHandler(fileName, 10, 2) + if err != nil { + t.Fatal(err) + } + + buf := make([]byte, 10) + + h.Write(buf) + + h.Write(buf) + + if _, err := os.Stat(fileName + ".1"); err != nil { + t.Fatal(err) + } + + if _, err := os.Stat(fileName + ".2"); err == nil { + t.Fatal(err) + } + + h.Write(buf) + if _, err := os.Stat(fileName + ".2"); err != nil { + t.Fatal(err) + } + + h.Close() + + os.RemoveAll(path) +}