1 package logrus
2
3 import (
4 "encoding/json"
5 "errors"
6 "fmt"
7 "runtime"
8 "strings"
9 "testing"
10 )
11
12 func TestErrorNotLost(t *testing.T) {
13 formatter := &JSONFormatter{}
14
15 b, err := formatter.Format(WithField("error", errors.New("wild walrus")))
16 if err != nil {
17 t.Fatal("Unable to format entry: ", err)
18 }
19
20 entry := make(map[string]interface{})
21 err = json.Unmarshal(b, &entry)
22 if err != nil {
23 t.Fatal("Unable to unmarshal formatted entry: ", err)
24 }
25
26 if entry["error"] != "wild walrus" {
27 t.Fatal("Error field not set")
28 }
29 }
30
31 func TestErrorNotLostOnFieldNotNamedError(t *testing.T) {
32 formatter := &JSONFormatter{}
33
34 b, err := formatter.Format(WithField("omg", errors.New("wild walrus")))
35 if err != nil {
36 t.Fatal("Unable to format entry: ", err)
37 }
38
39 entry := make(map[string]interface{})
40 err = json.Unmarshal(b, &entry)
41 if err != nil {
42 t.Fatal("Unable to unmarshal formatted entry: ", err)
43 }
44
45 if entry["omg"] != "wild walrus" {
46 t.Fatal("Error field not set")
47 }
48 }
49
50 func TestFieldClashWithTime(t *testing.T) {
51 formatter := &JSONFormatter{}
52
53 b, err := formatter.Format(WithField("time", "right now!"))
54 if err != nil {
55 t.Fatal("Unable to format entry: ", err)
56 }
57
58 entry := make(map[string]interface{})
59 err = json.Unmarshal(b, &entry)
60 if err != nil {
61 t.Fatal("Unable to unmarshal formatted entry: ", err)
62 }
63
64 if entry["fields.time"] != "right now!" {
65 t.Fatal("fields.time not set to original time field")
66 }
67
68 if entry["time"] != "0001-01-01T00:00:00Z" {
69 t.Fatal("time field not set to current time, was: ", entry["time"])
70 }
71 }
72
73 func TestFieldClashWithMsg(t *testing.T) {
74 formatter := &JSONFormatter{}
75
76 b, err := formatter.Format(WithField("msg", "something"))
77 if err != nil {
78 t.Fatal("Unable to format entry: ", err)
79 }
80
81 entry := make(map[string]interface{})
82 err = json.Unmarshal(b, &entry)
83 if err != nil {
84 t.Fatal("Unable to unmarshal formatted entry: ", err)
85 }
86
87 if entry["fields.msg"] != "something" {
88 t.Fatal("fields.msg not set to original msg field")
89 }
90 }
91
92 func TestFieldClashWithLevel(t *testing.T) {
93 formatter := &JSONFormatter{}
94
95 b, err := formatter.Format(WithField("level", "something"))
96 if err != nil {
97 t.Fatal("Unable to format entry: ", err)
98 }
99
100 entry := make(map[string]interface{})
101 err = json.Unmarshal(b, &entry)
102 if err != nil {
103 t.Fatal("Unable to unmarshal formatted entry: ", err)
104 }
105
106 if entry["fields.level"] != "something" {
107 t.Fatal("fields.level not set to original level field")
108 }
109 }
110
111 func TestFieldClashWithRemappedFields(t *testing.T) {
112 formatter := &JSONFormatter{
113 FieldMap: FieldMap{
114 FieldKeyTime: "@timestamp",
115 FieldKeyLevel: "@level",
116 FieldKeyMsg: "@message",
117 },
118 }
119
120 b, err := formatter.Format(WithFields(Fields{
121 "@timestamp": "@timestamp",
122 "@level": "@level",
123 "@message": "@message",
124 "timestamp": "timestamp",
125 "level": "level",
126 "msg": "msg",
127 }))
128 if err != nil {
129 t.Fatal("Unable to format entry: ", err)
130 }
131
132 entry := make(map[string]interface{})
133 err = json.Unmarshal(b, &entry)
134 if err != nil {
135 t.Fatal("Unable to unmarshal formatted entry: ", err)
136 }
137
138 for _, field := range []string{"timestamp", "level", "msg"} {
139 if entry[field] != field {
140 t.Errorf("Expected field %v to be untouched; got %v", field, entry[field])
141 }
142
143 remappedKey := fmt.Sprintf("fields.%s", field)
144 if remapped, ok := entry[remappedKey]; ok {
145 t.Errorf("Expected %s to be empty; got %v", remappedKey, remapped)
146 }
147 }
148
149 for _, field := range []string{"@timestamp", "@level", "@message"} {
150 if entry[field] == field {
151 t.Errorf("Expected field %v to be mapped to an Entry value", field)
152 }
153
154 remappedKey := fmt.Sprintf("fields.%s", field)
155 if remapped, ok := entry[remappedKey]; ok {
156 if remapped != field {
157 t.Errorf("Expected field %v to be copied to %s; got %v", field, remappedKey, remapped)
158 }
159 } else {
160 t.Errorf("Expected field %v to be copied to %s; was absent", field, remappedKey)
161 }
162 }
163 }
164
165 func TestFieldsInNestedDictionary(t *testing.T) {
166 formatter := &JSONFormatter{
167 DataKey: "args",
168 }
169
170 logEntry := WithFields(Fields{
171 "level": "level",
172 "test": "test",
173 })
174 logEntry.Level = InfoLevel
175
176 b, err := formatter.Format(logEntry)
177 if err != nil {
178 t.Fatal("Unable to format entry: ", err)
179 }
180
181 entry := make(map[string]interface{})
182 err = json.Unmarshal(b, &entry)
183 if err != nil {
184 t.Fatal("Unable to unmarshal formatted entry: ", err)
185 }
186
187 args := entry["args"].(map[string]interface{})
188
189 for _, field := range []string{"test", "level"} {
190 if value, present := args[field]; !present || value != field {
191 t.Errorf("Expected field %v to be present under 'args'; untouched", field)
192 }
193 }
194
195 for _, field := range []string{"test", "fields.level"} {
196 if _, present := entry[field]; present {
197 t.Errorf("Expected field %v not to be present at top level", field)
198 }
199 }
200
201
202 if entry["level"] != "info" {
203 t.Errorf("Expected 'level' field to contain 'info'")
204 }
205 }
206
207 func TestJSONEntryEndsWithNewline(t *testing.T) {
208 formatter := &JSONFormatter{}
209
210 b, err := formatter.Format(WithField("level", "something"))
211 if err != nil {
212 t.Fatal("Unable to format entry: ", err)
213 }
214
215 if b[len(b)-1] != '\n' {
216 t.Fatal("Expected JSON log entry to end with a newline")
217 }
218 }
219
220 func TestJSONMessageKey(t *testing.T) {
221 formatter := &JSONFormatter{
222 FieldMap: FieldMap{
223 FieldKeyMsg: "message",
224 },
225 }
226
227 b, err := formatter.Format(&Entry{Message: "oh hai"})
228 if err != nil {
229 t.Fatal("Unable to format entry: ", err)
230 }
231 s := string(b)
232 if !(strings.Contains(s, "message") && strings.Contains(s, "oh hai")) {
233 t.Fatal("Expected JSON to format message key")
234 }
235 }
236
237 func TestJSONLevelKey(t *testing.T) {
238 formatter := &JSONFormatter{
239 FieldMap: FieldMap{
240 FieldKeyLevel: "somelevel",
241 },
242 }
243
244 b, err := formatter.Format(WithField("level", "something"))
245 if err != nil {
246 t.Fatal("Unable to format entry: ", err)
247 }
248 s := string(b)
249 if !strings.Contains(s, "somelevel") {
250 t.Fatal("Expected JSON to format level key")
251 }
252 }
253
254 func TestJSONTimeKey(t *testing.T) {
255 formatter := &JSONFormatter{
256 FieldMap: FieldMap{
257 FieldKeyTime: "timeywimey",
258 },
259 }
260
261 b, err := formatter.Format(WithField("level", "something"))
262 if err != nil {
263 t.Fatal("Unable to format entry: ", err)
264 }
265 s := string(b)
266 if !strings.Contains(s, "timeywimey") {
267 t.Fatal("Expected JSON to format time key")
268 }
269 }
270
271 func TestFieldDoesNotClashWithCaller(t *testing.T) {
272 SetReportCaller(false)
273 formatter := &JSONFormatter{}
274
275 b, err := formatter.Format(WithField("func", "howdy pardner"))
276 if err != nil {
277 t.Fatal("Unable to format entry: ", err)
278 }
279
280 entry := make(map[string]interface{})
281 err = json.Unmarshal(b, &entry)
282 if err != nil {
283 t.Fatal("Unable to unmarshal formatted entry: ", err)
284 }
285
286 if entry["func"] != "howdy pardner" {
287 t.Fatal("func field replaced when ReportCaller=false")
288 }
289 }
290
291 func TestFieldClashWithCaller(t *testing.T) {
292 SetReportCaller(true)
293 formatter := &JSONFormatter{}
294 e := WithField("func", "howdy pardner")
295 e.Caller = &runtime.Frame{Function: "somefunc"}
296 b, err := formatter.Format(e)
297 if err != nil {
298 t.Fatal("Unable to format entry: ", err)
299 }
300
301 entry := make(map[string]interface{})
302 err = json.Unmarshal(b, &entry)
303 if err != nil {
304 t.Fatal("Unable to unmarshal formatted entry: ", err)
305 }
306
307 if entry["fields.func"] != "howdy pardner" {
308 t.Fatalf("fields.func not set to original func field when ReportCaller=true (got '%s')",
309 entry["fields.func"])
310 }
311
312 if entry["func"] != "somefunc" {
313 t.Fatalf("func not set as expected when ReportCaller=true (got '%s')",
314 entry["func"])
315 }
316
317 SetReportCaller(false)
318 }
319
320 func TestJSONDisableTimestamp(t *testing.T) {
321 formatter := &JSONFormatter{
322 DisableTimestamp: true,
323 }
324
325 b, err := formatter.Format(WithField("level", "something"))
326 if err != nil {
327 t.Fatal("Unable to format entry: ", err)
328 }
329 s := string(b)
330 if strings.Contains(s, FieldKeyTime) {
331 t.Error("Did not prevent timestamp", s)
332 }
333 }
334
335 func TestJSONEnableTimestamp(t *testing.T) {
336 formatter := &JSONFormatter{}
337
338 b, err := formatter.Format(WithField("level", "something"))
339 if err != nil {
340 t.Fatal("Unable to format entry: ", err)
341 }
342 s := string(b)
343 if !strings.Contains(s, FieldKeyTime) {
344 t.Error("Timestamp not present", s)
345 }
346 }
347
View as plain text