|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Globalization;
using System.Diagnostics.Tracing;
using Microsoft.AspNetCore.Internal;
using Microsoft.AspNetCore.InternalTesting;
namespace Microsoft.AspNetCore.ConcurrencyLimiter.Tests;
public class ConcurrencyLimiterEventSourceTests : LoggedTest
{
[Fact]
public void MatchesNameAndGuid()
{
var eventSource = new ConcurrencyLimiterEventSource();
Assert.Equal("Microsoft.AspNetCore.ConcurrencyLimiter", eventSource.Name);
Assert.Equal(Guid.Parse("a605548a-6963-55cf-f000-99a6013deb01", CultureInfo.InvariantCulture), eventSource.Guid);
}
[Fact]
public void RecordsRequestsRejected()
{
// Arrange
var expectedId = 1;
var eventListener = new TestEventListener(expectedId);
var eventSource = GetConcurrencyLimiterEventSource();
eventListener.EnableEvents(eventSource, EventLevel.Informational);
// Act
eventSource.RequestRejected();
// Assert
var eventData = eventListener.EventData;
Assert.NotNull(eventData);
Assert.Equal(expectedId, eventData.EventId);
Assert.Equal(EventLevel.Warning, eventData.Level);
Assert.Same(eventSource, eventData.EventSource);
Assert.Null(eventData.Message);
Assert.Empty(eventData.Payload);
}
[Fact]
public async Task TracksQueueLength()
{
// Arrange
using var eventSource = GetConcurrencyLimiterEventSource();
using var eventListener = new TestCounterListener(LoggerFactory, eventSource.Name, [
"queue-length",
"queue-duration",
"requests-rejected",
]);
using var timeoutTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30));
var lengthValues = eventListener.GetCounterValues("queue-length", timeoutTokenSource.Token).GetAsyncEnumerator();
eventListener.EnableEvents(eventSource, EventLevel.Informational, EventKeywords.None,
new Dictionary<string, string>
{
{"EventCounterIntervalSec", ".1" }
});
// Act
eventSource.RequestRejected();
Assert.True(await UntilValueMatches(lengthValues, 0));
using (eventSource.QueueTimer())
{
Assert.True(await UntilValueMatches(lengthValues, 1));
using (eventSource.QueueTimer())
{
Assert.True(await UntilValueMatches(lengthValues, 2));
}
Assert.True(await UntilValueMatches(lengthValues, 1));
}
Assert.True(await UntilValueMatches(lengthValues, 0));
}
[Fact]
public async Task TracksDurationSpentInQueue()
{
// Arrange
using var eventSource = GetConcurrencyLimiterEventSource();
using var eventListener = new TestCounterListener(LoggerFactory, eventSource.Name, [
"queue-length",
"queue-duration",
"requests-rejected",
]);
using var timeoutTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var durationValues = eventListener.GetCounterValues("queue-duration", timeoutTokenSource.Token).GetAsyncEnumerator();
eventListener.EnableEvents(eventSource, EventLevel.Informational, EventKeywords.None,
new Dictionary<string, string>
{
{"EventCounterIntervalSec", ".1" }
});
// Act
Assert.True(await UntilValueMatches(durationValues, 0));
using (eventSource.QueueTimer())
{
Assert.True(await UntilValueMatches(durationValues, 0));
}
// check that something (anything!) has been written
while (await durationValues.MoveNextAsync())
{
if (durationValues.Current > 0)
{
return;
}
}
throw new TimeoutException();
}
private async Task<bool> UntilValueMatches(IAsyncEnumerator<double> enumerator, int value)
{
while (await enumerator.MoveNextAsync())
{
if (enumerator.Current == value)
{
return true;
}
}
return false;
}
private static ConcurrencyLimiterEventSource GetConcurrencyLimiterEventSource()
{
return new ConcurrencyLimiterEventSource(Guid.NewGuid().ToString());
}
}
|