...
1
2
3
4
5
6
7
8
9
10
11
12
13
14 package logger
15
16 import (
17 "fmt"
18 "io"
19 "net/http"
20 "os"
21 "strings"
22 "time"
23 )
24
25
26 type RequestLogger interface {
27 Log(req *http.Request, status int, fields Fields)
28 }
29
30
31 const (
32 FieldUsername = "username"
33 FieldTimestamp = "timestamp"
34 FieldElapsedTime = "elapsed"
35 FieldResponseSize = "size"
36 )
37
38
39 type Fields map[string]interface{}
40
41
42 func (f Fields) Exists(key string) bool {
43 _, ok := f[key]
44 return ok
45 }
46
47
48 func (f Fields) Get(key string) interface{} {
49 return f[key]
50 }
51
52
53 func (f Fields) GetString(key string) string {
54 v, ok := f[key].(string)
55 if ok {
56 return v
57 }
58 return "-"
59 }
60
61
62 func (f Fields) GetDuration(key string) time.Duration {
63 v, _ := f[key].(time.Duration)
64 return v
65 }
66
67
68 func (f Fields) GetTime(key string) time.Time {
69 v, _ := f[key].(time.Time)
70 return v
71 }
72
73
74 func (f Fields) GetInt(key string) int {
75 v, _ := f[key].(int)
76 return v
77 }
78
79 type logger struct {
80 w io.Writer
81 }
82
83 var _ RequestLogger = &logger{}
84
85
86 func New(w io.Writer) RequestLogger {
87 return &logger{w}
88 }
89
90
91 var DefaultLogger = New(os.Stderr)
92
93 func (l *logger) Log(req *http.Request, status int, fields Fields) {
94 _, _ = fmt.Fprintf(l.w, `%s %s [%s] (%s) "%s %s %s" %d %d "%s" "%s"%c`,
95 req.RemoteAddr[0:strings.LastIndex(req.RemoteAddr, ":")],
96 fields.GetString(FieldUsername),
97 fields.GetTime(FieldTimestamp).Format("2006-01-02 15:04:05Z07:00"),
98 fields.GetDuration(FieldElapsedTime).String(),
99 req.Method,
100 req.URL.String(),
101 req.Proto,
102 status,
103 fields.GetInt(FieldResponseSize),
104 req.Header.Get("Referer"),
105 req.Header.Get("User-Agent"),
106 '\n',
107 )
108 }
109
View as plain text