73d45b15 by astaxie

log support file & logrotate

1 parent c5a23d5c
Showing 1 changed file with 154 additions and 4 deletions
1 package beego 1 package beego
2 2
3 import ( 3 import (
4 "fmt"
5 "io/ioutil"
4 "log" 6 "log"
5 "os" 7 "os"
8 "path"
9 "path/filepath"
10 "strings"
11 "sync"
12 "time"
6 ) 13 )
7 14
8 //-------------------- 15 type FileLogWriter struct {
9 // LOG LEVEL 16 *log.Logger
10 //-------------------- 17 // The opened file
18 filename string
19
20 maxlines int
21 maxlines_curlines int
22
23 // Rotate at size
24 maxsize int
25 maxsize_cursize int
26
27 // Rotate daily
28 daily bool
29 maxday int64
30 daily_opendate int
31
32 rotate bool
33
34 startLock sync.Mutex //only one log can writer to the file
35 }
36
37 func NewFileWriter(fname string, rotate bool) *FileLogWriter {
38 w := &FileLogWriter{
39 filename: fname,
40 maxlines: 1000000,
41 maxsize: 1 << 28, //256 MB
42 daily: true,
43 maxday: 7,
44 rotate: rotate,
45 }
46 return w
47 }
48
49 func (w *FileLogWriter) StartLogger() error {
50 if err := w.DoRotate(false); err != nil {
51 return err
52 }
53 return nil
54 }
55
56 func (w *FileLogWriter) docheck(size int) {
57 w.startLock.Lock()
58 defer w.startLock.Unlock()
59 if (w.maxlines > 0 && w.maxlines_curlines >= w.maxlines) ||
60 (w.maxsize > 0 && w.maxsize_cursize >= w.maxsize) ||
61 (w.daily && time.Now().Day() != w.daily_opendate) {
62 if err := w.DoRotate(true); err != nil {
63 fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.filename, err)
64 return
65 }
66 }
67 w.maxlines_curlines++
68 w.maxsize_cursize += size
69 }
70
71 func (w *FileLogWriter) Printf(format string, v ...interface{}) {
72 // Perform the write
73 str := fmt.Sprintf(format, v...)
74 n := 24 + len(str) // 24 stand for the length "2013/06/23 21:00:22 [T] "
75
76 w.docheck(n)
77 w.Logger.Printf(format, v...)
78 }
79
80 func (w *FileLogWriter) DoRotate(rotate bool) error {
81 if rotate {
82 _, err := os.Lstat(w.filename)
83 if err == nil { // file exists
84 // Find the next available number
85 num := 1
86 fname := ""
87 for ; err == nil && num <= 999; num++ {
88 fname = w.filename + fmt.Sprintf(".%s.%03d", time.Now().Format("2006-01-02"), num)
89 _, err = os.Lstat(fname)
90 }
91 // return error if the last file checked still existed
92 if err == nil {
93 return fmt.Errorf("Rotate: Cannot find free log number to rename %s\n", w.filename)
94 }
95
96 // Rename the file to its newfound home
97 err = os.Rename(w.filename, fname)
98 if err != nil {
99 return fmt.Errorf("Rotate: %s\n", err)
100 }
101 go w.deleteOldLog()
102 }
103 }
104
105 // Open the log file
106 fd, err := os.OpenFile(w.filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0660)
107 if err != nil {
108 return err
109 }
110 w.Logger = log.New(fd, "", log.Ldate|log.Ltime)
111 finfo, err := fd.Stat()
112 if err != nil {
113 return fmt.Errorf("get stat err: %s\n", err)
114 }
115 w.maxsize_cursize = int(finfo.Size())
116 w.daily_opendate = time.Now().Day()
117 if finfo.Size() > 0 {
118 content, err := ioutil.ReadAll(fd)
119 if err != nil {
120 //Do something
121 }
122 w.maxlines_curlines = len(strings.Split(string(content), "\n"))
123
124 } else {
125 w.maxlines_curlines = 0
126 }
127 BeeLogger = w
128 return nil
129 }
130
131 func (w *FileLogWriter) deleteOldLog() {
132 dir := path.Dir(w.filename)
133 filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
134 if !info.IsDir() && info.ModTime().Unix() < (time.Now().Unix()-60*60*24*w.maxday) {
135 os.Remove(path)
136 }
137 return nil
138 })
139 }
11 140
12 // Log levels to control the logging output. 141 // Log levels to control the logging output.
13 const ( 142 const (
...@@ -34,8 +163,29 @@ func SetLevel(l int) { ...@@ -34,8 +163,29 @@ func SetLevel(l int) {
34 level = l 163 level = l
35 } 164 }
36 165
166 type IBeeLogger interface {
167 Fatal(v ...interface{})
168 Fatalf(format string, v ...interface{})
169 Fatalln(v ...interface{})
170 Flags() int
171 Output(calldepth int, s string) error
172 Panic(v ...interface{})
173 Panicf(format string, v ...interface{})
174 Panicln(v ...interface{})
175 Prefix() string
176 Print(v ...interface{})
177 Printf(format string, v ...interface{})
178 Println(v ...interface{})
179 SetFlags(flag int)
180 SetPrefix(prefix string)
181 }
182
37 // logger references the used application logger. 183 // logger references the used application logger.
38 var BeeLogger = log.New(os.Stdout, "", log.Ldate|log.Ltime) 184 var BeeLogger IBeeLogger
185
186 func init() {
187 BeeLogger = log.New(os.Stdout, "", log.Ldate|log.Ltime)
188 }
39 189
40 // SetLogger sets a new logger. 190 // SetLogger sets a new logger.
41 func SetLogger(l *log.Logger) { 191 func SetLogger(l *log.Logger) {
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!