(t *testing.T)
| 279 | } |
| 280 | |
| 281 | func TestRecordStreamRetry(t *testing.T) { |
| 282 | t.Parallel() |
| 283 | |
| 284 | // One row per ChatErrorKind constant. Production callers always |
| 285 | // reach RecordStreamRetry through chaterror.Classify, which |
| 286 | // guarantees Kind is non-empty, so no empty-string case is |
| 287 | // needed. |
| 288 | tests := []struct { |
| 289 | name string |
| 290 | kind codersdk.ChatErrorKind |
| 291 | chainBroken bool |
| 292 | }{ |
| 293 | {name: "overloaded", kind: codersdk.ChatErrorKindOverloaded}, |
| 294 | {name: "rate_limit", kind: codersdk.ChatErrorKindRateLimit}, |
| 295 | {name: "timeout", kind: codersdk.ChatErrorKindTimeout}, |
| 296 | {name: "startup_timeout", kind: codersdk.ChatErrorKindStartupTimeout}, |
| 297 | {name: "auth", kind: codersdk.ChatErrorKindAuth}, |
| 298 | {name: "config", kind: codersdk.ChatErrorKindConfig}, |
| 299 | {name: "missing_key", kind: codersdk.ChatErrorKindMissingKey}, |
| 300 | {name: "generic", kind: codersdk.ChatErrorKindGeneric}, |
| 301 | {name: "chain_broken", kind: codersdk.ChatErrorKindGeneric, chainBroken: true}, |
| 302 | } |
| 303 | |
| 304 | for _, tt := range tests { |
| 305 | t.Run(tt.name, func(t *testing.T) { |
| 306 | t.Parallel() |
| 307 | |
| 308 | reg := prometheus.NewRegistry() |
| 309 | m := chatloop.NewMetrics(reg) |
| 310 | m.RecordStreamRetry("test-provider", "test-model", chaterror.ClassifiedError{ |
| 311 | Kind: tt.kind, |
| 312 | ChainBroken: tt.chainBroken, |
| 313 | }) |
| 314 | |
| 315 | requireCounter(t, reg, "coderd_chatd_stream_retries_total", 1, map[string]string{ |
| 316 | "provider": "test-provider", |
| 317 | "model": "test-model", |
| 318 | "kind": string(tt.kind), |
| 319 | "chain_broken": strconv.FormatBool(tt.chainBroken), |
| 320 | }) |
| 321 | }) |
| 322 | } |
| 323 | } |
| 324 | |
| 325 | func TestRecordStreamBufferDropped(t *testing.T) { |
| 326 | t.Parallel() |
nothing calls this directly
no test coverage detected