Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(443)

Side by Side Diff: src/pkg/log/syslog/syslog.go

Issue 6782140: code review 6782140: log/syslog: retry once if write fails (Closed)
Patch Set: diff -r ee5afd4b14b7 https://code.google.com/p/go Created 12 years, 3 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/pkg/log/syslog/syslog_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // +build !windows,!plan9 5 // +build !windows,!plan9
6 6
7 // Package syslog provides a simple interface to the system log 7 // Package syslog provides a simple interface to the system log
8 // service. It can send messages to the syslog daemon using UNIX 8 // service. It can send messages to the syslog daemon using UNIX
9 // domain sockets, UDP, or TCP connections. 9 // domain sockets, UDP, or TCP connections.
10 package syslog 10 package syslog
11 11
12 import ( 12 import (
13 "errors" 13 "errors"
14 "fmt" 14 "fmt"
15 "log" 15 "log"
16 "net" 16 "net"
17 "os" 17 "os"
18 "sync"
18 "time" 19 "time"
19 ) 20 )
20 21
21 // The Priority is a combination of the syslog facility and 22 // The Priority is a combination of the syslog facility and
22 // severity. For example, LOG_ALERT | LOG_FTP sends an alert severity 23 // severity. For example, LOG_ALERT | LOG_FTP sends an alert severity
23 // message from the FTP facility. The default severity is LOG_EMERG; 24 // message from the FTP facility. The default severity is LOG_EMERG;
24 // the default facility is LOG_KERN. 25 // the default facility is LOG_KERN.
25 type Priority int 26 type Priority int
26 27
27 const severityMask = 0x07 28 const severityMask = 0x07
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 LOG_LOCAL5 72 LOG_LOCAL5
72 LOG_LOCAL6 73 LOG_LOCAL6
73 LOG_LOCAL7 74 LOG_LOCAL7
74 ) 75 )
75 76
76 // A Writer is a connection to a syslog server. 77 // A Writer is a connection to a syslog server.
77 type Writer struct { 78 type Writer struct {
78 priority Priority 79 priority Priority
79 tag string 80 tag string
80 hostname string 81 hostname string
81 » conn serverConn 82 » network string
83 » raddr string
84
85 » mu sync.Mutex // guards conn
86 » conn serverConn
82 } 87 }
83 88
84 type serverConn interface { 89 type serverConn interface {
mikio 2012/12/16 06:54:17 I think this interface is unnecessary unless you w
jeff.allen 2012/12/18 15:18:03 Done.
85 writeString(p Priority, hostname, tag, s string) (int, error) 90 writeString(p Priority, hostname, tag, s string) (int, error)
86 close() error 91 close() error
87 } 92 }
88 93
89 type netConn struct { 94 type netConn struct {
mikio 2012/12/16 06:54:17 ditto.
jeff.allen 2012/12/18 15:18:03 Done.
90 conn net.Conn 95 conn net.Conn
91 } 96 }
92 97
93 // New establishes a new connection to the system log daemon. Each 98 // New establishes a new connection to the system log daemon. Each
94 // write to the returned writer sends a log message with the given 99 // write to the returned writer sends a log message with the given
95 // priority and prefix. 100 // priority and prefix.
96 func New(priority Priority, tag string) (w *Writer, err error) { 101 func New(priority Priority, tag string) (w *Writer, err error) {
97 return Dial("", "", priority, tag) 102 return Dial("", "", priority, tag)
98 } 103 }
99 104
100 // Dial establishes a connection to a log daemon by connecting to 105 // Dial establishes a connection to a log daemon by connecting to
101 // address raddr on the network net. Each write to the returned 106 // address raddr on the network net. Each write to the returned
102 // writer sends a log message with the given facility, severity and 107 // writer sends a log message with the given facility, severity and
103 // tag. 108 // tag.
104 func Dial(network, raddr string, priority Priority, tag string) (w *Writer, err error) { 109 func Dial(network, raddr string, priority Priority, tag string) (*Writer, error) {
105 if priority < 0 || priority > LOG_LOCAL7|LOG_DEBUG { 110 if priority < 0 || priority > LOG_LOCAL7|LOG_DEBUG {
106 return nil, errors.New("log/syslog: invalid priority") 111 return nil, errors.New("log/syslog: invalid priority")
107 } 112 }
108 113
109 if tag == "" { 114 if tag == "" {
110 tag = os.Args[0] 115 tag = os.Args[0]
111 } 116 }
112
113 hostname, _ := os.Hostname() 117 hostname, _ := os.Hostname()
114 118
115 » var conn serverConn 119 » w := &Writer{
116 » if network == "" { 120 » » priority: priority,
117 » » conn, err = unixSyslog() 121 » » tag: tag,
118 » » if hostname == "" { 122 » » hostname: hostname,
119 » » » hostname = "localhost" 123 » » network: network,
124 » » raddr: raddr,
125 » }
126
127 » // w.mu not held, but w is still private to us at this point
128 » err := w.connect()
129 » if err != nil {
130 » » return nil, err
131 » }
132 » return w, err
133 }
134
135 // (*Writer).connect makes a connection to the syslog server.
136 // It must be called with w.mu held.
137 func (w *Writer) connect() (err error) {
138 » if w.conn != nil {
139 » » // ignore err from close, it makes sense to continue anyway
140 » » w.conn.close()
141 » » w.conn = nil
142 » }
143
144 » if w.network == "" {
145 » » w.conn, err = unixSyslog()
146 » » if w.hostname == "" {
147 » » » w.hostname = "localhost"
120 } 148 }
121 } else { 149 } else {
122 var c net.Conn 150 var c net.Conn
123 » » c, err = net.Dial(network, raddr) 151 » » c, err = net.Dial(w.network, w.raddr)
124 » » conn = netConn{c} 152 » » if err == nil {
125 » » if hostname == "" { 153 » » » w.conn = netConn{c}
126 » » » hostname = c.LocalAddr().String() 154 » » » if w.hostname == "" {
155 » » » » w.hostname = c.LocalAddr().String()
156 » » » }
127 } 157 }
128 } 158 }
129 » if err != nil { 159 » return
130 » » return nil, err
131 » }
132
133 » return &Writer{priority: priority, tag: tag, hostname: hostname, conn: c onn}, nil
134 } 160 }
135 161
136 // Write sends a log message to the syslog daemon. 162 // Write sends a log message to the syslog daemon.
137 func (w *Writer) Write(b []byte) (int, error) { 163 func (w *Writer) Write(b []byte) (int, error) {
138 return w.writeString(w.priority, string(b)) 164 return w.writeString(w.priority, string(b))
139 } 165 }
140 166
141 func (w *Writer) Close() error { return w.conn.close() } 167 func (w *Writer) Close() error {
mikio 2012/12/16 06:54:17 Close is exposed so it needs comments.
jeff.allen 2012/12/18 15:18:03 Done.
168 » w.mu.Lock()
169 » defer w.mu.Unlock()
170
171 » if w.conn != nil {
172 » » err := w.conn.close()
173 » » w.conn = nil
174 » » return err
175 » }
176 » return nil
177 }
142 178
143 // Emerg logs a message with severity LOG_EMERG, ignoring the severity 179 // Emerg logs a message with severity LOG_EMERG, ignoring the severity
144 // passed to New. 180 // passed to New.
145 func (w *Writer) Emerg(m string) (err error) { 181 func (w *Writer) Emerg(m string) (err error) {
146 _, err = w.writeString(LOG_EMERG, m) 182 _, err = w.writeString(LOG_EMERG, m)
147 return err 183 return err
148 } 184 }
149 185
150 // Alert logs a message with severity LOG_ALERT, ignoring the severity 186 // Alert logs a message with severity LOG_ALERT, ignoring the severity
151 // passed to New. 187 // passed to New.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 } 226 }
191 227
192 // Debug logs a message with severity LOG_DEBUG, ignoring the severity 228 // Debug logs a message with severity LOG_DEBUG, ignoring the severity
193 // passed to New. 229 // passed to New.
194 func (w *Writer) Debug(m string) (err error) { 230 func (w *Writer) Debug(m string) (err error) {
195 _, err = w.writeString(LOG_DEBUG, m) 231 _, err = w.writeString(LOG_DEBUG, m)
196 return err 232 return err
197 } 233 }
198 234
199 func (w *Writer) writeString(p Priority, s string) (int, error) { 235 func (w *Writer) writeString(p Priority, s string) (int, error) {
200 » return w.conn.writeString((w.priority&facilityMask)|(p&severityMask), 236 » w.mu.Lock()
237 » defer w.mu.Unlock()
238
239 » if w.conn == nil {
mikio 2012/12/16 06:54:17 I'm not keen to manage a conn state with write-onl
jeff.allen 2012/12/18 15:18:03 I think the correct approach to this risk is to re
240 » » err := w.connect()
241 » » if err != nil {
242 » » » return 0, err
243 » » }
244 » }
245 » n, err := w.conn.writeString((w.priority&facilityMask)|(p&severityMask),
201 w.hostname, w.tag, s) 246 w.hostname, w.tag, s)
247 if err != nil {
248 // try once to reconnect, to handle the case where
249 // the unix socket was closed and reopened by a restarting
250 // syslogd.
251 err = w.connect()
252 if err != nil {
253 return 0, err
254 }
255 n, err = w.conn.writeString((w.priority&facilityMask)|(p&severit yMask),
256 w.hostname, w.tag, s)
257 }
258 return n, err
202 } 259 }
203 260
204 // writeString: generates and writes a syslog formatted string. The 261 // writeString: generates and writes a syslog formatted string. The
205 // format is as follows: <PRI>1 TIMESTAMP HOSTNAME TAG[PID]: MSG 262 // format is as follows: <PRI>1 TIMESTAMP HOSTNAME TAG[PID]: MSG
206 func (n netConn) writeString(p Priority, hostname, tag, msg string) (int, error) { 263 func (n netConn) writeString(p Priority, hostname, tag, msg string) (int, error) {
207 nl := "" 264 nl := ""
208 if len(msg) == 0 || msg[len(msg)-1] != '\n' { 265 if len(msg) == 0 || msg[len(msg)-1] != '\n' {
209 nl = "\n" 266 nl = "\n"
210 } 267 }
211 timestamp := time.Now().Format(time.RFC3339) 268 timestamp := time.Now().Format(time.RFC3339)
(...skipping 12 matching lines...) Expand all
224 // the system log service with the specified priority. The logFlag 281 // the system log service with the specified priority. The logFlag
225 // argument is the flag set passed through to log.New to create 282 // argument is the flag set passed through to log.New to create
226 // the Logger. 283 // the Logger.
227 func NewLogger(p Priority, logFlag int) (*log.Logger, error) { 284 func NewLogger(p Priority, logFlag int) (*log.Logger, error) {
228 s, err := New(p, "") 285 s, err := New(p, "")
229 if err != nil { 286 if err != nil {
230 return nil, err 287 return nil, err
231 } 288 }
232 return log.New(s, "", logFlag), nil 289 return log.New(s, "", logFlag), nil
233 } 290 }
OLDNEW
« no previous file with comments | « no previous file | src/pkg/log/syslog/syslog_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b