69 lines
2.8 KiB
C#
69 lines
2.8 KiB
C#
using Omika.Core.Configuration;
|
|
using Omika.Core.Observability;
|
|
|
|
namespace Omika.Tests.Observability;
|
|
|
|
public class RateLimitTests
|
|
{
|
|
[Fact]
|
|
public void Storm_IdenticalEvents_IsRateLimited_AndBounded()
|
|
{
|
|
// NOTE : RateLimitPerEvent est volontairement abaissé à 100 (défaut = 1000)
|
|
// pour rendre le test de tempête rapide et lisible. La fenêtre fixe est
|
|
// de 1 seconde ; 100 000 occurrences mono-thread → ~100 acceptées, le
|
|
// reste abandonné par la protection anti-log-storm.
|
|
var options = new ObservabilityOptions { RateLimitPerEvent = 100 };
|
|
var (sink, _, counters) = ObservabilityTestHarness.CreatePipeline(options);
|
|
|
|
const long total = 100_000;
|
|
for (long i = 0; i < total; i++)
|
|
{
|
|
sink.Track(ObservabilityTestHarness.NewEvent(TelemetryEventCodes.MobileAppStarted));
|
|
}
|
|
|
|
// Tous les événements sont comptabilisés une et une seule fois.
|
|
Assert.Equal(total, counters.Accepted + counters.DroppedTotal);
|
|
// La protection rate limit a bien abandonné des occurrences.
|
|
Assert.True(counters.DroppedRateLimited > 0);
|
|
// La mémoire est bornée : on n'accepte qu'une fraction du flux.
|
|
Assert.True(counters.Accepted <= total);
|
|
}
|
|
|
|
[Fact]
|
|
public void ExactRateLimit_SingleThreaded_1000Events_RateLimit100()
|
|
{
|
|
// Fenêtre fixe = 1 s, exécution séquentielle mono-thread (aucune course).
|
|
// Le limiter accepte exactement les 100 premières occurrences puis droppe
|
|
// les 900 suivantes : le résultat est déterministe dans ce cadre.
|
|
var options = new ObservabilityOptions { RateLimitPerEvent = 100 };
|
|
var (sink, _, counters) = ObservabilityTestHarness.CreatePipeline(options);
|
|
|
|
for (int i = 0; i < 1000; i++)
|
|
{
|
|
sink.Track(ObservabilityTestHarness.NewEvent(TelemetryEventCodes.MobileAppStarted));
|
|
}
|
|
|
|
Assert.Equal(100L, counters.Accepted);
|
|
Assert.Equal(900L, counters.DroppedRateLimited);
|
|
Assert.Equal(1000L, counters.Accepted + counters.DroppedTotal);
|
|
}
|
|
|
|
[Fact]
|
|
public void ManyDistinctCodes_AreBounded_NoThrow()
|
|
{
|
|
var options = new ObservabilityOptions();
|
|
var (sink, _, counters) = ObservabilityTestHarness.CreatePipeline(options);
|
|
|
|
// Plus de codes distincts que la capacité interne de suivi (1024) : les
|
|
// codes excédentaires sont abandonnés sans exception, la mémoire reste bornée.
|
|
for (int i = 0; i < 5000; i++)
|
|
{
|
|
EventCode code = EventCode.Create("MOB", "T" + i.ToString("D7"), 1);
|
|
sink.Track(ObservabilityTestHarness.NewEvent(code));
|
|
}
|
|
|
|
Assert.Equal(5000L, counters.Accepted + counters.DroppedTotal);
|
|
Assert.True(counters.DroppedRateLimited > 0);
|
|
}
|
|
}
|