github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/log/syslog/syslog.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build !windows,!plan9 6 7 // Package syslog provides a simple interface to the system log 8 // service. It can send messages to the syslog daemon using UNIX 9 // domain sockets, UDP or TCP. 10 // 11 // Only one call to Dial is necessary. On write failures, 12 // the syslog client will attempt to reconnect to the server 13 // and write again. 14 package syslog 15 16 import ( 17 "errors" 18 "fmt" 19 "log" 20 "net" 21 "os" 22 "strings" 23 "sync" 24 "time" 25 ) 26 27 // The Priority is a combination of the syslog facility and 28 // severity. For example, LOG_ALERT | LOG_FTP sends an alert severity 29 // message from the FTP facility. The default severity is LOG_EMERG; 30 // the default facility is LOG_KERN. 31 type Priority int 32 33 const severityMask = 0x07 34 const facilityMask = 0xf8 35 36 const ( 37 // Severity. 38 39 // From /usr/include/sys/syslog.h. 40 // These are the same on Linux, BSD, and OS X. 41 LOG_EMERG Priority = iota 42 LOG_ALERT 43 LOG_CRIT 44 LOG_ERR 45 LOG_WARNING 46 LOG_NOTICE 47 LOG_INFO 48 LOG_DEBUG 49 ) 50 51 const ( 52 // Facility. 53 54 // From /usr/include/sys/syslog.h. 55 // These are the same up to LOG_FTP on Linux, BSD, and OS X. 56 LOG_KERN Priority = iota << 3 57 LOG_USER 58 LOG_MAIL 59 LOG_DAEMON 60 LOG_AUTH 61 LOG_SYSLOG 62 LOG_LPR 63 LOG_NEWS 64 LOG_UUCP 65 LOG_CRON 66 LOG_AUTHPRIV 67 LOG_FTP 68 _ // unused 69 _ // unused 70 _ // unused 71 _ // unused 72 LOG_LOCAL0 73 LOG_LOCAL1 74 LOG_LOCAL2 75 LOG_LOCAL3 76 LOG_LOCAL4 77 LOG_LOCAL5 78 LOG_LOCAL6 79 LOG_LOCAL7 80 ) 81 82 // A Writer is a connection to a syslog server. 83 type Writer struct { 84 priority Priority 85 tag string 86 hostname string 87 network string 88 raddr string 89 90 mu sync.Mutex // guards conn 91 conn net.Conn 92 } 93 94 // New establishes a new connection to the system log daemon. Each 95 // write to the returned writer sends a log message with the given 96 // priority and prefix. 97 func New(priority Priority, tag string) (w *Writer, err error) { 98 return Dial("", "", priority, tag) 99 } 100 101 // Dial establishes a connection to a log daemon by connecting to 102 // address raddr on the network net. Each write to the returned 103 // writer sends a log message with the given facility, severity and 104 // tag. 105 func Dial(network, raddr string, priority Priority, tag string) (*Writer, error) { 106 if priority < 0 || priority > LOG_LOCAL7|LOG_DEBUG { 107 return nil, errors.New("log/syslog: invalid priority") 108 } 109 110 if tag == "" { 111 tag = os.Args[0] 112 } 113 hostname, _ := os.Hostname() 114 115 w := &Writer{ 116 priority: priority, 117 tag: tag, 118 hostname: hostname, 119 network: network, 120 raddr: raddr, 121 } 122 123 w.mu.Lock() 124 defer w.mu.Unlock() 125 126 err := w.connect() 127 if err != nil { 128 return nil, err 129 } 130 return w, err 131 } 132 133 // connect makes a connection to the syslog server. 134 // It must be called with w.mu held. 135 func (w *Writer) connect() (err error) { 136 if w.conn != nil { 137 // ignore err from close, it makes sense to continue anyway 138 w.conn.Close() 139 w.conn = nil 140 } 141 142 if w.network == "" { 143 w.conn, err = unixSyslog() 144 if w.hostname == "" { 145 w.hostname = "localhost" 146 } 147 } else { 148 var c net.Conn 149 c, err = net.Dial(w.network, w.raddr) 150 if err == nil { 151 w.conn = c 152 if w.hostname == "" { 153 w.hostname = c.LocalAddr().String() 154 } 155 } 156 } 157 return 158 } 159 160 // Write sends a log message to the syslog daemon. 161 func (w *Writer) Write(b []byte) (int, error) { 162 return w.writeAndRetry(w.priority, string(b)) 163 } 164 165 // Close closes a connection to the syslog daemon. 166 func (w *Writer) Close() error { 167 w.mu.Lock() 168 defer w.mu.Unlock() 169 170 if w.conn != nil { 171 err := w.conn.Close() 172 w.conn = nil 173 return err 174 } 175 return nil 176 } 177 178 // Emerg logs a message with severity LOG_EMERG, ignoring the severity 179 // passed to New. 180 func (w *Writer) Emerg(m string) (err error) { 181 _, err = w.writeAndRetry(LOG_EMERG, m) 182 return err 183 } 184 185 // Alert logs a message with severity LOG_ALERT, ignoring the severity 186 // passed to New. 187 func (w *Writer) Alert(m string) (err error) { 188 _, err = w.writeAndRetry(LOG_ALERT, m) 189 return err 190 } 191 192 // Crit logs a message with severity LOG_CRIT, ignoring the severity 193 // passed to New. 194 func (w *Writer) Crit(m string) (err error) { 195 _, err = w.writeAndRetry(LOG_CRIT, m) 196 return err 197 } 198 199 // Err logs a message with severity LOG_ERR, ignoring the severity 200 // passed to New. 201 func (w *Writer) Err(m string) (err error) { 202 _, err = w.writeAndRetry(LOG_ERR, m) 203 return err 204 } 205 206 // Wanring logs a message with severity LOG_WARNING, ignoring the 207 // severity passed to New. 208 func (w *Writer) Warning(m string) (err error) { 209 _, err = w.writeAndRetry(LOG_WARNING, m) 210 return err 211 } 212 213 // Notice logs a message with severity LOG_NOTICE, ignoring the 214 // severity passed to New. 215 func (w *Writer) Notice(m string) (err error) { 216 _, err = w.writeAndRetry(LOG_NOTICE, m) 217 return err 218 } 219 220 // Info logs a message with severity LOG_INFO, ignoring the severity 221 // passed to New. 222 func (w *Writer) Info(m string) (err error) { 223 _, err = w.writeAndRetry(LOG_INFO, m) 224 return err 225 } 226 227 // Debug logs a message with severity LOG_DEBUG, ignoring the severity 228 // passed to New. 229 func (w *Writer) Debug(m string) (err error) { 230 _, err = w.writeAndRetry(LOG_DEBUG, m) 231 return err 232 } 233 234 func (w *Writer) writeAndRetry(p Priority, s string) (int, error) { 235 pr := (w.priority & facilityMask) | (p & severityMask) 236 237 w.mu.Lock() 238 defer w.mu.Unlock() 239 240 if w.conn != nil { 241 if n, err := w.write(pr, s); err == nil { 242 return n, err 243 } 244 } 245 if err := w.connect(); err != nil { 246 return 0, err 247 } 248 return w.write(pr, s) 249 } 250 251 // write generates and writes a syslog formatted string. The 252 // format is as follows: <PRI>TIMESTAMP HOSTNAME TAG[PID]: MSG 253 func (w *Writer) write(p Priority, msg string) (int, error) { 254 // ensure it ends in a \n 255 nl := "" 256 if !strings.HasSuffix(msg, "\n") { 257 nl = "\n" 258 } 259 260 timestamp := time.Now().Format(time.RFC3339) 261 fmt.Fprintf(w.conn, "<%d>%s %s %s[%d]: %s%s", 262 p, timestamp, w.hostname, 263 w.tag, os.Getpid(), msg, nl) 264 return len(msg), nil 265 } 266 267 // NewLogger creates a log.Logger whose output is written to 268 // the system log service with the specified priority. The logFlag 269 // argument is the flag set passed through to log.New to create 270 // the Logger. 271 func NewLogger(p Priority, logFlag int) (*log.Logger, error) { 272 s, err := New(p, "") 273 if err != nil { 274 return nil, err 275 } 276 return log.New(s, "", logFlag), nil 277 }