using System.Diagnostics.Metrics; namespace HSchool.Server.Game; /// Per-school tick counters surfaced in the Aspire dashboard. internal sealed class GameMetrics : IDisposable { public const string MeterName = "HSchool.Server.Game"; private readonly Meter _meter; private readonly Counter _ticks; private readonly Histogram _tickDuration; private readonly UpDownCounter _connections; private int _schools; public GameMetrics(IMeterFactory meterFactory) { _meter = meterFactory.Create(MeterName); _ticks = _meter.CreateCounter("hschool.game.ticks", "{tick}", "Simulation steps executed."); _tickDuration = _meter.CreateHistogram("hschool.game.tick.duration", "ms", "Wall time of one simulation step."); _connections = _meter.CreateUpDownCounter("hschool.game.connections", "{connection}", "Open WebSocket connections."); _meter.CreateObservableGauge("hschool.game.schools", () => Volatile.Read(ref _schools), "{school}", "Schools that currently exist."); } public void RecordTick(double durationMs) { _ticks.Add(1); _tickDuration.Record(durationMs); } public void ClientConnected() => _connections.Add(1); public void ClientDisconnected() => _connections.Add(-1); public void SchoolsChanged(int count) => Volatile.Write(ref _schools, count); public void Dispose() => _meter.Dispose(); }