package prometheus import ( // Hybrid instrumentation rationale: direct client_golang instrumentation // lives in app/webrtc/metrics.go (hot-path counters and histograms); // this file owns the snapshot-style gauges. See the design doc at // docs/design/2026-05-03-datarhei-dragon-fork-webrtc-prometheus-metrics-design.md. "github.com/prometheus/client_golang/prometheus" ) // WebRTCStats is a point-in-time snapshot of the WebRTC subsystem state. // Populated by Handler.Stats() in app/webrtc and consumed by the collector // at scrape time. type WebRTCStats struct { StreamCount int PeersByStream map[string]int UDPPortsInUse int } // WebRTCStatsSource is implemented by app/webrtc.Handler (via its Stats() // method). The interface lives here so prometheus/ does not import app/webrtc, // keeping the dependency arrow one-directional. type WebRTCStatsSource interface { Stats() WebRTCStats } type webrtcCollector struct { core string source WebRTCStatsSource activeStreamsDesc *prometheus.Desc activePeersDesc *prometheus.Desc udpPortsInUseDesc *prometheus.Desc } // NewWebRTCCollector returns a prometheus.Collector that emits three gauge // metrics at scrape time by calling source.Stats(). Register it with the // shared Metrics registry before the /metrics endpoint starts serving. func NewWebRTCCollector(core string, source WebRTCStatsSource) prometheus.Collector { cl := prometheus.Labels{"core": core} return &webrtcCollector{ core: core, source: source, activeStreamsDesc: prometheus.NewDesc( "dragonfork_webrtc_active_streams", "Streams currently registered (processes with webrtc.enabled=true running).", nil, cl, ), activePeersDesc: prometheus.NewDesc( "dragonfork_webrtc_active_peers", "Currently subscribed WHEP peers per stream.", []string{"stream_id"}, cl, ), udpPortsInUseDesc: prometheus.NewDesc( "dragonfork_webrtc_udp_ports_in_use", "UDP ports currently allocated (2 per active stream).", nil, cl, ), } } func (c *webrtcCollector) Describe(ch chan<- *prometheus.Desc) { ch <- c.activeStreamsDesc ch <- c.activePeersDesc ch <- c.udpPortsInUseDesc } func (c *webrtcCollector) Collect(ch chan<- prometheus.Metric) { stats := c.source.Stats() ch <- prometheus.MustNewConstMetric(c.activeStreamsDesc, prometheus.GaugeValue, float64(stats.StreamCount)) ch <- prometheus.MustNewConstMetric(c.udpPortsInUseDesc, prometheus.GaugeValue, float64(stats.UDPPortsInUse)) for streamID, count := range stats.PeersByStream { ch <- prometheus.MustNewConstMetric(c.activePeersDesc, prometheus.GaugeValue, float64(count), streamID) } }