// handleLog consumes and logs any Entry's passed to the channel func (s *Syslog) handleLog(entries <-chan *log.Entry) { var e *log.Entry var line string formatter := s.formatFunc(s) for e = range entries { line = string(formatter(e)) switch e.Level { case log.DebugLevel: s.writer.Debug(line) case log.TraceLevel, log.InfoLevel: s.writer.Info(line) case log.NoticeLevel: s.writer.Notice(line) case log.WarnLevel: s.writer.Warning(line) case log.ErrorLevel: s.writer.Err(line) case log.PanicLevel, log.AlertLevel: s.writer.Alert(line) case log.FatalLevel: s.writer.Crit(line) } e.Consumed() } }
// HandleLog is the default http log handler func HandleLog(h HTTP, entries <-chan *log.Entry) { var e *log.Entry var b []byte var reader *bytes.Reader formatter := h.FormatFunc()(h) remoteHost := h.RemoteHost() httpClient := stdhttp.Client{} req, _ := stdhttp.NewRequest(h.Method(), remoteHost, nil) req.Header = h.Headers() for e = range entries { b = formatter(e) reader = bytes.NewReader(b) req.Body = ioutil.NopCloser(reader) req.ContentLength = int64(reader.Len()) resp, err := httpClient.Do(req) if err != nil { log.Error("Could not post data to %s: %v\n", remoteHost, err) goto END } if resp.StatusCode < 200 || resp.StatusCode >= 299 { bt, _ := ioutil.ReadAll(resp.Body) log.Error("Received HTTP %d during POST request to %s body: %s\n", resp.StatusCode, remoteHost, string(bt)) } END: e.Consumed() } }
// handleLog consumes and logs any Entry's passed to the channel func (c *Console) handleLog(entries <-chan *log.Entry) { var e *log.Entry // var b io.WriterTo var b []byte formatter := c.formatFunc(c) for e = range entries { b = formatter(e) c.writer.Write(b) e.Consumed() } }
// Run starts the logger consuming on the returned channed func (c *CustomHandler) Run() chan<- *log.Entry { // in a big high traffic app, set a higher buffer ch := make(chan *log.Entry, c.buffer) // can run as many consumers on the channel as you want, // depending on the buffer size or your needs go func(entries <-chan *log.Entry) { // below prints to os.Stderr but could marshal to JSON // and send to central logging server // --------- // |----------> | console | // | --------- // i.e. ----------------- ----------------- Unmarshal ------------- -------- // | app log handler | -- json --> | central log app | -- to -> | log handler | --> | syslog | // ----------------- ----------------- Entry ------------- -------- // | --------- // |----------> | DataDog | // --------- var e *log.Entry b := new(bytes.Buffer) for e = range entries { b.Reset() b.WriteString(e.Message) for _, f := range e.Fields { fmt.Fprintf(b, " %s=%v", f.Key, f.Value) } fmt.Println(b.String()) e.Consumed() // done writing the entry } }(ch) return ch }
func (email *Email) handleLog(entries <-chan *log.Entry) { var e *log.Entry var s gomail.SendCloser var err error var open bool var alreadyTriedSending bool var message *gomail.Message var count uint8 formatter := email.formatFunc(email) d := gomail.NewDialer(email.host, email.port, email.username, email.password) for { select { case e = <-entries: count = 0 alreadyTriedSending = false message = formatter(e) REOPEN: // check if smtp connection open if !open { count++ if s, err = d.Dial(); err != nil { log.WithFields(log.F("error", err)).Warn("ERROR connection to smtp server") if count == 3 { // we tried to reconnect... e.Consumed() break } goto REOPEN } count = 0 open = true } RESEND: count++ if err = gomail.Send(s, message); err != nil { log.WithFields(log.F("error", err)).Warn("ERROR sending to smtp server, retrying") if count == 3 && !alreadyTriedSending { // maybe we got disconnected... alreadyTriedSending = true open = false s.Close() goto REOPEN } else if alreadyTriedSending { // we reopened and tried 2 more times, can;t say we didn't try log.WithFields(log.F("error", err)).Alert("ERROR sending log via EMAIL, RETRY and REOPEN failed") e.Consumed() break } goto RESEND } e.Consumed() case <-time.After(email.keepalive): if open { s.Close() open = false } } } }