123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- package log
- import (
- "fmt"
- "os"
- "path"
- "time"
- )
- // FileHandler writes log to a file.
- type FileHandler struct {
- fd *os.File
- }
- // NewFileHandler creates a FileHander
- func NewFileHandler(fileName string, flag int) (*FileHandler, error) {
- dir := path.Dir(fileName)
- os.Mkdir(dir, 0777)
- f, err := os.OpenFile(fileName, flag, 0755)
- if err != nil {
- return nil, err
- }
- h := new(FileHandler)
- h.fd = f
- return h, nil
- }
- // Write implements Handler interface
- func (h *FileHandler) Write(b []byte) (n int, err error) {
- return h.fd.Write(b)
- }
- // Close implements Handler interface
- func (h *FileHandler) Close() error {
- return h.fd.Close()
- }
- // RotatingFileHandler writes log a file, if file size exceeds maxBytes,
- // it will backup current file and open a new one.
- //
- // max backup file number is set by backupCount, it will delete oldest if backups too many.
- type RotatingFileHandler struct {
- fd *os.File
- fileName string
- maxBytes int
- curBytes int
- backupCount int
- }
- // NewRotatingFileHandler creates a RotatingFileHandler
- func NewRotatingFileHandler(fileName string, maxBytes int, backupCount int) (*RotatingFileHandler, error) {
- dir := path.Dir(fileName)
- os.MkdirAll(dir, 0777)
- h := new(RotatingFileHandler)
- if maxBytes <= 0 {
- return nil, fmt.Errorf("invalid max bytes")
- }
- 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
- }
- f, err := h.fd.Stat()
- if err != nil {
- return nil, err
- }
- h.curBytes = int(f.Size())
- return h, nil
- }
- // Write implements Handler interface
- func (h *RotatingFileHandler) Write(p []byte) (n int, err error) {
- h.doRollover()
- n, err = h.fd.Write(p)
- h.curBytes += n
- return
- }
- // Close implements Handler interface
- func (h *RotatingFileHandler) Close() error {
- if h.fd != nil {
- return h.fd.Close()
- }
- return nil
- }
- func (h *RotatingFileHandler) doRollover() {
- if h.curBytes < h.maxBytes {
- return
- }
- f, err := h.fd.Stat()
- if err != nil {
- return
- }
- if h.maxBytes <= 0 {
- return
- } else if f.Size() < int64(h.maxBytes) {
- h.curBytes = int(f.Size())
- 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)
- h.curBytes = 0
- f, err := h.fd.Stat()
- if err != nil {
- return
- }
- h.curBytes = int(f.Size())
- }
- }
- // TimeRotatingFileHandler 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 TimeRotatingFileHandler struct {
- fd *os.File
- baseName string
- interval int64
- suffix string
- rolloverAt int64
- }
- // TimeRotating way
- const (
- WhenSecond = iota
- WhenMinute
- WhenHour
- WhenDay
- )
- // NewTimeRotatingFileHandler creates a TimeRotatingFileHandler
- func NewTimeRotatingFileHandler(baseName string, when int8, interval int) (*TimeRotatingFileHandler, error) {
- dir := path.Dir(baseName)
- os.MkdirAll(dir, 0777)
- h := new(TimeRotatingFileHandler)
- h.baseName = baseName
- switch when {
- case WhenSecond:
- h.interval = 1
- h.suffix = "2006-01-02_15-04-05"
- case WhenMinute:
- h.interval = 60
- h.suffix = "2006-01-02_15-04"
- case WhenHour:
- h.interval = 3600
- h.suffix = "2006-01-02_15"
- case WhenDay:
- h.interval = 3600 * 24
- h.suffix = "2006-01-02"
- default:
- return nil, fmt.Errorf("invalid when_rotate: %d", when)
- }
- h.interval = h.interval * int64(interval)
- var err error
- h.fd, err = os.OpenFile(h.baseName, 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 *TimeRotatingFileHandler) 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)
- 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
- }
- }
- // Write implements Handler interface
- func (h *TimeRotatingFileHandler) Write(b []byte) (n int, err error) {
- h.doRollover()
- return h.fd.Write(b)
- }
- // Close implements Handler interface
- func (h *TimeRotatingFileHandler) Close() error {
- return h.fd.Close()
- }
|