TestSendToOutChanLoudOnFirstDrop validates the two-message-shape behaviour: the very first drop's Error carries the expanded "recording is now LOSSY" wording, and subsequent sampled emissions (n%1024 == 0) carry the TERSE default. Per Copilot review on PR #4176 the loud signal rides on the existing
(t *testing.T)
| 851 | // clear actionable line at the moment capture goes lossy, no |
| 852 | // log-level duplication. |
| 853 | func TestSendToOutChanLoudOnFirstDrop(t *testing.T) { |
| 854 | t.Parallel() |
| 855 | |
| 856 | ch := make(chan *models.Mock, 1) |
| 857 | mgr := &SyncMockManager{ |
| 858 | buffer: make([]*models.Mock, 0, defaultMockBufferCapacity), |
| 859 | } |
| 860 | mgr.SetOutputChannel(ch) |
| 861 | |
| 862 | core, logs := observer.New(zap.ErrorLevel) |
| 863 | mgr.SetLogger(zap.New(core)) |
| 864 | |
| 865 | // Fill the slot so the next send hits the drop branch. |
| 866 | ch <- &models.Mock{} |
| 867 | |
| 868 | mgr.sendToOutChan(&models.Mock{Spec: models.MockSpec{ReqTimestampMock: time.Now()}}) |
| 869 | |
| 870 | if got := mgr.DropCount(); got != 1 { |
| 871 | t.Fatalf("expected dropCount=1, got %d", got) |
| 872 | } |
| 873 | if logs.Len() != 1 { |
| 874 | t.Fatalf("expected exactly one Error log on first drop, got %d", logs.Len()) |
| 875 | } |
| 876 | first := logs.All()[0] |
| 877 | if first.Level != zap.ErrorLevel { |
| 878 | t.Fatalf("expected Error level, got %v", first.Level) |
| 879 | } |
| 880 | // The first-drop message must carry the operator-actionable |
| 881 | // "LOSSY" wording — the whole point of the expanded n==1 |
| 882 | // message is to surface the actionable cliff signal *the moment* |
| 883 | // capture stops being whole, so the operator can react before |
| 884 | // the per-1024 sampler hides hundreds of subsequent drops. |
| 885 | if !strings.Contains(first.Message, "LOSSY") { |
| 886 | t.Errorf("first-drop Error missing LOSSY wording: %q", first.Message) |
| 887 | } |
| 888 | |
| 889 | // Now drive dropCount up to the next sampler milestone (1024) |
| 890 | // without paying the per-drop wall-clock cost, then walk |
| 891 | // sendToOutChan once more to fire the n==1024 branch. The |
| 892 | // emitted message must be the TERSE default — without "LOSSY" |
| 893 | // — so the sampled telemetry doesn't drown a stuck consumer's |
| 894 | // goroutine in the long actionable string. |
| 895 | mgr.dropCount.Store(sendDropSampleRate - 1) // next Add brings n to 1024 |
| 896 | mgr.sendToOutChan(&models.Mock{Spec: models.MockSpec{ReqTimestampMock: time.Now()}}) |
| 897 | if logs.Len() != 2 { |
| 898 | t.Fatalf("expected a second Error log at n==%d, got total=%d", |
| 899 | sendDropSampleRate, logs.Len()) |
| 900 | } |
| 901 | second := logs.All()[1] |
| 902 | if second.Level != zap.ErrorLevel { |
| 903 | t.Fatalf("expected Error level on second sampled emission, got %v", second.Level) |
| 904 | } |
| 905 | if strings.Contains(second.Message, "LOSSY") { |
| 906 | t.Errorf("subsequent sampled Error must use terse default; got %q", second.Message) |
| 907 | } |
| 908 | } |
| 909 | |
| 910 | // TestSendToOutChanDropSampling validates the sampling rule: |
nothing calls this directly
no test coverage detected