-
Notifications
You must be signed in to change notification settings - Fork 1
/
report_test.go
183 lines (147 loc) · 5.93 KB
/
report_test.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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package report_test
import (
"bytes"
"errors"
"fmt"
"testing"
"time"
"github.com/robtuley/report"
"go.uber.org/goleak"
)
func TestLoggerDoesNotLeakRoutines(t *testing.T) {
defer goleak.VerifyNoLeaks(t)
log := report.New("test")
log.Export(report.StdOutJSON())
log.Info("http.response", report.Data{"status": 200, "request": "/page1"})
log.Action("json.unparseable", report.Data{})
log.RuntimeEvery(time.Second)
log.Close()
// note that the Honeycomb exporter relies on a global state Init() and Close()
// and on testing seems to leak goroutines but is an external constraint so
// not included in this test
}
func Example() {
// setup logging output
log := report.New("example")
log.Baggage("timestamp", "2017-05-20T21:00:24.2+01:00") // to make output deterministic
log.Export(report.StdOutJSON())
defer log.Close()
// ticker daemon execution
log.Info("example.start", report.Data{})
seq := 0
for i := 0; i < 3; i++ {
log.Info("example.tick", report.Data{"sequence": seq})
seq = seq + 1
}
log.Info("example.stop", report.Data{})
// validate
if log.Count("example.tick") != 3 {
// your own log validation...
fmt.Print("Ooops! example.tick should be 3")
}
if err := log.Err(); err != nil {
// your own log validation...
fmt.Print(err)
}
// Output:
// {"name":"example.start","service_name":"example","timestamp":"2017-05-20T21:00:24.2+01:00","type":"info"}
// {"name":"example.tick","sequence":0,"service_name":"example","timestamp":"2017-05-20T21:00:24.2+01:00","type":"info"}
// {"name":"example.tick","sequence":1,"service_name":"example","timestamp":"2017-05-20T21:00:24.2+01:00","type":"info"}
// {"name":"example.tick","sequence":2,"service_name":"example","timestamp":"2017-05-20T21:00:24.2+01:00","type":"info"}
// {"name":"example.stop","service_name":"example","timestamp":"2017-05-20T21:00:24.2+01:00","type":"info"}
}
func ExampleLogger_Info() {
// setup logging output
log := report.New("example")
log.Baggage("timestamp", "2017-05-20T21:00:24.2+01:00") // to make output deterministic
log.Export(report.StdOutJSON())
defer log.Close()
// normal usage is simple to call log.Info
log.Info("http.response", report.Data{"status": 200, "request": "/page1"})
log.Info("http.response", report.Data{"status": 200, "request": "/page2"})
// if you want to block until the logline is written, consume from the returned channel
<-log.Info("http.response", report.Data{"status": 404, "request": "/nopage"})
if err := log.Err(); err != nil {
fmt.Print(err)
}
// Output:
// {"name":"http.response","request":"/page1","service_name":"example","status":200,"timestamp":"2017-05-20T21:00:24.2+01:00","type":"info"}
// {"name":"http.response","request":"/page2","service_name":"example","status":200,"timestamp":"2017-05-20T21:00:24.2+01:00","type":"info"}
// {"name":"http.response","request":"/nopage","service_name":"example","status":404,"timestamp":"2017-05-20T21:00:24.2+01:00","type":"info"}
}
func ExampleLogger_Action() {
// setup logging output
log := report.New("example")
log.Baggage("timestamp", "2017-05-20T21:00:24.2+01:00") // to make output deterministic
log.Export(report.StdOutJSON())
defer log.Close()
// for example we get an error...
err := errors.New("Failed to parse JSON")
// normal usage is simple to call log.Action
log.Action("json.unparseable", report.Data{"error": err.Error()})
// if you want to block until the logline is written, consume from the returned channel
// (useful if you intend to shutdown as a result of this error)
<-log.Action("json.unparseable", report.Data{"error": err.Error()})
// LastError can be used to validate if an actionable event was logged
if err := log.Err(); err != nil {
fmt.Println(err.Error())
}
// Output:
// {"error":"Failed to parse JSON","name":"json.unparseable","service_name":"example","timestamp":"2017-05-20T21:00:24.2+01:00","type":"action"}
// {"error":"Failed to parse JSON","name":"json.unparseable","service_name":"example","timestamp":"2017-05-20T21:00:24.2+01:00","type":"action"}
// Actionable event: json.unparseable
}
func ExampleLogger_Count() {
log := report.New("example")
defer log.Close()
log.Info("http.response.200", report.Data{})
log.Info("http.response.404", report.Data{})
log.Info("http.response.200", report.Data{})
fmt.Printf("404 response count is %d", log.Count("http.response.404"))
if err := log.Err(); err != nil {
fmt.Print(err)
}
// Output:
// 404 response count is 1
}
func ExampleLogger_Err() {
log := report.New("example")
log.Export(report.StdOutJSON())
defer log.Close()
// this log line has errored, but to prevent error handling clutter
// the library interface requires you need to check error states
// separately using Logger.LastError()
<-log.Info("encoding.fail", report.Data{
"unencodeable": make(chan int),
})
// check whether there has been any logging errors
if err := log.Err(); err != nil {
fmt.Println(err.Error())
}
// Output:
// Error sending encoding.fail: json: unsupported type: chan int
}
func ExampleLogger_Export() {
// want to write to 2 logfiles, represented here as 2 buffers
b1 := &bytes.Buffer{}
b2 := &bytes.Buffer{}
// setup logging output
log := report.New("example")
log.Baggage("timestamp", "2017-05-20T21:00:24.2+01:00") // to make output deterministic
defer log.Close()
// configure 2 writers
log.Export(report.JSON(b1))
log.Export(report.JSON(b2))
// log something
<-log.Info("http.response", report.Data{"status": 404, "request": "/nopage"})
// output the 2 log files, note these have been written in parallel which
// is why they are kept separate in this example until the end
fmt.Print(b1)
fmt.Print(b2)
if err := log.Err(); err != nil {
fmt.Print(err)
}
// Output:
// {"name":"http.response","request":"/nopage","service_name":"example","status":404,"timestamp":"2017-05-20T21:00:24.2+01:00","type":"info"}
// {"name":"http.response","request":"/nopage","service_name":"example","status":404,"timestamp":"2017-05-20T21:00:24.2+01:00","type":"info"}
}