log support file & logrotate
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) { | ... | ... |
-
Please register or sign in to post a comment