using System.Collections.Concurrent; namespace MP.IOC.Services { public class RouteStats { public long Count; public TimeSpan TotalDuration = TimeSpan.Zero; public ConcurrentDictionary Destinations = new(); public ConcurrentDictionary StatusCodes = new(); } public class RouteStatsManager { private readonly ConcurrentDictionary _map = new(); public void Record(string method, string destination) { var stat = _map.GetOrAdd(method, _ => new RouteStats()); Interlocked.Increment(ref stat.Count); stat.Destinations.AddOrUpdate(destination, 1, (_, v) => v + 1); } public void RecordDuration(string method, TimeSpan duration) { if (_map.TryGetValue(method, out var stat)) { lock (stat) { stat.TotalDuration += 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 Snapshot() { return _map.ToDictionary(kv => kv.Key, kv => kv.Value); } public void Clear() { _map.Clear(); } } }