package starlog import ( "bytes" "sync/atomic" "testing" "time" ) func TestSamplingRateDeterministic(t *testing.T) { var buf bytes.Buffer logger := newStructuredTestLogger(&buf) logger.SetSamplingConfig(SamplingConfig{ Enable: true, Levels: []int{LvInfo}, Rate: 0.5, Scope: SamplingScopeGlobal, }) for idx := 0; idx < 5; idx++ { logger.Infoln("sample") } stats := logger.GetSamplingStats() if stats.Allowed != 3 || stats.Dropped != 2 { t.Fatalf("unexpected sampling stats: %+v", stats) } if got := bytes.Count(buf.Bytes(), []byte("sample")); got != 3 { t.Fatalf("expected 3 sampled logs in output, got %d", got) } } func TestSamplingDropCallback(t *testing.T) { logger := newStructuredTestLogger(&bytes.Buffer{}) var callbackCount uint64 logger.SetSamplingConfig(SamplingConfig{ Enable: true, Levels: []int{LvInfo}, Rate: 0, Scope: SamplingScopeGlobal, OnDrop: func(data SamplingDropData) { if data.Reason == "" { t.Errorf("drop callback reason should not be empty") } atomic.AddUint64(&callbackCount, 1) }, }) logger.Infoln("drop-all") logger.Infoln("drop-all") if atomic.LoadUint64(&callbackCount) != 2 { t.Fatalf("sampling drop callback should be called twice, got %d", callbackCount) } } func TestDedupWindow(t *testing.T) { var buf bytes.Buffer logger := newStructuredTestLogger(&buf) logger.SetDedupConfig(DedupConfig{ Enable: true, Levels: []int{LvInfo}, Window: time.Hour, Scope: DedupScopeByKey, }) logger.Infoln("dup") logger.Infoln("dup") logger.Infoln("dup") logger.Infoln("other") stats := logger.GetDedupStats() if stats.Allowed != 2 || stats.Dropped != 2 { t.Fatalf("unexpected dedup stats: %+v", stats) } if got := bytes.Count(buf.Bytes(), []byte("dup")); got != 1 { t.Fatalf("expected one deduped dup log in output, got %d", got) } if got := bytes.Count(buf.Bytes(), []byte("other")); got != 1 { t.Fatalf("expected one other log in output, got %d", got) } } func TestSamplingDedupConfigSnapshotApply(t *testing.T) { logger := newStructuredTestLogger(&bytes.Buffer{}) cfg := logger.GetConfig() cfg.Sampling = SamplingConfig{ Enable: true, Levels: []int{LvInfo}, Rate: 0.25, Scope: SamplingScopeByKey, } cfg.Dedup = DedupConfig{ Enable: true, Levels: []int{LvWarning}, Window: 3 * time.Second, Scope: DedupScopeByKey, } logger.ApplyConfig(cfg) samplingCfg := logger.GetSamplingConfig() if !samplingCfg.Enable || samplingCfg.Rate != 0.25 || samplingCfg.Scope != SamplingScopeByKey { t.Fatalf("unexpected sampling config after ApplyConfig: %+v", samplingCfg) } dedupCfg := logger.GetDedupConfig() if !dedupCfg.Enable || dedupCfg.Window != 3*time.Second || dedupCfg.Scope != DedupScopeByKey { t.Fatalf("unexpected dedup config after ApplyConfig: %+v", dedupCfg) } }