1
2
3
4
5
6
7
8 package syslog
9
10 import (
11 "errors"
12 "fmt"
13 "log"
14 "net"
15 "os"
16 "strings"
17 "sync"
18 "time"
19 )
20
21
22
23
24
25 type Priority int
26
27 const severityMask = 0x07
28 const facilityMask = 0xf8
29
30 const (
31
32
33
34
35 LOG_EMERG Priority = iota
36 LOG_ALERT
37 LOG_CRIT
38 LOG_ERR
39 LOG_WARNING
40 LOG_NOTICE
41 LOG_INFO
42 LOG_DEBUG
43 )
44
45 const (
46
47
48
49
50 LOG_KERN Priority = iota << 3
51 LOG_USER
52 LOG_MAIL
53 LOG_DAEMON
54 LOG_AUTH
55 LOG_SYSLOG
56 LOG_LPR
57 LOG_NEWS
58 LOG_UUCP
59 LOG_CRON
60 LOG_AUTHPRIV
61 LOG_FTP
62 _
63 _
64 _
65 _
66 LOG_LOCAL0
67 LOG_LOCAL1
68 LOG_LOCAL2
69 LOG_LOCAL3
70 LOG_LOCAL4
71 LOG_LOCAL5
72 LOG_LOCAL6
73 LOG_LOCAL7
74 )
75
76
77 type Writer struct {
78 priority Priority
79 tag string
80 hostname string
81 network string
82 raddr string
83
84 mu sync.Mutex
85 conn serverConn
86 }
87
88
89
90
91
92
93
94 type serverConn interface {
95 writeString(p Priority, hostname, tag, s, nl string) error
96 close() error
97 }
98
99 type netConn struct {
100 local bool
101 conn net.Conn
102 }
103
104
105
106
107
108 func New(priority Priority, tag string) (*Writer, error) {
109 return Dial("", "", priority, tag)
110 }
111
112
113
114
115
116
117
118
119 func Dial(network, raddr string, priority Priority, tag string) (*Writer, error) {
120 if priority < 0 || priority > LOG_LOCAL7|LOG_DEBUG {
121 return nil, errors.New("log/syslog: invalid priority")
122 }
123
124 if tag == "" {
125 tag = os.Args[0]
126 }
127 hostname, _ := os.Hostname()
128
129 w := &Writer{
130 priority: priority,
131 tag: tag,
132 hostname: hostname,
133 network: network,
134 raddr: raddr,
135 }
136
137 w.mu.Lock()
138 defer w.mu.Unlock()
139
140 err := w.connect()
141 if err != nil {
142 return nil, err
143 }
144 return w, err
145 }
146
147
148
149 func (w *Writer) connect() (err error) {
150 if w.conn != nil {
151
152 w.conn.close()
153 w.conn = nil
154 }
155
156 if w.network == "" {
157 w.conn, err = unixSyslog()
158 if w.hostname == "" {
159 w.hostname = "localhost"
160 }
161 } else {
162 var c net.Conn
163 c, err = net.Dial(w.network, w.raddr)
164 if err == nil {
165 w.conn = &netConn{
166 conn: c,
167 local: w.network == "unixgram" || w.network == "unix",
168 }
169 if w.hostname == "" {
170 w.hostname = c.LocalAddr().String()
171 }
172 }
173 }
174 return
175 }
176
177
178 func (w *Writer) Write(b []byte) (int, error) {
179 return w.writeAndRetry(w.priority, string(b))
180 }
181
182
183 func (w *Writer) Close() error {
184 w.mu.Lock()
185 defer w.mu.Unlock()
186
187 if w.conn != nil {
188 err := w.conn.close()
189 w.conn = nil
190 return err
191 }
192 return nil
193 }
194
195
196
197 func (w *Writer) Emerg(m string) error {
198 _, err := w.writeAndRetry(LOG_EMERG, m)
199 return err
200 }
201
202
203
204 func (w *Writer) Alert(m string) error {
205 _, err := w.writeAndRetry(LOG_ALERT, m)
206 return err
207 }
208
209
210
211 func (w *Writer) Crit(m string) error {
212 _, err := w.writeAndRetry(LOG_CRIT, m)
213 return err
214 }
215
216
217
218 func (w *Writer) Err(m string) error {
219 _, err := w.writeAndRetry(LOG_ERR, m)
220 return err
221 }
222
223
224
225 func (w *Writer) Warning(m string) error {
226 _, err := w.writeAndRetry(LOG_WARNING, m)
227 return err
228 }
229
230
231
232 func (w *Writer) Notice(m string) error {
233 _, err := w.writeAndRetry(LOG_NOTICE, m)
234 return err
235 }
236
237
238
239 func (w *Writer) Info(m string) error {
240 _, err := w.writeAndRetry(LOG_INFO, m)
241 return err
242 }
243
244
245
246 func (w *Writer) Debug(m string) error {
247 _, err := w.writeAndRetry(LOG_DEBUG, m)
248 return err
249 }
250
251 func (w *Writer) writeAndRetry(p Priority, s string) (int, error) {
252 pr := (w.priority & facilityMask) | (p & severityMask)
253
254 w.mu.Lock()
255 defer w.mu.Unlock()
256
257 if w.conn != nil {
258 if n, err := w.write(pr, s); err == nil {
259 return n, err
260 }
261 }
262 if err := w.connect(); err != nil {
263 return 0, err
264 }
265 return w.write(pr, s)
266 }
267
268
269
270 func (w *Writer) write(p Priority, msg string) (int, error) {
271
272 nl := ""
273 if !strings.HasSuffix(msg, "\n") {
274 nl = "\n"
275 }
276
277 err := w.conn.writeString(p, w.hostname, w.tag, msg, nl)
278 if err != nil {
279 return 0, err
280 }
281
282
283
284 return len(msg), nil
285 }
286
287 func (n *netConn) writeString(p Priority, hostname, tag, msg, nl string) error {
288 if n.local {
289
290
291
292 timestamp := time.Now().Format(time.Stamp)
293 _, err := fmt.Fprintf(n.conn, "<%d>%s %s[%d]: %s%s",
294 p, timestamp,
295 tag, os.Getpid(), msg, nl)
296 return err
297 }
298 timestamp := time.Now().Format(time.RFC3339)
299 _, err := fmt.Fprintf(n.conn, "<%d>%s %s %s[%d]: %s%s",
300 p, timestamp, hostname,
301 tag, os.Getpid(), msg, nl)
302 return err
303 }
304
305 func (n *netConn) close() error {
306 return n.conn.Close()
307 }
308
309
310
311
312
313 func NewLogger(p Priority, logFlag int) (*log.Logger, error) {
314 s, err := New(p, "")
315 if err != nil {
316 return nil, err
317 }
318 return log.New(s, "", logFlag), nil
319 }
320
View as plain text