Premiere commit - Omika
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
using Omika.Core.Configuration;
|
||||
using Omika.Core.Observability;
|
||||
|
||||
namespace Omika.Tests.Observability;
|
||||
|
||||
public class TelemetryWorkerTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task Worker_DrainsToExporter()
|
||||
{
|
||||
var (queue, counters) = CreateQueue();
|
||||
var exporter = new CollectingExporter();
|
||||
var worker = new TelemetryWorker(queue, exporter);
|
||||
|
||||
queue.TryEnqueue(ObservabilityTestHarness.NewEvent(TelemetryEventCodes.MobileAppStarted));
|
||||
queue.TryEnqueue(ObservabilityTestHarness.NewEvent(TelemetryEventCodes.MobileAppStarted));
|
||||
|
||||
using var cts = new CancellationTokenSource();
|
||||
Task run = worker.ExecuteAsync(cts.Token);
|
||||
|
||||
await ObservabilityTestHarness.WaitUntilAsync(() => exporter.Count == 2);
|
||||
|
||||
cts.Cancel();
|
||||
await run;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Worker_DoesNotStarveLowPriority()
|
||||
{
|
||||
var (queue, _) = CreateQueue();
|
||||
var exporter = new CollectingExporter();
|
||||
var worker = new TelemetryWorker(queue, exporter);
|
||||
|
||||
// Fort arriéré de P0 + quelques P4 : les P4 doivent quand même être exportés.
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
queue.TryEnqueue(ObservabilityTestHarness.NewEvent(
|
||||
TelemetryEventCodes.MobileSyncOperationReceived, priority: TelemetryPriority.P0));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
queue.TryEnqueue(ObservabilityTestHarness.NewEvent(
|
||||
TelemetryEventCodes.MobileAppStarted, priority: TelemetryPriority.P4));
|
||||
}
|
||||
|
||||
using var cts = new CancellationTokenSource();
|
||||
Task run = worker.ExecuteAsync(cts.Token);
|
||||
|
||||
await ObservabilityTestHarness.WaitUntilAsync(() => exporter.Count == 110);
|
||||
|
||||
cts.Cancel();
|
||||
await run;
|
||||
|
||||
Assert.Equal(100, exporter.ByPriority(TelemetryPriority.P0));
|
||||
Assert.Equal(10, exporter.ByPriority(TelemetryPriority.P4));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Worker_ExporterThrows_DoesNotPropagate()
|
||||
{
|
||||
var (queue, _) = CreateQueue();
|
||||
var worker = new TelemetryWorker(queue, new ThrowingExporter());
|
||||
|
||||
queue.TryEnqueue(ObservabilityTestHarness.NewEvent(TelemetryEventCodes.MobileAppStarted));
|
||||
|
||||
using var cts = new CancellationTokenSource();
|
||||
Task run = worker.ExecuteAsync(cts.Token);
|
||||
|
||||
// Laisse au worker le temps de tenter l'export, d'échouer et de reprendre.
|
||||
await Task.Delay(300);
|
||||
cts.Cancel();
|
||||
|
||||
await run;
|
||||
// Le lot a été abandonné (perte de log acceptable) ; aucune exception.
|
||||
Assert.Equal(0, queue.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Worker_Cancellation_Stops()
|
||||
{
|
||||
var (queue, _) = CreateQueue();
|
||||
var worker = new TelemetryWorker(queue, new NullTelemetryExporter());
|
||||
|
||||
using var cts = new CancellationTokenSource();
|
||||
Task run = worker.ExecuteAsync(cts.Token);
|
||||
|
||||
cts.Cancel();
|
||||
await run;
|
||||
}
|
||||
|
||||
private static (PriorityTelemetryQueue Queue, TelemetryCounters Counters) CreateQueue()
|
||||
{
|
||||
var options = new ObservabilityOptions();
|
||||
var counters = new TelemetryCounters();
|
||||
return (new PriorityTelemetryQueue(options, counters), counters);
|
||||
}
|
||||
|
||||
private sealed class CollectingExporter : ITelemetryExporter
|
||||
{
|
||||
private readonly object _lock = new();
|
||||
private readonly List<OmikaEvent> _exported = [];
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _exported.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int ByPriority(TelemetryPriority priority)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _exported.Count(e => e.EffectivePriority == priority);
|
||||
}
|
||||
}
|
||||
|
||||
public Task ExportAsync(IReadOnlyList<OmikaEvent> events, CancellationToken cancellationToken = default)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_exported.AddRange(events);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class ThrowingExporter : ITelemetryExporter
|
||||
{
|
||||
public Task ExportAsync(IReadOnlyList<OmikaEvent> events, CancellationToken cancellationToken = default) =>
|
||||
throw new InvalidOperationException("exporteur défaillant (test)");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user