|
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"
|
@@ -163,6 +164,102 @@ func TestLogSender_LogLimitExceeded(t *testing.T) {
|
163 | 164 | require.Len(t, uut.queues, 0)
|
164 | 165 | }
|
165 | 166 |
|
| 167 | +func TestLogSender_SkipHugeLog(t *testing.T) { |
| 168 | + t.Parallel() |
| 169 | + testCtx := testutil.Context(t, testutil.WaitShort) |
| 170 | + ctx, cancel := context.WithCancel(testCtx) |
| 171 | + logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug) |
| 172 | + fDest := newFakeLogDest() |
| 173 | + uut := newLogSender(logger) |
| 174 | + |
| 175 | + t0 := dbtime.Now() |
| 176 | + ls1 := uuid.UUID{0x11} |
| 177 | + hugeLog := make([]byte, logOutputMaxBytes+1) |
| 178 | + for i := range hugeLog { |
| 179 | + hugeLog[i] = 'q' |
| 180 | + } |
| 181 | + err := uut.enqueue(ls1, |
| 182 | + agentsdk.Log{ |
| 183 | + CreatedAt: t0, |
| 184 | + Output: string(hugeLog), |
| 185 | + Level: codersdk.LogLevelInfo, |
| 186 | + }, |
| 187 | + agentsdk.Log{ |
| 188 | + CreatedAt: t0, |
| 189 | + Output: "test log 1, src 1", |
| 190 | + Level: codersdk.LogLevelInfo, |
| 191 | + }) |
| 192 | + require.NoError(t, err) |
| 193 | + |
| 194 | + loopErr := make(chan error, 1) |
| 195 | + go func() { |
| 196 | + err := uut.sendLoop(ctx, fDest) |
| 197 | + loopErr <- err |
| 198 | + }() |
| 199 | + |
| 200 | + req := testutil.RequireRecvCtx(ctx, t, fDest.reqs) |
| 201 | + require.NotNil(t, req) |
| 202 | + require.Len(t, req.Logs, 1, "it should skip the huge log") |
| 203 | + require.Equal(t, "test log 1, src 1", req.Logs[0].GetOutput()) |
| 204 | + require.Equal(t, proto.Log_INFO, req.Logs[0].GetLevel()) |
| 205 | + testutil.RequireSendCtx(ctx, t, fDest.resps, &proto.BatchCreateLogsResponse{}) |
| 206 | + |
| 207 | + cancel() |
| 208 | + err = testutil.RequireRecvCtx(testCtx, t, loopErr) |
| 209 | + require.NoError(t, err) |
| 210 | +} |
| 211 | + |
| 212 | +func TestLogSender_Batch(t *testing.T) { |
| 213 | + t.Parallel() |
| 214 | + testCtx := testutil.Context(t, testutil.WaitShort) |
| 215 | + ctx, cancel := context.WithCancel(testCtx) |
| 216 | + logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug) |
| 217 | + fDest := newFakeLogDest() |
| 218 | + uut := newLogSender(logger) |
| 219 | + |
| 220 | + t0 := dbtime.Now() |
| 221 | + ls1 := uuid.UUID{0x11} |
| 222 | + var logs []agentsdk.Log |
| 223 | + for i := 0; i < 60000; i++ { |
| 224 | + logs = append(logs, agentsdk.Log{ |
| 225 | + CreatedAt: t0, |
| 226 | + Output: "r", |
| 227 | + Level: codersdk.LogLevelInfo, |
| 228 | + }) |
| 229 | + } |
| 230 | + err := uut.enqueue(ls1, logs...) |
| 231 | + require.NoError(t, err) |
| 232 | + |
| 233 | + loopErr := make(chan error, 1) |
| 234 | + go func() { |
| 235 | + err := uut.sendLoop(ctx, fDest) |
| 236 | + loopErr <- err |
| 237 | + }() |
| 238 | + |
| 239 | + // with 60k logs, we should split into two updates to avoid going over 1MiB, since each log |
| 240 | + // is about 21 bytes. |
| 241 | + gotLogs := 0 |
| 242 | + req := testutil.RequireRecvCtx(ctx, t, fDest.reqs) |
| 243 | + require.NotNil(t, req) |
| 244 | + gotLogs += len(req.Logs) |
| 245 | + wire, err := protobuf.Marshal(req) |
| 246 | + require.NoError(t, err) |
| 247 | + require.Less(t, len(wire), logOutputMaxBytes, "wire should not exceed 1MiB") |
| 248 | + testutil.RequireSendCtx(ctx, t, fDest.resps, &proto.BatchCreateLogsResponse{}) |
| 249 | + req = testutil.RequireRecvCtx(ctx, t, fDest.reqs) |
| 250 | + require.NotNil(t, req) |
| 251 | + gotLogs += len(req.Logs) |
| 252 | + wire, err = protobuf.Marshal(req) |
| 253 | + require.NoError(t, err) |
| 254 | + require.Less(t, len(wire), logOutputMaxBytes, "wire should not exceed 1MiB") |
| 255 | + require.Equal(t, 60000, gotLogs) |
| 256 | + testutil.RequireSendCtx(ctx, t, fDest.resps, &proto.BatchCreateLogsResponse{}) |
| 257 | + |
| 258 | + cancel() |
| 259 | + err = testutil.RequireRecvCtx(testCtx, t, loopErr) |
| 260 | + require.NoError(t, err) |
| 261 | +} |
| 262 | + |
166 | 263 | type fakeLogDest struct {
|
167 | 264 | reqs chan *proto.BatchCreateLogsRequest
|
168 | 265 | resps chan *proto.BatchCreateLogsResponse
|
|
0 commit comments