Skip to content

Instantly share code, notes, and snippets.

@cespare
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.

Revisions

  1. cespare revised this gist Oct 31, 2012. 1 changed file with 10 additions and 0 deletions.
    10 changes: 10 additions & 0 deletions main.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,10 @@
    func main() {
    mux := http.DefaultServeMux
    mux.HandleFunc("/", indexHandler)
    loggingHandler := NewApacheLoggingHandler(mux, os.Stderr)
    server := &http.Server{
    Addr: fmt.Sprintf(":%s", 2345),
    Handler: loggingHandler,
    }
    server.ListenAndServe()
    }
  2. cespare created this gist Oct 31, 2012.
    67 changes: 67 additions & 0 deletions log.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,67 @@
    type ApacheLogRecord struct {
    http.ResponseWriter

    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,
    r.elapsedTime.Seconds())
    }

    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
    r.ResponseWriter.WriteHeader(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)

    record.Log(h.out)
    }