Last active
January 10, 2017 23:02
-
-
Save karrick/b9dd40dbee34695491a0c30f76f09cb6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ErrorLogHandler returns a new http.Handler that logs HTTP requests that result in response | |
// errors. The handler will output lines in common log format to the specified io.Writer. | |
func ErrorLogHandler(next http.Handler, out io.Writer) http.Handler { | |
const apacheLogFormat = "%s [%s] \"%s\" %d %d %f\n" | |
const timeFormat = "02/Jan/2006:15:04:05 MST" | |
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
lrw := &loggedResponseWriter{ | |
ResponseWriter: w, | |
status: http.StatusOK, | |
} | |
begin := time.Now() | |
next.ServeHTTP(lrw, r) | |
if lrw.status != http.StatusOK { | |
end := time.Now() | |
clientIP := r.RemoteAddr | |
if colon := strings.LastIndex(clientIP, ":"); colon != -1 { | |
clientIP = clientIP[:colon] | |
} | |
request := fmt.Sprintf("%s %s %s", r.Method, r.RequestURI, r.Proto) | |
duration := end.Sub(begin).Seconds() | |
formattedTime := end.UTC().Format(timeFormat) | |
fmt.Fprintf(out, apacheLogFormat, clientIP, formattedTime, request, lrw.status, lrw.responseBytes, duration) | |
} | |
}) | |
} | |
// LogHandler returns a new http.Handler that logs HTTP requests and responses in common log format | |
// to the specified io.Writer. | |
func LogHandler(next http.Handler, out io.Writer) http.Handler { | |
const apacheLogFormat = "%s [%s] \"%s\" %d %d %f\n" | |
const timeFormat = "02/Jan/2006:15:04:05 MST" | |
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
lrw := &loggedResponseWriter{ | |
ResponseWriter: w, | |
status: http.StatusOK, | |
} | |
begin := time.Now() | |
next.ServeHTTP(lrw, r) | |
end := time.Now() | |
clientIP := r.RemoteAddr | |
if colon := strings.LastIndex(clientIP, ":"); colon != -1 { | |
clientIP = clientIP[:colon] | |
} | |
request := fmt.Sprintf("%s %s %s", r.Method, r.RequestURI, r.Proto) | |
duration := end.Sub(begin).Seconds() | |
formattedTime := end.UTC().Format(timeFormat) | |
fmt.Fprintf(out, apacheLogFormat, clientIP, formattedTime, request, lrw.status, lrw.responseBytes, duration) | |
}) | |
} | |
type loggedResponseWriter struct { | |
http.ResponseWriter | |
responseBytes int64 | |
status int | |
} | |
func (r *loggedResponseWriter) Write(p []byte) (int, error) { | |
written, err := r.ResponseWriter.Write(p) | |
r.responseBytes += int64(written) | |
return written, err | |
} | |
func (r *loggedResponseWriter) WriteHeader(status int) { | |
r.status = status | |
r.ResponseWriter.WriteHeader(status) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment