Create passthroughLogger when LogOf is called and request has no logger

pull/6/head
Jessica Forrester 2014-09-11 16:48:06 -04:00
parent d82cf7dd48
commit 0f2b8f4f9f
3 changed files with 28 additions and 11 deletions

View File

@ -133,18 +133,18 @@ func (self *WatchServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
cn, ok := w.(http.CloseNotifier)
if !ok {
loggedW.Addf("unable to get CloseNotifier")
http.NotFound(loggedW, req)
http.NotFound(w, req)
return
}
flusher, ok := w.(http.Flusher)
if !ok {
loggedW.Addf("unable to get Flusher")
http.NotFound(loggedW, req)
http.NotFound(w, req)
return
}
loggedW.Header().Set("Transfer-Encoding", "chunked")
loggedW.WriteHeader(http.StatusOK)
w.Header().Set("Transfer-Encoding", "chunked")
w.WriteHeader(http.StatusOK)
flusher.Flush()
encoder := json.NewEncoder(w)

View File

@ -40,6 +40,10 @@ func Handler(delegate http.Handler, pred StacktracePred) http.Handler {
// StacktracePred returns true if a stacktrace should be logged for this status.
type StacktracePred func(httpStatus int) (logStacktrace bool)
type logger interface {
Addf(format string, data ...interface{})
}
// Add a layer on top of ResponseWriter, so we can track latency and error
// message sources.
type respLogger struct {
@ -54,6 +58,14 @@ type respLogger struct {
logStacktracePred StacktracePred
}
// Simple logger that logs immediately when Addf is called
type passthroughLogger struct{}
// Addf logs info immediately.
func (passthroughLogger) Addf(format string, data ...interface{}) {
glog.Infof(format, data...)
}
// DefaultStacktracePred is the default implementation of StacktracePred.
func DefaultStacktracePred(status int) bool {
return status < http.StatusOK || status >= http.StatusBadRequest
@ -87,11 +99,12 @@ func NewLogged(req *http.Request, w *http.ResponseWriter) *respLogger {
}
// LogOf returns the logger hiding in w. If there is not an existing logger
// then one will be created because NewLogged() must have been previously
// called for the log to work.
func LogOf(req *http.Request, w http.ResponseWriter) *respLogger {
// then a passthroughLogger will be created which will log to stdout immediately
// when Addf is called.
func LogOf(req *http.Request, w http.ResponseWriter) logger {
if _, exists := w.(*respLogger); !exists {
NewLogged(req, &w)
pl := &passthroughLogger{}
return pl
}
if rl, ok := w.(*respLogger); ok {
return rl

View File

@ -91,12 +91,16 @@ func TestLogOf(t *testing.T) {
t.Errorf("Unexpected error: %v", err)
}
handler := func(w http.ResponseWriter, r *http.Request) {
var want string
if makeLogger {
NewLogged(req, &w)
want = "*httplog.respLogger"
} else {
want = "*httplog.passthroughLogger"
}
got := reflect.TypeOf(*LogOf(r, w)).String()
if got != "httplog.respLogger" {
t.Errorf("Expected %v, got %v", "httplog.respLogger", got)
got := reflect.TypeOf(LogOf(r, w)).String()
if want != got {
t.Errorf("Expected %v, got %v", want, got)
}
}
w := httptest.NewRecorder()