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