github.com/blystad/deis@v0.11.0/logger/syslog/filehandler.go (about) 1 package syslog 2 3 import ( 4 "log" 5 "os" 6 "os/signal" 7 "syscall" 8 ) 9 10 // FileHandler implements Handler interface to save messages into a 11 // text file. It properly handles logrotate HUP signal (closes a file and tries 12 // to open/create new one). 13 type FileHandler struct { 14 bh *BaseHandler 15 filename string 16 f *os.File 17 l Logger 18 } 19 20 // NewFileHandler accepts all arguments expected by NewBaseHandler plus 21 // filename which is the path to the log file. 22 func NewFileHandler(filename string, qlen int, filter func(*Message) bool, 23 ft bool) *FileHandler { 24 25 h := &FileHandler{ 26 bh: NewBaseHandler(qlen, filter, ft), 27 filename: filename, 28 l: log.New(os.Stderr, "", log.LstdFlags), 29 } 30 go h.mainLoop() 31 return h 32 } 33 34 // SetLogger changes an internal logger used to log I/O errors. By default I/O 35 // errors are written to os.Stderr using log.Logger. 36 func (h *FileHandler) SetLogger(l Logger) { 37 h.l = l 38 } 39 40 func (h *FileHandler) mainLoop() { 41 defer h.bh.End() 42 43 mq := h.bh.Queue() 44 sq := make(chan os.Signal, 1) 45 signal.Notify(sq, syscall.SIGHUP) 46 47 for { 48 select { 49 case <-sq: // SIGHUP probably from logrotate 50 h.checkErr(h.f.Close()) 51 h.f = nil 52 case m, ok := <-mq: // message to save 53 if !ok { 54 if h.f != nil { 55 h.checkErr(h.f.Close()) 56 } 57 return 58 } 59 h.saveMessage(m) 60 } 61 } 62 } 63 64 func (h *FileHandler) saveMessage(m *Message) { 65 var err error 66 if h.f == nil { 67 h.f, err = os.OpenFile( 68 h.filename, 69 os.O_WRONLY|os.O_APPEND|os.O_CREATE, 70 0620, 71 ) 72 if h.checkErr(err) { 73 return 74 } 75 } 76 _, err = h.f.WriteString(m.String() + "\n") 77 h.checkErr(err) 78 } 79 80 func (h *FileHandler) checkErr(err error) bool { 81 if err == nil { 82 return false 83 } 84 if h.l == nil { 85 log.Print(h.filename, ": ", err) 86 } else { 87 h.l.Print(h.filename, ": ", err) 88 } 89 return true 90 } 91 92 // Handle queues and dispatches a message. See BaseHandler.Handle 93 func (h *FileHandler) Handle(m *Message) *Message { 94 return h.bh.Handle(m) 95 }