forked from fabiolb/fabio
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlogger.go
144 lines (125 loc) · 4.7 KB
/
logger.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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// Package logger implements a configurable access logger.
//
// The access log format is defined through a format string which expands to a
// log line per request. The values are taken as is and no quoting or escaping
// takes place. Text between two fields is printed verbatim. See the common
// log file formats for an example.
//
// $header.<name> - request http header (name: [a-zA-Z0-9-]+)
// $remote_addr - host:port of remote client
// $remote_host - host of remote client
// $remote_port - port of remote client
// $request - request <method> <uri> <proto>
// $request_args - request query parameters
// $request_host - request host header (aka server name)
// $request_method - request method
// $request_scheme - request scheme
// $request_uri - request URI
// $request_url - request URL
// $request_proto - request protocol
// $response_body_size - response body size in bytes
// $response_status - response status code
// $response_time_ms - response time in S.sss format
// $response_time_us - response time in S.ssssss format
// $response_time_ns - response time in S.sssssssss format
// $time_rfc3339 - log timestamp in YYYY-MM-DDTHH:MM:SSZ format
// $time_rfc3339_ms - log timestamp in YYYY-MM-DDTHH:MM:SS.sssZ format
// $time_rfc3339_us - log timestamp in YYYY-MM-DDTHH:MM:SS.ssssssZ format
// $time_rfc3339_ns - log timestamp in YYYY-MM-DDTHH:MM:SS.sssssssssZ format
// $time_unix_ms - log timestamp in unix epoch ms
// $time_unix_us - log timestamp in unix epoch us
// $time_unix_ns - log timestamp in unix epoch ns
// $time_common - log timestamp in DD/MMM/YYYY:HH:MM:SS -ZZZZ
// $upstream_addr - host:port of upstream server
// $upstream_host - host of upstream server
// $upstream_port - port of upstream server
// $upstream_request_scheme - upstream request scheme
// $upstream_request_uri - upstream request URI
// $upstream_request_url - upstream request URL
//
package logger
import (
"bytes"
"errors"
"io"
"net/http"
"net/url"
"sync"
"time"
)
// Common log file formats.
const (
CommonFormat = `$remote_host - - [$time_common] "$request" $response_status $response_body_size`
CombinedFormat = `$remote_host - - [$time_common] "$request" $response_status $response_body_size "$header.Referer" "$header.User-Agent"`
)
// Event defines the elements of a loggable event.
type Event struct {
// Start is the time when the action that triggered the event started.
Start time.Time
// End is the time when the action that triggered the event was completed.
End time.Time
// Request is the HTTP request that is connected to this event.
// It should only be set for HTTP log events.
Request *http.Request
// Response is the HTTP response which is connected to this event.
// It should only be set for HTTP log events.
Response *http.Response
// RequestURL is the URL of the incoming HTTP request.
// It should only be set for HTTP log events.
RequestURL *url.URL
// UpstreamAddr is the TCP address in the form of "host:port" of the
// upstream server which handled the proxied request.
UpstreamAddr string
// UpstreamService is the name of the upstream service as
// defined in the route.
UpstreamService string
// UpstreamURL is the URL which was sent to the upstream server.
// It should only be set for HTTP log events.
UpstreamURL *url.URL
}
// Logger logs an event.
type Logger interface {
Log(*Event)
}
// New creates a new logger that writes log events in the given format to the
// provided writer. If no writer was provided no log output is generated.
// If the format is empty or invalid an error is returned.
func New(w io.Writer, format string) (Logger, error) {
if w == nil {
return &noopLogger{}, nil
}
p, err := parse(format, fields)
if err != nil {
return nil, err
}
if len(p) == 0 {
return nil, errors.New("empty log format")
}
return &logger{p: p, w: w}, nil
}
type noopLogger struct{}
func (l *noopLogger) Log(*Event) {}
type logger struct {
p pattern
mu sync.Mutex
w io.Writer
}
// bufSize defines the default size of the log buffers.
const bufSize = 1024
// pool provides a reusable set of log buffers.
var pool = sync.Pool{
New: func() interface{} {
return bytes.NewBuffer(make([]byte, 0, bufSize))
},
}
// Log writes a log line for the request that was executed
// between t1 and t2.
func (l *logger) Log(e *Event) {
b := pool.Get().(*bytes.Buffer)
b.Reset()
l.p.write(b, e)
l.mu.Lock()
l.w.Write(b.Bytes())
l.mu.Unlock()
pool.Put(b)
}