Properly defaulting the status in log code

This commit is contained in:
Kris 2015-11-03 14:06:51 -08:00
parent 21a75abfbd
commit 05182fc7d5
2 changed files with 56 additions and 11 deletions

View File

@ -53,6 +53,8 @@ type logger interface {
// the http.ResponseWriter. We can recover panics from go-restful, and // the http.ResponseWriter. We can recover panics from go-restful, and
// the logging value is questionable. // the logging value is questionable.
type respLogger struct { type respLogger struct {
hijacked bool
statusRecorded bool
status int status int
statusStack string statusStack string
addedInfo string addedInfo string
@ -155,7 +157,11 @@ func (rl *respLogger) Addf(format string, data ...interface{}) {
func (rl *respLogger) Log() { func (rl *respLogger) Log() {
latency := time.Since(rl.startTime) latency := time.Since(rl.startTime)
if glog.V(2) { if glog.V(2) {
if !rl.hijacked {
glog.InfoDepth(1, fmt.Sprintf("%s %s: (%v) %v%v%v [%s %s]", rl.req.Method, rl.req.RequestURI, latency, rl.status, rl.statusStack, rl.addedInfo, rl.req.Header["User-Agent"], rl.req.RemoteAddr)) glog.InfoDepth(1, fmt.Sprintf("%s %s: (%v) %v%v%v [%s %s]", rl.req.Method, rl.req.RequestURI, latency, rl.status, rl.statusStack, rl.addedInfo, rl.req.Header["User-Agent"], rl.req.RemoteAddr))
} else {
glog.InfoDepth(1, fmt.Sprintf("%s %s: (%v) hijacked [%s %s]", rl.req.Method, rl.req.RequestURI, latency, rl.req.Header["User-Agent"], rl.req.RemoteAddr))
}
} }
} }
@ -166,6 +172,9 @@ func (rl *respLogger) Header() http.Header {
// Write implements http.ResponseWriter. // Write implements http.ResponseWriter.
func (rl *respLogger) Write(b []byte) (int, error) { func (rl *respLogger) Write(b []byte) (int, error) {
if !rl.statusRecorded {
rl.recordStatus(http.StatusOK) // Default if WriteHeader hasn't been called
}
return rl.w.Write(b) return rl.w.Write(b)
} }
@ -181,7 +190,19 @@ func (rl *respLogger) Flush() {
// WriteHeader implements http.ResponseWriter. // WriteHeader implements http.ResponseWriter.
func (rl *respLogger) WriteHeader(status int) { func (rl *respLogger) WriteHeader(status int) {
rl.recordStatus(status)
rl.w.WriteHeader(status)
}
// Hijack implements http.Hijacker.
func (rl *respLogger) Hijack() (net.Conn, *bufio.ReadWriter, error) {
rl.hijacked = true
return rl.w.(http.Hijacker).Hijack()
}
func (rl *respLogger) recordStatus(status int) {
rl.status = status rl.status = status
rl.statusRecorded = true
if rl.logStacktracePred(status) { if rl.logStacktracePred(status) {
// Only log stacks for errors // Only log stacks for errors
stack := make([]byte, 2048) stack := make([]byte, 2048)
@ -190,10 +211,4 @@ func (rl *respLogger) WriteHeader(status int) {
} else { } else {
rl.statusStack = "" rl.statusStack = ""
} }
rl.w.WriteHeader(status)
}
// Hijack implements http.Hijacker.
func (rl *respLogger) Hijack() (net.Conn, *bufio.ReadWriter, error) {
return rl.w.(http.Hijacker).Hijack()
} }

View File

@ -129,3 +129,33 @@ func TestUnlogged(t *testing.T) {
handler(w, req) handler(w, req)
} }
} }
type testResponseWriter struct{}
func (*testResponseWriter) Header() http.Header { return nil }
func (*testResponseWriter) Write([]byte) (int, error) { return 0, nil }
func (*testResponseWriter) WriteHeader(int) {}
func TestLoggedStatus(t *testing.T) {
req, err := http.NewRequest("GET", "http://example.com", nil)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
var tw http.ResponseWriter = new(testResponseWriter)
logger := NewLogged(req, &tw)
logger.Write(nil)
if logger.status != http.StatusOK {
t.Errorf("expected status after write to be %v, got %v", http.StatusOK, logger.status)
}
tw = new(testResponseWriter)
logger = NewLogged(req, &tw)
logger.WriteHeader(http.StatusForbidden)
logger.Write(nil)
if logger.status != http.StatusForbidden {
t.Errorf("expected status after write to remain %v, got %v", http.StatusForbidden, logger.status)
}
}