...
1
2
3
4
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
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
33
34
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
112 type Option func(*syslogLogger)
113
114
115 type PrioritySelector func(keyvals ...interface{}) gosyslog.Priority
116
117
118
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 }
148
View as plain text