File: src\Shared\EventSource.Testing\TestCounterListener.cs
Web Access
Project: src\src\Hosting\Hosting\test\Microsoft.AspNetCore.Hosting.Tests.csproj (Microsoft.AspNetCore.Hosting.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.Collections.Generic;
using System.Diagnostics.Tracing;
using System.Threading;
using System.Threading.Channels;
 
namespace Microsoft.AspNetCore.Internal;
 
internal sealed class TestCounterListener : EventListener
{
    private readonly Dictionary<string, Channel<double>> _counters = new Dictionary<string, Channel<double>>();
 
    /// <summary>
    /// Creates a new TestCounterListener.
    /// </summary>
    /// <param name="counterNames">The names of ALL counters for the event source. You must name each counter, even if you do not intend to use it.</param>
    public TestCounterListener(string[] counterNames)
    {
        foreach (var item in counterNames)
        {
            _counters[item] = Channel.CreateUnbounded<double>();
        }
    }
 
    public IAsyncEnumerable<double> GetCounterValues(string counterName, CancellationToken cancellationToken = default)
    {
        return _counters[counterName].Reader.ReadAllAsync(cancellationToken);
    }
 
    protected override void OnEventWritten(EventWrittenEventArgs eventData)
    {
        if (eventData.EventName == "EventCounters")
        {
            var payload = (IDictionary<string, object>)eventData.Payload[0];
            var counter = (string)payload["Name"];
            payload.TryGetValue("Increment", out var increment);
            payload.TryGetValue("Mean", out var mean);
            var writer = _counters[counter].Writer;
            writer.TryWrite((double)(increment ?? mean));
        }
    }
}