Skip to content

Instantly share code, notes, and snippets.

@Tantas
Forked from cespare/log.go
Last active September 8, 2021 18:22
Show Gist options
  • Save Tantas/1fc00c5eb7c291e2a34b to your computer and use it in GitHub Desktop.
Save Tantas/1fc00c5eb7c291e2a34b to your computer and use it in GitHub Desktop.

Revisions

  1. Joseph Preiss revised this gist Apr 5, 2015. 1 changed file with 19 additions and 1 deletion.
    20 changes: 19 additions & 1 deletion main.go
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,25 @@
    func main() {
    // Open appending or create the access log.
    accessLogFile, err := os.OpenFile("access.log", os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
    if err != nil {
    log.Fatalf("Error using assess.log: %s", err.Error())
    }
    defer accessLogFile.Close()

    // Create a buffered writer and ensure it is flushed when an interrupt occurs.
    bufferedAccessLogWriter := bufio.NewWriter(accessLogFile)
    c := make(chan os.Signal, 1)
    signal.Notify(c, os.Interrupt)
    go func() {
    <-c
    log.Println("Flushing logs and exiting...")
    bufferedAccessLogWriter.Flush()
    os.Exit(0)
    }()

    mux := http.DefaultServeMux
    mux.HandleFunc("/", indexHandler)
    loggingHandler := NewApacheLoggingHandler(mux, os.Stderr)
    loggingHandler := NewApacheLoggingHandler(mux, bufferedAccessLogWriter)
    server := &http.Server{
    Addr: ":8000",
    Handler: loggingHandler,
  2. Joseph Preiss revised this gist Apr 5, 2015. 2 changed files with 29 additions and 4 deletions.
    29 changes: 27 additions & 2 deletions log.go
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,14 @@
    import (
    "fmt"
    "io"
    "net/http"
    "strings"
    "time"
    )

    // https://httpd.apache.org/docs/2.2/logs.html#combined + execution time.
    const apacheFormatPattern = "%s - - [%s] \"%s %s %s\" %d %d \"%s\" \"%s\" %.4f\n"

    type ApacheLogRecord struct {
    http.ResponseWriter

    @@ -6,13 +17,15 @@ type ApacheLogRecord struct {
    method, uri, protocol string
    status int
    responseBytes int64
    referer string
    userAgent string
    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,
    fmt.Fprintf(out, apacheFormatPattern, r.ip, timeFormatted, r.method,
    r.uri, r.protocol, r.status, r.responseBytes, r.referer, r.userAgent,
    r.elapsedTime.Seconds())
    }

    @@ -45,6 +58,16 @@ func (h *ApacheLoggingHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request
    clientIP = clientIP[:colon]
    }

    referer := r.Referer()
    if referer == "" {
    referer = "-"
    }

    userAgent := r.UserAgent()
    if userAgent == "" {
    userAgent = "-"
    }

    record := &ApacheLogRecord{
    ResponseWriter: rw,
    ip: clientIP,
    @@ -53,6 +76,8 @@ func (h *ApacheLoggingHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request
    uri: r.RequestURI,
    protocol: r.Proto,
    status: http.StatusOK,
    referer: referer,
    userAgent: userAgent,
    elapsedTime: time.Duration(0),
    }

    4 changes: 2 additions & 2 deletions main.go
    Original file line number Diff line number Diff line change
    @@ -3,8 +3,8 @@ func main() {
    mux.HandleFunc("/", indexHandler)
    loggingHandler := NewApacheLoggingHandler(mux, os.Stderr)
    server := &http.Server{
    Addr: fmt.Sprintf(":%s", 2345),
    Addr: ":8000",
    Handler: loggingHandler,
    }
    server.ListenAndServe()
    }
    }
  3. @cespare 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()
    }
  4. @cespare 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)
    }