perkeep/website/logging.go

96 lines
1.8 KiB
Go

package main
import (
"bufio"
"fmt"
"io"
"os"
"http"
"time"
)
type logRecord struct {
timeEpochNs int64
ip, method, rawpath string
responseBytes int64
responseStatus int
userAgent, referer string
rw http.ResponseWriter
}
type logHandler struct {
ch chan *logRecord
dir string
handler http.Handler
}
func NewLoggingHandler(handler http.Handler, dir string) http.Handler {
h := &logHandler{
ch: make(chan *logRecord),
dir: dir,
handler: handler,
}
go h.logFromChannel()
return h
}
func (h *logHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
lr := &logRecord{
timeEpochNs: time.Nanoseconds(),
ip: rw.RemoteAddr(),
method: r.Method,
rawpath: r.URL.RawPath,
userAgent: r.UserAgent,
referer: r.Referer,
responseStatus: http.StatusOK,
rw: rw,
}
h.handler.ServeHTTP(lr, r)
h.ch <- lr
}
func (h *logHandler) logFromChannel() {
for {
lr := <-h.ch
lr.rw = nil
logLine := fmt.Sprintf("Request: %#v\n", lr)
if h.dir == "-" {
os.Stdout.WriteString(logLine)
}
}
}
func (lr *logRecord) Write(p []byte) (int, os.Error) {
written, err := lr.rw.Write(p)
lr.responseBytes += int64(written)
return written, err
}
func (lr *logRecord) WriteHeader(status int) {
lr.responseStatus = status
lr.rw.WriteHeader(status)
}
// Boring proxies: (seems like I should be able to use embedding somehow...)
func (lr *logRecord) RemoteAddr() string {
return lr.rw.RemoteAddr()
}
func (lr *logRecord) UsingTLS() bool {
return lr.rw.UsingTLS()
}
func (lr *logRecord) SetHeader(k, v string) {
lr.rw.SetHeader(k, v)
}
func (lr *logRecord) Flush() {
lr.rw.Flush()
}
func (lr *logRecord) Hijack() (io.ReadWriteCloser, *bufio.ReadWriter, os.Error) {
return lr.rw.Hijack()
}