Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/common-go/log/log_test.go
2498 views
1
// Copyright (c) 2021 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package log
6
7
import (
8
"bytes"
9
"fmt"
10
"io"
11
"strings"
12
"testing"
13
"time"
14
15
"github.com/google/go-cmp/cmp"
16
"github.com/sirupsen/logrus"
17
)
18
19
func TestFromBuffer(t *testing.T) {
20
tests := []struct {
21
Description string
22
Input []byte
23
Expected []byte
24
}{
25
{
26
"Empty",
27
[]byte("\x00"),
28
[]byte(""),
29
},
30
{
31
"With null and without msg or message field",
32
[]byte("\x00{\"notMessages\":\"\"}"),
33
[]byte(""),
34
},
35
{
36
"Output without msg or message field",
37
[]byte("\x00{\"notMessages\":\"\"}"),
38
[]byte(""),
39
},
40
{
41
"Output with message field",
42
[]byte("{\"level\":\"info\",\"message\":\"DisposeWorkspace called\",\"time\":\"2021-09-14T21:26:44Z\"}"),
43
[]byte("{\"context\":\"test\",\"level\":\"info\",\"msg\":\"DisposeWorkspace called\",\"time\":\"2021-09-14T21:26:44Z\"}\n"),
44
},
45
{
46
"Output with msg field",
47
[]byte("{\"level\":\"info\",\"msg\":\"DisposeWorkspace called\",\"time\":\"2021-09-14T21:26:44Z\"}"),
48
[]byte("{\"context\":\"test\",\"level\":\"info\",\"msg\":\"DisposeWorkspace called\",\"time\":\"2021-09-14T21:26:44Z\"}\n"),
49
},
50
{
51
"Output with msg field and error level",
52
[]byte("{\"level\":\"error\",\"message\":\"DisposeWorkspace called\",\"time\":\"2021-09-14T21:26:44Z\"}"),
53
[]byte("{\"context\":\"test\",\"level\":\"error\",\"msg\":\"DisposeWorkspace called\",\"time\":\"2021-09-14T21:26:44Z\"}\n"),
54
},
55
{
56
"Output with msg field and error level",
57
[]byte("{\"level\":\"error\",\"message\":\"DisposeWorkspace called\",\"time\":\"2021-09-14T21:26:44Z\"}"),
58
[]byte("{\"context\":\"test\",\"level\":\"error\",\"msg\":\"DisposeWorkspace called\",\"time\":\"2021-09-14T21:26:44Z\"}\n"),
59
},
60
{
61
"With invalid JSON",
62
[]byte("{\"notMessages\":\"\""),
63
[]byte(""),
64
},
65
{
66
"Text as JSON",
67
[]byte("NOT JSON"),
68
[]byte(""),
69
},
70
{
71
"Mixed content - text and valid JSON",
72
[]byte("SOMETHING INVALID\n{\"level\":\"error\",\"message\":\"DisposeWorkspace called\",\"time\":\"2021-09-14T21:26:44Z\"}"),
73
[]byte("{\"context\":\"test\",\"level\":\"error\",\"msg\":\"DisposeWorkspace called\",\"time\":\"2021-09-14T21:26:44Z\"}\n"),
74
},
75
}
76
77
for _, test := range tests {
78
logger := logrus.New()
79
var buffer bytes.Buffer
80
logger.SetFormatter(&logrus.JSONFormatter{})
81
logger.SetOutput(&buffer)
82
logger.SetLevel(logrus.DebugLevel)
83
84
entry := logger.WithField("context", "test")
85
86
FromBuffer(bytes.NewBuffer(test.Input), entry)
87
if diff := cmp.Diff(string(test.Expected), buffer.String()); diff != "" {
88
t.Errorf("%v: unexpected result (-want +got):\n%s", test.Description, diff)
89
}
90
}
91
}
92
93
type TestWorkspaceInfo struct {
94
WorkspaceId string
95
InstanceId string
96
WorkspaceContextUrl string
97
}
98
99
func TestScrubFormatter(t *testing.T) {
100
logger := logrus.New()
101
logger.SetFormatter(newGcpFormatter(false))
102
103
var buffer bytes.Buffer
104
logger.SetOutput(&buffer)
105
106
createInfo := func() *TestWorkspaceInfo {
107
return &TestWorkspaceInfo{
108
WorkspaceId: "1234567890",
109
InstanceId: "1234567890",
110
WorkspaceContextUrl: "https://github.com/gitpod-io/gitpod",
111
}
112
}
113
info := createInfo()
114
workspaceID := "1234567890"
115
116
logTime := time.Now()
117
logger.WithTime(logTime).WithField("info", info).WithField("workspaceID", workspaceID).
118
WithError(fmt.Errorf("some test error")).
119
WithFields(ServiceContext("test", "1.0.0")).
120
Info("email: [email protected]")
121
122
expectation := fmt.Sprintf(
123
`{"error":"some test error","info":"[redacted:nested]","level":"info","message":"email: [email protected]","serviceContext":{"service":"test","version":"1.0.0"},"severity":"INFO","time":"%s","workspaceID":"[redacted:md5:e807f1fcf82d132f9bb018ca6738a19f]"}`,
124
logTime.Format(time.RFC3339Nano),
125
)
126
actual := strings.TrimSpace(buffer.String())
127
if diff := cmp.Diff(expectation, actual); diff != "" {
128
t.Errorf("unexpected result (-want +got):\n%s", diff)
129
}
130
if diff := cmp.Diff(createInfo(), info); diff != "" {
131
t.Errorf("info: unexpected result (-want +got):\n%s", diff)
132
}
133
if diff := cmp.Diff("1234567890", workspaceID); diff != "" {
134
t.Errorf("workspaceID: unexpected result (-want +got):\n%s", diff)
135
}
136
}
137
138
/*
139
12/06/2023 - no cahce fields
140
cpu: Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz
141
BenchmarkSimpleScrubFormatter/json-32 312109 3617 ns/op 2035 B/op 31 allocs/op
142
BenchmarkSimpleScrubFormatter/scrub+json-32 244150 4753 ns/op 2242 B/op 37 allocs/op
143
144
09/06/2023 - with redacting nested fields
145
cpu: Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz
146
BenchmarkSimpleScrubFormatter/json-32 281763 3666 ns/op 2035 B/op 31 allocs/op
147
BenchmarkSimpleScrubFormatter/scrub+json-32 278829 4248 ns/op 2204 B/op 37 allocs/op
148
149
05/06/2023 - with json scrubbing
150
cpu: Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz
151
BenchmarkSimpleScrubFormatter/json-32 321686 3546 ns/op 2035 B/op 31 allocs/op
152
BenchmarkSimpleScrubFormatter/scrub+json-32 148384 8308 ns/op 3781 B/op 76 allocs/op
153
154
02/06/2023 (Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz) - with cache lock and eviction
155
BenchmarkSimpleScrubFormatter/json-32 359746 3144 ns/op 1914 B/op 28 allocs/op
156
BenchmarkSimpleScrubFormatter/scrub+json-32 312946 3796 ns/op 2083 B/op 34 allocs/op
157
158
02/06/2023 (Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz) - precomputed cache
159
BenchmarkSimpleScrubFormatter/json-32 367134 3215 ns/op 1914 B/op 28 allocs/op
160
BenchmarkSimpleScrubFormatter/scrub+json-32 302583 3869 ns/op 2083 B/op 34 allocs/op
161
162
01/06/2023 (Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz) - with caching without lower case conversion
163
BenchmarkSimpleScrubFormatter/json-32 377443 3059 ns/op 1914 B/op 28 allocs/op
164
BenchmarkSimpleScrubFormatter/scrub+json-32 311752 3704 ns/op 2083 B/op 34 allocs/op
165
166
31/05/2023 (Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz) - skip message, scrub with KeyValue for string type
167
BenchmarkSimpleScrubFormatter/json-32 376062 3019 ns/op 1914 B/op 28 allocs/op
168
BenchmarkSimpleScrubFormatter/scrub+json-32 313464 3798 ns/op 2097 B/op 35 allocs/op
169
170
31/05/2023 (Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz) - skip message
171
BenchmarkSimpleScrubFormatter/json-32 380050 2991 ns/op 1914 B/op 28 allocs/op
172
BenchmarkSimpleScrubFormatter/scrub+json-32 270021 4420 ns/op 2233 B/op 43 allocs/op
173
174
30/05/2023 (Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz) - scrubbing takes almost twice as long because of relection and regex replacements
175
BenchmarkSimpleScrubFormatter/json-32 368532 3095 ns/op 1914 B/op 28 allocs/op
176
BenchmarkSimpleScrubFormatter/scrub+json-32 200944 5858 ns/op 2666 B/op 53 allocs/op
177
0 1.21s (flat, cum) 38.29% of Total
178
. . 94:func (formatter *scrubFormatter) Format(entry *logrus.Entry) ([]byte, error) {
179
. 300ms 95: entry.Message = scrubber.Default.Value(entry.Message)
180
. 260ms 96: err := scrubber.Default.Struct(entry.Data)
181
. . 97: if err != nil {
182
. . 98: return nil, fmt.Errorf("cannot scrub log entry: %w", err)
183
. . 99: }
184
. 650ms 100: return formatter.delegate.Format(entry)
185
. . 101:}
186
*/
187
func BenchmarkSimpleScrubFormatter(b *testing.B) {
188
logger := logrus.New()
189
logger.SetOutput(io.Discard)
190
191
run := func() {
192
logger.WithField("workspaceID", "1234567890").Info("email: [email protected]")
193
}
194
195
logger.SetFormatter(newGcpFormatter(true))
196
b.Run("json", func(b *testing.B) {
197
for i := 0; i < b.N; i++ {
198
run()
199
}
200
})
201
202
logger.SetFormatter(newGcpFormatter(false))
203
b.Run("scrub+json", func(b *testing.B) {
204
for i := 0; i < b.N; i++ {
205
run()
206
}
207
})
208
209
}
210
211
/*
212
12/06/2023 - no cahce fields
213
cpu: Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz
214
BenchmarkStructScrubFormatter/json-32 304662 3860 ns/op 2091 B/op 32 allocs/op
215
BenchmarkStructScrubFormatter/scrub+json-32 320354 3698 ns/op 2091 B/op 32 allocs/op
216
217
09/06/2023 - with redacting nested fields
218
cpu: Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz
219
BenchmarkStructScrubFormatter/json-32 315826 3706 ns/op 2091 B/op 32 allocs/op
220
BenchmarkStructScrubFormatter/scrub+json-32 322910 3647 ns/op 2091 B/op 32 allocs/op
221
222
05/06/2023 - with json scrubbing
223
cpu: Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz
224
BenchmarkStructScrubFormatter/json-32 310472 3842 ns/op 2091 B/op 32 allocs/op
225
BenchmarkStructScrubFormatter/scrub+json-32 109390 10808 ns/op 5101 B/op 105 allocs/op
226
227
02/06/2023 (Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz - with cache lock and eviction
228
BenchmarkStructScrubFormatter/json-32 354174 3314 ns/op 1971 B/op 29 allocs/op
229
BenchmarkStructScrubFormatter/scrub+json-32 242992 4896 ns/op 2365 B/op 44 allocs/op
230
231
02/06/2023 (Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz - precomputed cache
232
BenchmarkStructScrubFormatter/json-32 344023 3465 ns/op 1971 B/op 29 allocs/op
233
BenchmarkStructScrubFormatter/scrub+json-32 240534 4850 ns/op 2365 B/op 44 allocs/op
234
235
01/06/2023 (Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz) - with caching without lower case conversion
236
BenchmarkStructScrubFormatter/json-32 354729 3259 ns/op 1971 B/op 29 allocs/op
237
BenchmarkStructScrubFormatter/scrub+json-32 232270 4767 ns/op 2365 B/op 44 allocs/op
238
239
01/06/2023 (Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz) - with substring mathing - 3 times slower
240
BenchmarkStructScrubFormatter/json-32 351439 3388 ns/op 1971 B/op 29 allocs/op
241
BenchmarkStructScrubFormatter/scrub+json-32 115599 9032 ns/op 2396 B/op 44 allocs/op
242
243
31/05/2023 (Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz) - early exit with SkipEntry + no double traversing
244
BenchmarkStructScrubFormatter/json-32 369788 3885 ns/op 1971 B/op 29 allocs/op
245
BenchmarkStructScrubFormatter/scrub+json-32 232442 5092 ns/op 2421 B/op 47 allocs/op
246
247
31/05/2023 (Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz) - initial, still double
248
BenchmarkStructScrubFormatter/json-32 349736 3240 ns/op 1971 B/op 29 allocs/op
249
BenchmarkStructScrubFormatter/scrub+json-32 142266 8295 ns/op 2580 B/op 53 allocs/op
250
*/
251
func BenchmarkStructScrubFormatter(b *testing.B) {
252
logger := logrus.New()
253
logger.SetOutput(io.Discard)
254
255
run := func() {
256
logger.WithField("info", &TestWorkspaceInfo{
257
WorkspaceId: "1234567890",
258
InstanceId: "1234567890",
259
WorkspaceContextUrl: "https://github.com/gitpod-io/gitpod",
260
}).Info("resolve workspace info failed")
261
}
262
263
logger.SetFormatter(newGcpFormatter(true))
264
b.Run("json", func(b *testing.B) {
265
for i := 0; i < b.N; i++ {
266
run()
267
}
268
})
269
270
logger.SetFormatter(newGcpFormatter(false))
271
b.Run("scrub+json", func(b *testing.B) {
272
for i := 0; i < b.N; i++ {
273
run()
274
}
275
})
276
277
}
278
279