Files
mapo-core/MP.IOC/Services/RouteStatsManager.cs
T
2026-04-07 11:56:06 +02:00

92 lines
2.9 KiB
C#

using System.Collections.Concurrent;
namespace MP.IOC.Services
{
public class RouteStats
{
public long Count;
public TimeSpan TotalDuration = TimeSpan.Zero;
public TimeSpan MaxDuration = TimeSpan.Zero;
public TimeSpan MinDuration = TimeSpan.MaxValue;
public ConcurrentDictionary<string, DestinationStats> Destinations = new();
public ConcurrentDictionary<int, long> StatusCodes = new();
}
public class DestinationStats
{
public long Count;
public TimeSpan TotalDuration = TimeSpan.Zero;
public TimeSpan MaxDuration = TimeSpan.Zero;
public TimeSpan MinDuration = TimeSpan.MaxValue;
}
public class RouteStatsManager
{
private readonly ConcurrentDictionary<string, RouteStats> _map = new();
public void Record(string method, string destination)
{
var stat = _map.GetOrAdd(method, _ => new RouteStats());
Interlocked.Increment(ref stat.Count);
var destStat = stat.Destinations.GetOrAdd(destination, _ => new DestinationStats());
Interlocked.Increment(ref destStat.Count);
}
public void RecordDuration(string method, TimeSpan duration)
{
if (_map.TryGetValue(method, out var stat))
{
lock (stat)
{
stat.TotalDuration += duration;
if (stat.MaxDuration < duration)
{
stat.MaxDuration = duration;
}
if (stat.MinDuration > duration)
{
stat.MinDuration = duration;
}
foreach (var destStat in stat.Destinations.Values)
{
lock (destStat)
{
destStat.TotalDuration += duration;
if (destStat.MaxDuration < duration)
{
destStat.MaxDuration = duration;
}
if (destStat.MinDuration > duration)
{
destStat.MinDuration = duration;
}
}
}
}
}
}
public void RecordStatusCode(string method, int statusCode)
{
if (_map.TryGetValue(method, out var stat))
{
stat.StatusCodes.AddOrUpdate(statusCode, 1, (_, v) => v + 1);
}
}
public IReadOnlyDictionary<string, RouteStats> Snapshot()
{
return _map.ToDictionary(kv => kv.Key, kv => kv.Value);
}
public void Clear()
{
_map.Clear();
}
}
}