7
7
8
8
"github.com/google/uuid"
9
9
"github.com/stretchr/testify/require"
10
+ protobuf "google.golang.org/protobuf/proto"
10
11
11
12
"cdr.dev/slog"
12
13
"cdr.dev/slog/sloggers/slogtest"
@@ -17,7 +18,7 @@ import (
17
18
"github.com/coder/coder/v2/testutil"
18
19
)
19
20
20
- func TestLogSender (t * testing.T ) {
21
+ func TestLogSender_Mainline (t * testing.T ) {
21
22
t .Parallel ()
22
23
testCtx := testutil .Context (t , testutil .WaitShort )
23
24
ctx , cancel := context .WithCancel (testCtx )
@@ -116,6 +117,99 @@ func TestLogSender(t *testing.T) {
116
117
require .NoError (t , err )
117
118
}
118
119
120
+ func TestLogSender_SkipHugeLog (t * testing.T ) {
121
+ t .Parallel ()
122
+ testCtx := testutil .Context (t , testutil .WaitShort )
123
+ ctx , cancel := context .WithCancel (testCtx )
124
+ logger := slogtest .Make (t , nil ).Leveled (slog .LevelDebug )
125
+ fDest := newFakeLogDest ()
126
+ uut := newLogSender (logger )
127
+
128
+ t0 := dbtime .Now ()
129
+ ls1 := uuid.UUID {0x11 }
130
+ hugeLog := make ([]byte , logOutputMaxBytes + 1 )
131
+ for i := range hugeLog {
132
+ hugeLog [i ] = 'q'
133
+ }
134
+ err := uut .enqueue (ls1 ,
135
+ agentsdk.Log {
136
+ CreatedAt : t0 ,
137
+ Output : string (hugeLog ),
138
+ Level : codersdk .LogLevelInfo ,
139
+ },
140
+ agentsdk.Log {
141
+ CreatedAt : t0 ,
142
+ Output : "test log 1, src 1" ,
143
+ Level : codersdk .LogLevelInfo ,
144
+ })
145
+ require .NoError (t , err )
146
+
147
+ loopErr := make (chan error , 1 )
148
+ go func () {
149
+ err := uut .sendLoop (ctx , fDest )
150
+ loopErr <- err
151
+ }()
152
+
153
+ req := testutil .RequireRecvCtx (ctx , t , fDest .reqs )
154
+ require .NotNil (t , req )
155
+ require .Len (t , req .Logs , 1 , "it should skip the huge log" )
156
+ require .Equal (t , "test log 1, src 1" , req .Logs [0 ].GetOutput ())
157
+ require .Equal (t , proto .Log_INFO , req .Logs [0 ].GetLevel ())
158
+
159
+ cancel ()
160
+ err = testutil .RequireRecvCtx (testCtx , t , loopErr )
161
+ require .NoError (t , err )
162
+ }
163
+
164
+ func TestLogSender_Batch (t * testing.T ) {
165
+ t .Parallel ()
166
+ testCtx := testutil .Context (t , testutil .WaitShort )
167
+ ctx , cancel := context .WithCancel (testCtx )
168
+ logger := slogtest .Make (t , nil ).Leveled (slog .LevelDebug )
169
+ fDest := newFakeLogDest ()
170
+ uut := newLogSender (logger )
171
+
172
+ t0 := dbtime .Now ()
173
+ ls1 := uuid.UUID {0x11 }
174
+ var logs []agentsdk.Log
175
+ for i := 0 ; i < 60000 ; i ++ {
176
+ logs = append (logs , agentsdk.Log {
177
+ CreatedAt : t0 ,
178
+ Output : "r" ,
179
+ Level : codersdk .LogLevelInfo ,
180
+ })
181
+ }
182
+ err := uut .enqueue (ls1 , logs ... )
183
+ require .NoError (t , err )
184
+
185
+ loopErr := make (chan error , 1 )
186
+ go func () {
187
+ err := uut .sendLoop (ctx , fDest )
188
+ loopErr <- err
189
+ }()
190
+
191
+ // with 60k logs, we should split into two updates to avoid going over 1MiB, since each log
192
+ // is about 21 bytes.
193
+ gotLogs := 0
194
+ req := testutil .RequireRecvCtx (ctx , t , fDest .reqs )
195
+ require .NotNil (t , req )
196
+ gotLogs += len (req .Logs )
197
+ wire , err := protobuf .Marshal (req )
198
+ require .NoError (t , err )
199
+ require .Less (t , len (wire ), logOutputMaxBytes , "wire should not exceed 1MiB" )
200
+ req = testutil .RequireRecvCtx (ctx , t , fDest .reqs )
201
+ require .NotNil (t , req )
202
+ gotLogs += len (req .Logs )
203
+ wire , err = protobuf .Marshal (req )
204
+ require .NoError (t , err )
205
+ require .Less (t , len (wire ), logOutputMaxBytes , "wire should not exceed 1MiB" )
206
+ require .Equal (t , 60000 , gotLogs )
207
+
208
+ cancel ()
209
+ err = testutil .RequireRecvCtx (testCtx , t , loopErr )
210
+ require .NoError (t , err )
211
+ }
212
+
119
213
type fakeLogDest struct {
120
214
reqs chan * proto.BatchCreateLogsRequest
121
215
}
0 commit comments