The syslog library has been changed to prevent crashes if the syslog server is down, writing does not degrade if syslog server is slow.

This commit is contained in:
aluvare 2021-02-11 15:56:16 +01:00
parent cd4bf4ef8d
commit f160b155bb
1 changed files with 67 additions and 22 deletions

View File

@ -4,50 +4,95 @@ package syslog
import ( import (
"fmt" "fmt"
"log/syslog" //"log/syslog"
"github.com/GolangResources/syslog/syslog"
"os" "os"
"time"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
const (
NUM_SYSLOG_WORKERS = 8
CHANNEL_DEPTH = 8192
)
// SyslogHook to send logs via syslog. // SyslogHook to send logs via syslog.
type SyslogHook struct { type SyslogHook struct {
Writer *syslog.Writer Writer *syslog.Writer
SyslogNetwork string SyslogNetwork string
SyslogRaddr string SyslogRaddr string
Tag string
syschan chan *SEntry
}
type SEntry struct {
line string
level logrus.Level
} }
// Creates a hook to be added to an instance of logger. This is called with // Creates a hook to be added to an instance of logger. This is called with
// `hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_DEBUG, "")` // `hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_DEBUG, "")`
// `if err == nil { log.Hooks.Add(hook) }` // `if err == nil { log.Hooks.Add(hook) }`
func NewSyslogHook(network, raddr string, priority syslog.Priority, tag string) (*SyslogHook, error) { func NewSyslogHook(network, raddr string, priority syslog.Priority, tag string) (*SyslogHook, error) {
w, err := syslog.Dial(network, raddr, priority, tag) w, err := syslog.Dial("ctcp" , raddr, priority, nil)
return &SyslogHook{w, network, raddr}, err if err != nil {
return nil, err
}
hook := &SyslogHook{
w,
network,
raddr,
tag,
make(chan *SEntry, CHANNEL_DEPTH),
}
for i := 0; i <= NUM_SYSLOG_WORKERS; i++ {
go hook.worker(i)
}
return hook, err
}
func (hook *SyslogHook) worker(i int) {
for entry := range hook.syschan {
time.Sleep(1)
func() error {
switch entry.level {
case logrus.PanicLevel:
return hook.Writer.Crit(&entry.line, hook.Tag)
case logrus.FatalLevel:
return hook.Writer.Crit(&entry.line, hook.Tag)
case logrus.ErrorLevel:
return hook.Writer.Err(&entry.line, hook.Tag)
case logrus.WarnLevel:
return hook.Writer.Warning(&entry.line, hook.Tag)
case logrus.InfoLevel:
return hook.Writer.Info(&entry.line, hook.Tag)
case logrus.DebugLevel, logrus.TraceLevel:
return hook.Writer.Debug(&entry.line, hook.Tag)
default:
return nil
}
}()
}
} }
func (hook *SyslogHook) Fire(entry *logrus.Entry) error { func (hook *SyslogHook) Fire(entry *logrus.Entry) error {
var err error
line, err := entry.String() line, err := entry.String()
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err) fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err)
return err return err
} }
sentry := &SEntry{
switch entry.Level { line: line,
case logrus.PanicLevel: level: entry.Level,
return hook.Writer.Crit(line)
case logrus.FatalLevel:
return hook.Writer.Crit(line)
case logrus.ErrorLevel:
return hook.Writer.Err(line)
case logrus.WarnLevel:
return hook.Writer.Warning(line)
case logrus.InfoLevel:
return hook.Writer.Info(line)
case logrus.DebugLevel, logrus.TraceLevel:
return hook.Writer.Debug(line)
default:
return nil
} }
select {
case hook.syschan <- sentry:
default:
err = fmt.Errorf("logrus syslog chan full")
}
return err
} }
func (hook *SyslogHook) Levels() []logrus.Level { func (hook *SyslogHook) Levels() []logrus.Level {