github.com/go-kit/log@v0.2.1/syslog/syslog.go (about) 1 //go:build !windows && !plan9 && !nacl 2 // +build !windows,!plan9,!nacl 3 4 // Package syslog provides a Logger that writes to syslog. 5 package syslog 6 7 import ( 8 "bytes" 9 "io" 10 "sync" 11 12 gosyslog "log/syslog" 13 14 "github.com/go-kit/log" 15 "github.com/go-kit/log/level" 16 ) 17 18 // SyslogWriter is an interface wrapping stdlib syslog Writer. 19 type SyslogWriter interface { 20 Write([]byte) (int, error) 21 Close() error 22 Emerg(string) error 23 Alert(string) error 24 Crit(string) error 25 Err(string) error 26 Warning(string) error 27 Notice(string) error 28 Info(string) error 29 Debug(string) error 30 } 31 32 // NewSyslogLogger returns a new Logger which writes to syslog in syslog format. 33 // The body of the log message is the formatted output from the Logger returned 34 // by newLogger. 35 func NewSyslogLogger(w SyslogWriter, newLogger func(io.Writer) log.Logger, options ...Option) log.Logger { 36 l := &syslogLogger{ 37 w: w, 38 newLogger: newLogger, 39 prioritySelector: defaultPrioritySelector, 40 bufPool: sync.Pool{New: func() interface{} { 41 return &loggerBuf{} 42 }}, 43 } 44 45 for _, option := range options { 46 option(l) 47 } 48 49 return l 50 } 51 52 type syslogLogger struct { 53 w SyslogWriter 54 newLogger func(io.Writer) log.Logger 55 prioritySelector PrioritySelector 56 bufPool sync.Pool 57 } 58 59 func (l *syslogLogger) Log(keyvals ...interface{}) error { 60 level := l.prioritySelector(keyvals...) 61 62 lb := l.getLoggerBuf() 63 defer l.putLoggerBuf(lb) 64 if err := lb.logger.Log(keyvals...); err != nil { 65 return err 66 } 67 68 switch level { 69 case gosyslog.LOG_EMERG: 70 return l.w.Emerg(lb.buf.String()) 71 case gosyslog.LOG_ALERT: 72 return l.w.Alert(lb.buf.String()) 73 case gosyslog.LOG_CRIT: 74 return l.w.Crit(lb.buf.String()) 75 case gosyslog.LOG_ERR: 76 return l.w.Err(lb.buf.String()) 77 case gosyslog.LOG_WARNING: 78 return l.w.Warning(lb.buf.String()) 79 case gosyslog.LOG_NOTICE: 80 return l.w.Notice(lb.buf.String()) 81 case gosyslog.LOG_INFO: 82 return l.w.Info(lb.buf.String()) 83 case gosyslog.LOG_DEBUG: 84 return l.w.Debug(lb.buf.String()) 85 default: 86 _, err := l.w.Write(lb.buf.Bytes()) 87 return err 88 } 89 } 90 91 type loggerBuf struct { 92 buf *bytes.Buffer 93 logger log.Logger 94 } 95 96 func (l *syslogLogger) getLoggerBuf() *loggerBuf { 97 lb := l.bufPool.Get().(*loggerBuf) 98 if lb.buf == nil { 99 lb.buf = &bytes.Buffer{} 100 lb.logger = l.newLogger(lb.buf) 101 } else { 102 lb.buf.Reset() 103 } 104 return lb 105 } 106 107 func (l *syslogLogger) putLoggerBuf(lb *loggerBuf) { 108 l.bufPool.Put(lb) 109 } 110 111 // Option sets a parameter for syslog loggers. 112 type Option func(*syslogLogger) 113 114 // PrioritySelector inspects the list of keyvals and selects a syslog priority. 115 type PrioritySelector func(keyvals ...interface{}) gosyslog.Priority 116 117 // PrioritySelectorOption sets priority selector function to choose syslog 118 // priority. 119 func PrioritySelectorOption(selector PrioritySelector) Option { 120 return func(l *syslogLogger) { l.prioritySelector = selector } 121 } 122 123 func defaultPrioritySelector(keyvals ...interface{}) gosyslog.Priority { 124 l := len(keyvals) 125 for i := 0; i < l; i += 2 { 126 if keyvals[i] == level.Key() { 127 var val interface{} 128 if i+1 < l { 129 val = keyvals[i+1] 130 } 131 if v, ok := val.(level.Value); ok { 132 switch v { 133 case level.DebugValue(): 134 return gosyslog.LOG_DEBUG 135 case level.InfoValue(): 136 return gosyslog.LOG_INFO 137 case level.WarnValue(): 138 return gosyslog.LOG_WARNING 139 case level.ErrorValue(): 140 return gosyslog.LOG_ERR 141 } 142 } 143 } 144 } 145 146 return gosyslog.LOG_INFO 147 }