Skip to content

Instantly share code, notes, and snippets.

Created October 31, 2012 06:51
Show Gist options
  • Save cespare/3985516 to your computer and use it in GitHub Desktop.
Save cespare/3985516 to your computer and use it in GitHub Desktop.
Golang apache logging
type ApacheLogRecord struct {
ip string
time time.Time
method, uri, protocol string
status int
responseBytes int64
elapsedTime time.Duration
func (r *ApacheLogRecord) Log(out io.Writer) {
timeFormatted := r.time.Format("02/Jan/2006 03:04:05")
requestLine := fmt.Sprintf("%s %s %s", r.method, r.uri, r.protocol)
fmt.Fprintf(out, ApacheFormatPattern, r.ip, timeFormatted, requestLine, r.status, r.responseBytes,
func (r *ApacheLogRecord) Write(p []byte) (int, error) {
written, err := r.ResponseWriter.Write(p)
r.responseBytes += int64(written)
return written, err
func (r *ApacheLogRecord) WriteHeader(status int) {
r.status = status
type ApacheLoggingHandler struct {
handler http.Handler
out io.Writer
func NewApacheLoggingHandler(handler http.Handler, out io.Writer) http.Handler {
return &ApacheLoggingHandler{
handler: handler,
out: out,
func (h *ApacheLoggingHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
clientIP := r.RemoteAddr
if colon := strings.LastIndex(clientIP, ":"); colon != -1 {
clientIP = clientIP[:colon]
record := &ApacheLogRecord{
ResponseWriter: rw,
ip: clientIP,
time: time.Time{},
method: r.Method,
uri: r.RequestURI,
protocol: r.Proto,
status: http.StatusOK,
elapsedTime: time.Duration(0),
startTime := time.Now()
h.handler.ServeHTTP(record, r)
finishTime := time.Now()
record.time = finishTime.UTC()
record.elapsedTime = finishTime.Sub(startTime)
func main() {
mux := http.DefaultServeMux
mux.HandleFunc("/", indexHandler)
loggingHandler := NewApacheLoggingHandler(mux, os.Stderr)
server := &http.Server{
Addr: fmt.Sprintf(":%s", 2345),
Handler: loggingHandler,
Copy link

Great code!

Copy link

jeanbza commented Apr 26, 2014

ApacheFormatPattern is not defined in this code. Could you clarify?

edit: I found it in another of your repos: const apacheFormatPattern = "%s - - [%s] "%s %s %s" %d %d %.4f\n"

edit edit: If anyone is interested in seeing this in the gorilla mux framework, i've used the above idea over at

Copy link

cevaris commented Mar 8, 2015

This seems to be the proper ApacheFormatPattern for this code

const (
    ApacheFormatPattern = "%s - - [%s] \"%s %d %d\" %f\n"

Copy link

Hey. This implementation's AWESOME! What's the license for this code snippet in case I want to derive and use it in my code? Some form of CC? MIT? BSD? WTFPL?

Copy link

maugre commented May 30, 2016

Also curious about the license. I've copied a derivative[1], modified slightly to suit my needs and added a Negroni middleware to the package. I want to share that package, but depends on the license.


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment