Skip to content

Commit 2319e61

Browse files
committed
Add NewLine and Timestamp options
NewLine will append N lines to the end of the completed logger output. Timestamp will append a timestamp at the Started output. Also updated README to reflect changes.
1 parent ce7c813 commit 2319e61

File tree

3 files changed

+127
-5
lines changed

3 files changed

+127
-5
lines changed

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,34 @@ The output can directly sent to `log.Logger` or to a map[string]string with the
1515
go get -u github.com/aaronvb/logrequest
1616
```
1717

18+
## Options
19+
There are two optional options you can pass to the `LogRequest` struct:
20+
21+
`NewLine` (integer) - This will append N lines at the end of the log output. Note: This only works with logger output.
22+
23+
Example:
24+
```go
25+
lr := logrequest.LogRequest{Request: r, Writer: w, Handler: next, NewLine: 2}
26+
```
27+
```
28+
Started GET "/" 127.0.0.1:12345 HTTP/1.1
29+
Completed 200 in 3.7455ms
30+
31+
32+
Started GET "/home" 127.0.0.1:12345 HTTP/1.1
33+
Completed 200 in 1.891ms
34+
```
35+
36+
`Timestamp` (boolean) - This will add a timestamp at the beginning of the request.
37+
38+
Example:
39+
```go
40+
lr := logrequest.LogRequest{Request: r, Writer: w, Handler: next, Timestamp: true}
41+
```
42+
```
43+
Started GET "/home" 1.1.1.1:1234 HTTP/1.1 at 2020-05-13 02:25:33
44+
```
45+
1846
## Middleware Example (using [gorilla/mux](https://github.com/gorilla/mux))
1947
```go
2048
package main

logrequest.go

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ import (
1010
// LogRequest struct
1111
// Pass values from middleware to this struct
1212
type LogRequest struct {
13-
Writer http.ResponseWriter
14-
Request *http.Request
15-
Handler http.Handler
13+
Writer http.ResponseWriter
14+
Request *http.Request
15+
Handler http.Handler
16+
NewLine int
17+
Timestamp bool
1618
}
1719

1820
type statusWriter struct {
@@ -22,17 +24,34 @@ type statusWriter struct {
2224

2325
// ToLogger will print the Started and Completed request info to the passed logger
2426
func (lr LogRequest) ToLogger(logger *log.Logger) {
25-
logger.Printf(`Started %s "%s" %s %s`, lr.Request.Method, lr.Request.URL.RequestURI(), lr.Request.RemoteAddr, lr.Request.Proto)
27+
if lr.Timestamp == true {
28+
logger.Printf(`Started %s "%s" %s %s at %s`, lr.Request.Method, lr.Request.URL.RequestURI(), lr.Request.RemoteAddr, lr.Request.Proto, time.Now().Format("2006-01-02 15:04:05"))
29+
} else {
30+
logger.Printf(`Started %s "%s" %s %s`, lr.Request.Method, lr.Request.URL.RequestURI(), lr.Request.RemoteAddr, lr.Request.Proto)
31+
}
32+
2633
sw, completedDuration := lr.parseRequest()
2734
logger.Printf("Completed %d in %s", sw.statusCode, completedDuration)
35+
36+
if lr.NewLine > 0 {
37+
for i := 1; i <= lr.NewLine; i++ {
38+
logger.Println("\t")
39+
}
40+
}
2841
}
2942

3043
// ToString will return a map with the key 'started' and 'completed' that contain
3144
// a string output for eacch
3245
func (lr LogRequest) ToString() map[string]string {
3346
sw, completedDuration := lr.parseRequest()
3447
ts := make(map[string]string)
35-
ts["started"] = fmt.Sprintf(`Started %s "%s" %s %s`, lr.Request.Method, lr.Request.URL.RequestURI(), lr.Request.RemoteAddr, lr.Request.Proto)
48+
49+
if lr.Timestamp == true {
50+
ts["started"] = fmt.Sprintf(`Started %s "%s" %s %s at %s`, lr.Request.Method, lr.Request.URL.RequestURI(), lr.Request.RemoteAddr, lr.Request.Proto, time.Now().Format("2006-01-02 15:04:05"))
51+
} else {
52+
ts["started"] = fmt.Sprintf(`Started %s "%s" %s %s`, lr.Request.Method, lr.Request.URL.RequestURI(), lr.Request.RemoteAddr, lr.Request.Proto)
53+
}
54+
3655
ts["completed"] = fmt.Sprintf("Completed %d in %s", sw.statusCode, completedDuration)
3756

3857
return ts

logrequest_test.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"net/http/httptest"
99
"strings"
1010
"testing"
11+
"time"
1112
)
1213

1314
func TestToLogger(t *testing.T) {
@@ -56,6 +57,38 @@ func TestToLogger(t *testing.T) {
5657
}
5758
}
5859

60+
func TestToLoggerWithOptionals(t *testing.T) {
61+
var str bytes.Buffer
62+
var logger = log.Logger{}
63+
logger.SetOutput(&str)
64+
65+
app := &application{
66+
infoLog: &logger,
67+
}
68+
req, err := http.NewRequest(http.MethodGet, "/foo", nil)
69+
if err != nil {
70+
t.Fatal(err)
71+
}
72+
73+
testHandler := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
74+
rw.WriteHeader(http.StatusOK)
75+
})
76+
77+
rr := httptest.NewRecorder()
78+
handler := app.logRequestToLoggerWithOptionals(testHandler)
79+
handler.ServeHTTP(rr, req)
80+
81+
expectedStartedResults := fmt.Sprintf(`at %s`, time.Now().Format("2006-01-02 15:04:05"))
82+
if strings.Contains(str.String(), expectedStartedResults) == false {
83+
t.Errorf("Expected output was incorrect, %s does not contain %s", str.String(), expectedStartedResults)
84+
}
85+
86+
expectedCompletedResults := fmt.Sprintln("\t")
87+
if strings.Contains(str.String(), expectedCompletedResults) == false {
88+
t.Errorf("Expected output was incorrect, %s does not contain new line", str.String())
89+
}
90+
}
91+
5992
func TestToString(t *testing.T) {
6093
tables := []struct {
6194
statusCode int
@@ -102,6 +135,33 @@ func TestToString(t *testing.T) {
102135
}
103136
}
104137

138+
func TestToStringWithOptionals(t *testing.T) {
139+
var str bytes.Buffer
140+
var logger = log.Logger{}
141+
logger.SetOutput(&str)
142+
143+
app := &application{
144+
infoLog: &logger,
145+
}
146+
req, err := http.NewRequest(http.MethodGet, "/foo", nil)
147+
if err != nil {
148+
t.Fatal(err)
149+
}
150+
151+
testHandler := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
152+
rw.WriteHeader(http.StatusOK)
153+
})
154+
155+
rr := httptest.NewRecorder()
156+
handler := app.logRequestToStringWithOptionals(testHandler)
157+
handler.ServeHTTP(rr, req)
158+
159+
expectedStartedResults := fmt.Sprintf(`at %s`, time.Now().Format("2006-01-02 15:04:05"))
160+
if strings.Contains(str.String(), expectedStartedResults) == false {
161+
t.Errorf("Expected output was incorrect, %s does not contain %s", str.String(), expectedStartedResults)
162+
}
163+
}
164+
105165
// Helpers
106166

107167
type application struct {
@@ -122,3 +182,18 @@ func (app *application) logRequestToString(next http.Handler) http.Handler {
122182
app.infoLog.Println(lr.ToString()["completed"])
123183
})
124184
}
185+
186+
func (app *application) logRequestToLoggerWithOptionals(next http.Handler) http.Handler {
187+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
188+
lr := LogRequest{Request: r, Writer: w, Handler: next, NewLine: 1, Timestamp: true}
189+
lr.ToLogger(app.infoLog)
190+
})
191+
}
192+
193+
func (app *application) logRequestToStringWithOptionals(next http.Handler) http.Handler {
194+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
195+
lr := LogRequest{Request: r, Writer: w, Handler: next, Timestamp: true}
196+
app.infoLog.Println(lr.ToString()["started"])
197+
app.infoLog.Println(lr.ToString()["completed"])
198+
})
199+
}

0 commit comments

Comments
 (0)