...
1 package httpsnoop
2
3 import (
4 "io"
5 "net/http"
6 "time"
7 )
8
9
10 type Metrics struct {
11
12
13
14 Code int
15
16 Duration time.Duration
17
18
19
20
21
22 Written int64
23 }
24
25
26
27 func CaptureMetrics(hnd http.Handler, w http.ResponseWriter, r *http.Request) Metrics {
28 return CaptureMetricsFn(w, func(ww http.ResponseWriter) {
29 hnd.ServeHTTP(ww, r)
30 })
31 }
32
33
34
35
36
37 func CaptureMetricsFn(w http.ResponseWriter, fn func(http.ResponseWriter)) Metrics {
38 m := Metrics{Code: http.StatusOK}
39 m.CaptureMetrics(w, fn)
40 return m
41 }
42
43
44
45
46 func (m *Metrics) CaptureMetrics(w http.ResponseWriter, fn func(http.ResponseWriter)) {
47 var (
48 start = time.Now()
49 headerWritten bool
50 hooks = Hooks{
51 WriteHeader: func(next WriteHeaderFunc) WriteHeaderFunc {
52 return func(code int) {
53 next(code)
54
55 if !(code >= 100 && code <= 199) && !headerWritten {
56 m.Code = code
57 headerWritten = true
58 }
59 }
60 },
61
62 Write: func(next WriteFunc) WriteFunc {
63 return func(p []byte) (int, error) {
64 n, err := next(p)
65
66 m.Written += int64(n)
67 headerWritten = true
68 return n, err
69 }
70 },
71
72 ReadFrom: func(next ReadFromFunc) ReadFromFunc {
73 return func(src io.Reader) (int64, error) {
74 n, err := next(src)
75
76 headerWritten = true
77 m.Written += n
78 return n, err
79 }
80 },
81 }
82 )
83
84 fn(Wrap(w, hooks))
85 m.Duration += time.Since(start)
86 }
87
View as plain text