using System.Diagnostics.Metrics; namespace StellaOps.Graph.Api.Services; public interface IGraphMetrics : IDisposable { Counter BudgetDenied { get; } Histogram QueryLatencySeconds { get; } Counter OverlayCacheHit { get; } Counter OverlayCacheMiss { get; } Histogram ExportLatencySeconds { get; } Meter Meter { get; } } public sealed class GraphMetrics : IGraphMetrics { private readonly Meter _meter; public GraphMetrics() { _meter = new Meter("StellaOps.Graph.Api", "1.0.0"); BudgetDenied = _meter.CreateCounter("graph_query_budget_denied_total"); QueryLatencySeconds = _meter.CreateHistogram("graph_tile_latency_seconds", unit: "s"); OverlayCacheHit = _meter.CreateCounter("graph_overlay_cache_hits_total"); OverlayCacheMiss = _meter.CreateCounter("graph_overlay_cache_misses_total"); ExportLatencySeconds = _meter.CreateHistogram("graph_export_latency_seconds", unit: "s"); } public Counter BudgetDenied { get; } public Histogram QueryLatencySeconds { get; } public Counter OverlayCacheHit { get; } public Counter OverlayCacheMiss { get; } public Histogram ExportLatencySeconds { get; } public Meter Meter => _meter; public void Dispose() { _meter.Dispose(); } }