Merge pull request #86 from slene/master
fix logrotate
Showing
1 changed file
with
79 additions
and
33 deletions
| ... | @@ -14,6 +14,7 @@ import ( | ... | @@ -14,6 +14,7 @@ import ( |
| 14 | 14 | ||
| 15 | type FileLogWriter struct { | 15 | type FileLogWriter struct { |
| 16 | *log.Logger | 16 | *log.Logger |
| 17 | mw *MuxWriter | ||
| 17 | // The opened file | 18 | // The opened file |
| 18 | filename string | 19 | filename string |
| 19 | 20 | ||
| ... | @@ -34,6 +35,24 @@ type FileLogWriter struct { | ... | @@ -34,6 +35,24 @@ type FileLogWriter struct { |
| 34 | startLock sync.Mutex //only one log can writer to the file | 35 | startLock sync.Mutex //only one log can writer to the file |
| 35 | } | 36 | } |
| 36 | 37 | ||
| 38 | type MuxWriter struct { | ||
| 39 | sync.Mutex | ||
| 40 | fd *os.File | ||
| 41 | } | ||
| 42 | |||
| 43 | func (l *MuxWriter) Write(b []byte) (int, error) { | ||
| 44 | l.Lock() | ||
| 45 | defer l.Unlock() | ||
| 46 | return l.fd.Write(b) | ||
| 47 | } | ||
| 48 | |||
| 49 | func (l *MuxWriter) SetFd(fd *os.File) { | ||
| 50 | if l.fd != nil { | ||
| 51 | l.fd.Close() | ||
| 52 | } | ||
| 53 | l.fd = fd | ||
| 54 | } | ||
| 55 | |||
| 37 | func NewFileWriter(fname string, rotate bool) *FileLogWriter { | 56 | func NewFileWriter(fname string, rotate bool) *FileLogWriter { |
| 38 | w := &FileLogWriter{ | 57 | w := &FileLogWriter{ |
| 39 | filename: fname, | 58 | filename: fname, |
| ... | @@ -43,6 +62,10 @@ func NewFileWriter(fname string, rotate bool) *FileLogWriter { | ... | @@ -43,6 +62,10 @@ func NewFileWriter(fname string, rotate bool) *FileLogWriter { |
| 43 | maxdays: 7, | 62 | maxdays: 7, |
| 44 | rotate: rotate, | 63 | rotate: rotate, |
| 45 | } | 64 | } |
| 65 | // use MuxWriter instead direct use os.File for lock write when rotate | ||
| 66 | w.mw = new(MuxWriter) | ||
| 67 | // set MuxWriter as Logger's io.Writer | ||
| 68 | w.Logger = log.New(w.mw, "", log.Ldate|log.Ltime) | ||
| 46 | return w | 69 | return w |
| 47 | } | 70 | } |
| 48 | 71 | ||
| ... | @@ -71,9 +94,16 @@ func (w *FileLogWriter) SetRotateMaxDays(maxdays int64) *FileLogWriter { | ... | @@ -71,9 +94,16 @@ func (w *FileLogWriter) SetRotateMaxDays(maxdays int64) *FileLogWriter { |
| 71 | } | 94 | } |
| 72 | 95 | ||
| 73 | func (w *FileLogWriter) StartLogger() error { | 96 | func (w *FileLogWriter) StartLogger() error { |
| 74 | if err := w.DoRotate(false); err != nil { | 97 | fd, err := w.createLogFile() |
| 98 | if err != nil { | ||
| 75 | return err | 99 | return err |
| 76 | } | 100 | } |
| 101 | w.mw.SetFd(fd) | ||
| 102 | err = w.initFd() | ||
| 103 | if err != nil { | ||
| 104 | return err | ||
| 105 | } | ||
| 106 | BeeLogger = w | ||
| 77 | return nil | 107 | return nil |
| 78 | } | 108 | } |
| 79 | 109 | ||
| ... | @@ -83,7 +113,7 @@ func (w *FileLogWriter) docheck(size int) { | ... | @@ -83,7 +113,7 @@ func (w *FileLogWriter) docheck(size int) { |
| 83 | if (w.maxlines > 0 && w.maxlines_curlines >= w.maxlines) || | 113 | if (w.maxlines > 0 && w.maxlines_curlines >= w.maxlines) || |
| 84 | (w.maxsize > 0 && w.maxsize_cursize >= w.maxsize) || | 114 | (w.maxsize > 0 && w.maxsize_cursize >= w.maxsize) || |
| 85 | (w.daily && time.Now().Day() != w.daily_opendate) { | 115 | (w.daily && time.Now().Day() != w.daily_opendate) { |
| 86 | if err := w.DoRotate(true); err != nil { | 116 | if err := w.DoRotate(); err != nil { |
| 87 | fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.filename, err) | 117 | fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.filename, err) |
| 88 | return | 118 | return |
| 89 | } | 119 | } |
| ... | @@ -101,37 +131,14 @@ func (w *FileLogWriter) Printf(format string, v ...interface{}) { | ... | @@ -101,37 +131,14 @@ func (w *FileLogWriter) Printf(format string, v ...interface{}) { |
| 101 | w.Logger.Printf(format, v...) | 131 | w.Logger.Printf(format, v...) |
| 102 | } | 132 | } |
| 103 | 133 | ||
| 104 | func (w *FileLogWriter) DoRotate(rotate bool) error { | 134 | func (w *FileLogWriter) createLogFile() (*os.File, error) { |
| 105 | if rotate { | ||
| 106 | _, err := os.Lstat(w.filename) | ||
| 107 | if err == nil { // file exists | ||
| 108 | // Find the next available number | ||
| 109 | num := 1 | ||
| 110 | fname := "" | ||
| 111 | for ; err == nil && num <= 999; num++ { | ||
| 112 | fname = w.filename + fmt.Sprintf(".%s.%03d", time.Now().Format("2006-01-02"), num) | ||
| 113 | _, err = os.Lstat(fname) | ||
| 114 | } | ||
| 115 | // return error if the last file checked still existed | ||
| 116 | if err == nil { | ||
| 117 | return fmt.Errorf("Rotate: Cannot find free log number to rename %s\n", w.filename) | ||
| 118 | } | ||
| 119 | |||
| 120 | // Rename the file to its newfound home | ||
| 121 | err = os.Rename(w.filename, fname) | ||
| 122 | if err != nil { | ||
| 123 | return fmt.Errorf("Rotate: %s\n", err) | ||
| 124 | } | ||
| 125 | go w.deleteOldLog() | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | // Open the log file | 135 | // Open the log file |
| 130 | fd, err := os.OpenFile(w.filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0660) | 136 | fd, err := os.OpenFile(w.filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0660) |
| 131 | if err != nil { | 137 | return fd, err |
| 132 | return err | 138 | } |
| 133 | } | 139 | |
| 134 | w.Logger = log.New(fd, "", log.Ldate|log.Ltime) | 140 | func (w *FileLogWriter) initFd() error { |
| 141 | fd := w.mw.fd | ||
| 135 | finfo, err := fd.Stat() | 142 | finfo, err := fd.Stat() |
| 136 | if err != nil { | 143 | if err != nil { |
| 137 | return fmt.Errorf("get stat err: %s\n", err) | 144 | return fmt.Errorf("get stat err: %s\n", err) |
| ... | @@ -144,11 +151,50 @@ func (w *FileLogWriter) DoRotate(rotate bool) error { | ... | @@ -144,11 +151,50 @@ func (w *FileLogWriter) DoRotate(rotate bool) error { |
| 144 | fmt.Println(err) | 151 | fmt.Println(err) |
| 145 | } | 152 | } |
| 146 | w.maxlines_curlines = len(strings.Split(string(content), "\n")) | 153 | w.maxlines_curlines = len(strings.Split(string(content), "\n")) |
| 147 | |||
| 148 | } else { | 154 | } else { |
| 149 | w.maxlines_curlines = 0 | 155 | w.maxlines_curlines = 0 |
| 150 | } | 156 | } |
| 151 | BeeLogger = w | 157 | return nil |
| 158 | } | ||
| 159 | |||
| 160 | func (w *FileLogWriter) DoRotate() error { | ||
| 161 | _, err := os.Lstat(w.filename) | ||
| 162 | if err == nil { // file exists | ||
| 163 | // Find the next available number | ||
| 164 | num := 1 | ||
| 165 | fname := "" | ||
| 166 | for ; err == nil && num <= 999; num++ { | ||
| 167 | fname = w.filename + fmt.Sprintf(".%s.%03d", time.Now().Format("2006-01-02"), num) | ||
| 168 | _, err = os.Lstat(fname) | ||
| 169 | } | ||
| 170 | // return error if the last file checked still existed | ||
| 171 | if err == nil { | ||
| 172 | return fmt.Errorf("Rotate: Cannot find free log number to rename %s\n", w.filename) | ||
| 173 | } | ||
| 174 | |||
| 175 | // block Logger's io.Writer | ||
| 176 | w.mw.Lock() | ||
| 177 | defer w.mw.Unlock() | ||
| 178 | |||
| 179 | fd := w.mw.fd | ||
| 180 | fd.Close() | ||
| 181 | |||
| 182 | // close fd before rename | ||
| 183 | // Rename the file to its newfound home | ||
| 184 | err = os.Rename(w.filename, fname) | ||
| 185 | if err != nil { | ||
| 186 | return fmt.Errorf("Rotate: %s\n", err) | ||
| 187 | } | ||
| 188 | |||
| 189 | // re-start logger | ||
| 190 | err = w.StartLogger() | ||
| 191 | if err != nil { | ||
| 192 | return fmt.Errorf("Rotate StartLogger: %s\n", err) | ||
| 193 | } | ||
| 194 | |||
| 195 | go w.deleteOldLog() | ||
| 196 | } | ||
| 197 | |||
| 152 | return nil | 198 | return nil |
| 153 | } | 199 | } |
| 154 | 200 | ... | ... |
-
Please register or sign in to post a comment