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