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  }