-
Notifications
You must be signed in to change notification settings - Fork 13
/
log.go
91 lines (77 loc) · 1.69 KB
/
log.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package main
import (
"bufio"
"fmt"
"io"
"io/ioutil"
"log"
"net"
"net/http"
"time"
)
type LoggingMiddleware struct {
http.Handler
}
type ResponseRecorder struct {
ResponseWriter http.ResponseWriter
response int
*WriteCounter
}
func NewResponseRecorder(w http.ResponseWriter) *ResponseRecorder {
return &ResponseRecorder{w, 0, &WriteCounter{w, 0}}
}
func (r *ResponseRecorder) Header() http.Header {
return r.ResponseWriter.Header()
}
func (r *ResponseRecorder) WriteHeader(n int) {
r.ResponseWriter.WriteHeader(n)
r.response = n
}
func (r *ResponseRecorder) Hijack() (net.Conn, *bufio.ReadWriter, error) {
hijacker, ok := r.ResponseWriter.(http.Hijacker)
if !ok {
return nil, nil, fmt.Errorf("Not a Hijacker: %T", r.ResponseWriter)
}
return hijacker.Hijack()
}
func (r *ResponseRecorder) Flush() {
flusher, ok := r.ResponseWriter.(http.Flusher)
if !ok {
return
}
flusher.Flush()
}
type WriteCounter struct {
io.Writer
nBytes int
}
func (r *WriteCounter) Write(bs []byte) (n int, err error) {
if r.Writer != nil {
n, err = r.Writer.Write(bs)
} else {
n = len(bs)
}
r.nBytes += n
return n, err
}
func (x *LoggingMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
recorder := NewResponseRecorder(w)
uploaded := &WriteCounter{Writer: ioutil.Discard}
r.Body = struct {
io.Reader
io.Closer
}{io.TeeReader(r.Body, uploaded), r.Body}
start := time.Now()
x.Handler.ServeHTTP(recorder, r)
duration := time.Since(start)
log.Printf("%21v %3d %10d %10d %7.1fms %4v %v%-30v %v",
r.RemoteAddr,
recorder.response,
uploaded.nBytes,
recorder.nBytes,
duration.Seconds()*1000,
r.Method,
r.URL.Host,
r.URL.EscapedPath(),
r.Header.Get("User-Agent"))
}