File: ConcurrencyLimiterEventSourceTests.cs
Web Access
Project: src\src\Middleware\ConcurrencyLimiter\test\Microsoft.AspNetCore.ConcurrencyLimiter.Tests.csproj (Microsoft.AspNetCore.ConcurrencyLimiter.Tests)
// 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());
    }
}