datarhei-dragonfork-core/prometheus/webrtc.go
ZGaetano 23636e4a76
Some checks failed
ci / race tests (push) Blocked by required conditions
ci / WebRTC smoke (5-viewer fanout) (push) Blocked by required conditions
ci / WebRTC latency p95 gate (push) Blocked by required conditions
ci / vet + build (push) Has been cancelled
feat(prometheus): add WebRTC snapshot collector
2026-05-06 15:56:27 -04:00

75 lines
2.6 KiB
Go

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)
}
}