1
0
mirror of https://github.com/astaxie/beego.git synced 2024-12-22 22:00:49 +00:00

log support file & logrotate

This commit is contained in:
astaxie 2013-06-24 23:24:18 +08:00
parent c5a23d5cde
commit 73d45b150c

158
log.go
View File

@ -1,13 +1,142 @@
package beego
import (
"fmt"
"io/ioutil"
"log"
"os"
"path"
"path/filepath"
"strings"
"sync"
"time"
)
//--------------------
// LOG LEVEL
//--------------------
type FileLogWriter struct {
*log.Logger
// The opened file
filename string
maxlines int
maxlines_curlines int
// Rotate at size
maxsize int
maxsize_cursize int
// Rotate daily
daily bool
maxday int64
daily_opendate int
rotate bool
startLock sync.Mutex //only one log can writer to the file
}
func NewFileWriter(fname string, rotate bool) *FileLogWriter {
w := &FileLogWriter{
filename: fname,
maxlines: 1000000,
maxsize: 1 << 28, //256 MB
daily: true,
maxday: 7,
rotate: rotate,
}
return w
}
func (w *FileLogWriter) StartLogger() error {
if err := w.DoRotate(false); err != nil {
return err
}
return nil
}
func (w *FileLogWriter) docheck(size int) {
w.startLock.Lock()
defer w.startLock.Unlock()
if (w.maxlines > 0 && w.maxlines_curlines >= w.maxlines) ||
(w.maxsize > 0 && w.maxsize_cursize >= w.maxsize) ||
(w.daily && time.Now().Day() != w.daily_opendate) {
if err := w.DoRotate(true); err != nil {
fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.filename, err)
return
}
}
w.maxlines_curlines++
w.maxsize_cursize += size
}
func (w *FileLogWriter) Printf(format string, v ...interface{}) {
// Perform the write
str := fmt.Sprintf(format, v...)
n := 24 + len(str) // 24 stand for the length "2013/06/23 21:00:22 [T] "
w.docheck(n)
w.Logger.Printf(format, v...)
}
func (w *FileLogWriter) DoRotate(rotate bool) error {
if rotate {
_, err := os.Lstat(w.filename)
if err == nil { // file exists
// Find the next available number
num := 1
fname := ""
for ; err == nil && num <= 999; num++ {
fname = w.filename + fmt.Sprintf(".%s.%03d", time.Now().Format("2006-01-02"), num)
_, err = os.Lstat(fname)
}
// return error if the last file checked still existed
if err == nil {
return fmt.Errorf("Rotate: Cannot find free log number to rename %s\n", w.filename)
}
// Rename the file to its newfound home
err = os.Rename(w.filename, fname)
if err != nil {
return fmt.Errorf("Rotate: %s\n", err)
}
go w.deleteOldLog()
}
}
// Open the log file
fd, err := os.OpenFile(w.filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0660)
if err != nil {
return err
}
w.Logger = log.New(fd, "", log.Ldate|log.Ltime)
finfo, err := fd.Stat()
if err != nil {
return fmt.Errorf("get stat err: %s\n", err)
}
w.maxsize_cursize = int(finfo.Size())
w.daily_opendate = time.Now().Day()
if finfo.Size() > 0 {
content, err := ioutil.ReadAll(fd)
if err != nil {
//Do something
}
w.maxlines_curlines = len(strings.Split(string(content), "\n"))
} else {
w.maxlines_curlines = 0
}
BeeLogger = w
return nil
}
func (w *FileLogWriter) deleteOldLog() {
dir := path.Dir(w.filename)
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if !info.IsDir() && info.ModTime().Unix() < (time.Now().Unix()-60*60*24*w.maxday) {
os.Remove(path)
}
return nil
})
}
// Log levels to control the logging output.
const (
@ -34,8 +163,29 @@ func SetLevel(l int) {
level = l
}
type IBeeLogger interface {
Fatal(v ...interface{})
Fatalf(format string, v ...interface{})
Fatalln(v ...interface{})
Flags() int
Output(calldepth int, s string) error
Panic(v ...interface{})
Panicf(format string, v ...interface{})
Panicln(v ...interface{})
Prefix() string
Print(v ...interface{})
Printf(format string, v ...interface{})
Println(v ...interface{})
SetFlags(flag int)
SetPrefix(prefix string)
}
// logger references the used application logger.
var BeeLogger = log.New(os.Stdout, "", log.Ldate|log.Ltime)
var BeeLogger IBeeLogger
func init() {
BeeLogger = log.New(os.Stdout, "", log.Ldate|log.Ltime)
}
// SetLogger sets a new logger.
func SetLogger(l *log.Logger) {