package core import ( "bufio" "context" "crypto/tls" "io" "net/http" "net/url" "os" "sync" "testing" "time" "github.com/bluenviron/gortmplib" "github.com/bluenviron/gortsplib/v5" "github.com/bluenviron/gortsplib/v5/pkg/description" "github.com/bluenviron/gortsplib/v5/pkg/format" "github.com/bluenviron/mediacommon/v2/pkg/formats/mpegts" srt "github.com/datarhei/gosrt" "github.com/pion/rtp" pwebrtc "github.com/pion/webrtc/v4" "github.com/stretchr/testify/require" "github.com/bluenviron/mediamtx/internal/protocols/webrtc" "github.com/bluenviron/mediamtx/internal/protocols/whip" "github.com/bluenviron/mediamtx/internal/test" ) func httpPullFile(t *testing.T, hc *http.Client, u string) []byte { res, err := hc.Get(u) require.NoError(t, err) defer res.Body.Close() if res.StatusCode != http.StatusOK { t.Errorf("bad status code: %v", res.StatusCode) } byts, err := io.ReadAll(res.Body) require.NoError(t, err) return byts } func TestMetrics(t *testing.T) { serverCertFpath, err := test.CreateTempFile(test.TLSCertPub) require.NoError(t, err) defer os.Remove(serverCertFpath) serverKeyFpath, err := test.CreateTempFile(test.TLSCertKey) require.NoError(t, err) defer os.Remove(serverKeyFpath) p, ok := newInstance("api: yes\n" + "hlsAlwaysRemux: yes\n" + "metrics: yes\n" + "webrtcServerCert: " + serverCertFpath + "\n" + "webrtcServerKey: " + serverKeyFpath + "\n" + "rtspEncryption: optional\n" + "rtspServerCert: " + serverCertFpath + "\n" + "rtspServerKey: " + serverKeyFpath + "\n" + "rtmpEncryption: optional\n" + "rtmpServerCert: " + serverCertFpath + "\n" + "rtmpServerKey: " + serverKeyFpath + "\n" + "paths:\n" + " all_others:\n") require.Equal(t, true, ok) defer p.Close() tr := &http.Transport{} defer tr.CloseIdleConnections() hc := &http.Client{Transport: tr} t.Run("initial", func(t *testing.T) { bo := httpPullFile(t, hc, "http://localhost:9998/metrics") require.Equal(t, `paths 0 paths_bytes_received 0 paths_bytes_sent 0 paths_readers 0 hls_muxers 0 hls_muxers_bytes_sent 0 rtsp_conns 0 rtsp_conns_bytes_received 0 rtsp_conns_bytes_sent 0 rtsp_sessions 0 rtsp_sessions_bytes_received 0 rtsp_sessions_bytes_sent 0 rtsp_sessions_rtp_packets_received 0 rtsp_sessions_rtp_packets_sent 0 rtsp_sessions_rtp_packets_lost 0 rtsp_sessions_rtp_packets_in_error 0 rtsp_sessions_rtp_packets_jitter 0 rtsp_sessions_rtcp_packets_received 0 rtsp_sessions_rtcp_packets_sent 0 rtsp_sessions_rtcp_packets_in_error 0 rtsps_conns 0 rtsps_conns_bytes_received 0 rtsps_conns_bytes_sent 0 rtsps_sessions 0 rtsps_sessions_bytes_received 0 rtsps_sessions_bytes_sent 0 rtsps_sessions_rtp_packets_received 0 rtsps_sessions_rtp_packets_sent 0 rtsps_sessions_rtp_packets_lost 0 rtsps_sessions_rtp_packets_in_error 0 rtsps_sessions_rtp_packets_jitter 0 rtsps_sessions_rtcp_packets_received 0 rtsps_sessions_rtcp_packets_sent 0 rtsps_sessions_rtcp_packets_in_error 0 rtmp_conns 0 rtmp_conns_bytes_received 0 rtmp_conns_bytes_sent 0 rtmps_conns 0 rtmps_conns_bytes_received 0 rtmps_conns_bytes_sent 0 srt_conns 0 srt_conns_packets_sent 0 srt_conns_packets_received 0 srt_conns_packets_sent_unique 0 srt_conns_packets_received_unique 0 srt_conns_packets_send_loss 0 srt_conns_packets_received_loss 0 srt_conns_packets_retrans 0 srt_conns_packets_received_retrans 0 srt_conns_packets_sent_ack 0 srt_conns_packets_received_ack 0 srt_conns_packets_sent_nak 0 srt_conns_packets_received_nak 0 srt_conns_packets_sent_km 0 srt_conns_packets_received_km 0 srt_conns_us_snd_duration 0 srt_conns_packets_send_drop 0 srt_conns_packets_received_drop 0 srt_conns_packets_received_undecrypt 0 srt_conns_bytes_sent 0 srt_conns_bytes_received 0 srt_conns_bytes_sent_unique 0 srt_conns_bytes_received_unique 0 srt_conns_bytes_received_loss 0 srt_conns_bytes_retrans 0 srt_conns_bytes_received_retrans 0 srt_conns_bytes_send_drop 0 srt_conns_bytes_received_drop 0 srt_conns_bytes_received_undecrypt 0 srt_conns_us_packets_send_period 0 srt_conns_packets_flow_window 0 srt_conns_packets_flight_size 0 srt_conns_ms_rtt 0 srt_conns_mbps_send_rate 0 srt_conns_mbps_receive_rate 0 srt_conns_mbps_link_capacity 0 srt_conns_bytes_avail_send_buf 0 srt_conns_bytes_avail_receive_buf 0 srt_conns_mbps_max_bw 0 srt_conns_bytes_mss 0 srt_conns_packets_send_buf 0 srt_conns_bytes_send_buf 0 srt_conns_ms_send_buf 0 srt_conns_ms_send_tsb_pd_delay 0 srt_conns_packets_receive_buf 0 srt_conns_bytes_receive_buf 0 srt_conns_ms_receive_buf 0 srt_conns_ms_receive_tsb_pd_delay 0 srt_conns_packets_reorder_tolerance 0 srt_conns_packets_received_avg_belated_time 0 srt_conns_packets_send_loss_rate 0 srt_conns_packets_received_loss_rate 0 webrtc_sessions 0 webrtc_sessions_bytes_received 0 webrtc_sessions_bytes_sent 0 webrtc_sessions_rtp_packets_received 0 webrtc_sessions_rtp_packets_sent 0 webrtc_sessions_rtp_packets_lost 0 webrtc_sessions_rtp_packets_jitter 0 webrtc_sessions_rtcp_packets_received 0 webrtc_sessions_rtcp_packets_sent 0 `, string(bo)) }) t.Run("with data", func(t *testing.T) { terminate := make(chan struct{}) var wg sync.WaitGroup wg.Add(6) go func() { defer wg.Done() source := gortsplib.Client{} err2 := source.StartRecording("rtsp://localhost:8554/rtsp_path", &description.Session{Medias: []*description.Media{test.UniqueMediaH264()}}) require.NoError(t, err2) defer source.Close() <-terminate }() go func() { defer wg.Done() source2 := gortsplib.Client{TLSConfig: &tls.Config{InsecureSkipVerify: true}} err2 := source2.StartRecording("rtsps://localhost:8322/rtsps_path", &description.Session{Medias: []*description.Media{test.UniqueMediaH264()}}) require.NoError(t, err2) defer source2.Close() <-terminate }() go func() { defer wg.Done() u, err2 := url.Parse("rtmp://localhost:1935/rtmp_path") require.NoError(t, err2) conn := &gortmplib.Client{ URL: u, Publish: true, } err2 = conn.Initialize(context.Background()) require.NoError(t, err2) defer conn.Close() w := &gortmplib.Writer{ Conn: conn, Tracks: []format.Format{test.FormatH264}, } err2 = w.Initialize() require.NoError(t, err2) err2 = w.WriteH264(test.FormatH264, 2*time.Second, 2*time.Second, [][]byte{{5, 2, 3, 4}}) require.NoError(t, err2) <-terminate }() go func() { defer wg.Done() u, err2 := url.Parse("rtmps://localhost:1936/rtmps_path") require.NoError(t, err2) conn := &gortmplib.Client{ URL: u, TLSConfig: &tls.Config{InsecureSkipVerify: true}, Publish: true, } err2 = conn.Initialize(context.Background()) require.NoError(t, err2) defer conn.Close() w := &gortmplib.Writer{ Conn: conn, Tracks: []format.Format{test.FormatH264}, } err2 = w.Initialize() require.NoError(t, err2) err2 = w.WriteH264(test.FormatH264, 2*time.Second, 2*time.Second, [][]byte{{5, 2, 3, 4}}) require.NoError(t, err2) <-terminate }() go func() { defer wg.Done() su, err2 := url.Parse("http://localhost:8889/webrtc_path/whip") require.NoError(t, err2) tr2 := &http.Transport{} defer tr2.CloseIdleConnections() hc2 := &http.Client{Transport: tr2} track := &webrtc.OutgoingTrack{ Caps: pwebrtc.RTPCodecCapability{ MimeType: pwebrtc.MimeTypeH264, ClockRate: 90000, SDPFmtpLine: "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f", }, } s := &whip.Client{ HTTPClient: hc2, URL: su, Log: test.NilLogger, Publish: true, OutgoingTracks: []*webrtc.OutgoingTrack{track}, } err2 = s.Initialize(context.Background()) require.NoError(t, err2) defer checkClose(t, s.Close) err2 = track.WriteRTP(&rtp.Packet{ Header: rtp.Header{ Version: 2, Marker: true, PayloadType: 96, SequenceNumber: 123, Timestamp: 45343, SSRC: 563423, }, Payload: []byte{1}, }) require.NoError(t, err2) <-terminate }() go func() { defer wg.Done() srtConf := srt.DefaultConfig() address, err2 := srtConf.UnmarshalURL("srt://localhost:8890?streamid=publish:srt_path") require.NoError(t, err2) err2 = srtConf.Validate() require.NoError(t, err2) publisher, err2 := srt.Dial("srt", address, srtConf) require.NoError(t, err2) defer publisher.Close() track := &mpegts.Track{ Codec: &mpegts.CodecH264{}, } bw := bufio.NewWriter(publisher) w := &mpegts.Writer{W: bw, Tracks: []*mpegts.Track{track}} err2 = w.Initialize() require.NoError(t, err2) err2 = w.WriteH264(track, 0, 0, [][]byte{ test.FormatH264.SPS, test.FormatH264.PPS, {0x05, 1}, // IDR }) require.NoError(t, err2) err2 = bw.Flush() require.NoError(t, err2) <-terminate }() time.Sleep(500*time.Millisecond + 2*time.Second) bo := httpPullFile(t, hc, "http://localhost:9998/metrics") require.Regexp(t, `^paths\{name=".*?",state="ready"\} 1`+"\n"+ `paths_bytes_received\{name=".*?",state="ready"\} [0-9]+`+"\n"+ `paths_bytes_sent\{name=".*?",state="ready"\} [0-9]+`+"\n"+ `paths_readers\{name=".*?",state="ready"\} [0-9]+`+"\n"+ `paths\{name=".*?",state="ready"\} 1`+"\n"+ `paths_bytes_received\{name=".*?",state="ready"\} [0-9]+`+"\n"+ `paths_bytes_sent\{name=".*?",state="ready"\} [0-9]+`+"\n"+ `paths_readers\{name=".*?",state="ready"\} [0-9]+`+"\n"+ `paths\{name=".*?",state="ready"\} 1`+"\n"+ `paths_bytes_received\{name=".*?",state="ready"\} [0-9]+`+"\n"+ `paths_bytes_sent\{name=".*?",state="ready"\} [0-9]+`+"\n"+ `paths_readers\{name=".*?",state="ready"\} [0-9]+`+"\n"+ `paths\{name=".*?",state="ready"\} 1`+"\n"+ `paths_bytes_received\{name=".*?",state="ready"\} [0-9]+`+"\n"+ `paths_bytes_sent\{name=".*?",state="ready"\} [0-9]+`+"\n"+ `paths_readers\{name=".*?",state="ready"\} [0-9]+`+"\n"+ `paths\{name=".*?",state="ready"\} 1`+"\n"+ `paths_bytes_received\{name=".*?",state="ready"\} [0-9]+`+"\n"+ `paths_bytes_sent\{name=".*?",state="ready"\} [0-9]+`+"\n"+ `paths_readers\{name=".*?",state="ready"\} [0-9]+`+"\n"+ `paths\{name=".*?",state="ready"\} 1`+"\n"+ `paths_bytes_received\{name=".*?",state="ready"\} [0-9]+`+"\n"+ `paths_bytes_sent\{name=".*?",state="ready"\} [0-9]+`+"\n"+ `paths_readers\{name=".*?",state="ready"\} [0-9]+`+"\n"+ `hls_muxers\{name=".*?"\} 1`+"\n"+ `hls_muxers_bytes_sent\{name=".*?"\} 0`+"\n"+ `hls_muxers\{name=".*?"\} 1`+"\n"+ `hls_muxers_bytes_sent\{name=".*?"\} 0`+"\n"+ `hls_muxers\{name=".*?"\} 1`+"\n"+ `hls_muxers_bytes_sent\{name=".*?"\} 0`+"\n"+ `hls_muxers\{name=".*?"\} 1`+"\n"+ `hls_muxers_bytes_sent\{name=".*?"\} 0`+"\n"+ `hls_muxers\{name=".*?"\} 1`+"\n"+ `hls_muxers_bytes_sent\{name=".*?"\} 0`+"\n"+ `hls_muxers\{name=".*?"\} 1`+"\n"+ `hls_muxers_bytes_sent\{name=".*?"\} 0`+"\n"+ `rtsp_conns\{id=".*?"\} 1`+"\n"+ `rtsp_conns_bytes_received\{id=".*?"\} [0-9]+`+"\n"+ `rtsp_conns_bytes_sent\{id=".*?"\} [0-9]+`+"\n"+ `rtsp_sessions\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} 1`+"\n"+ `rtsp_sessions_bytes_received\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} 0`+"\n"+ `rtsp_sessions_bytes_sent\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `rtsp_sessions_rtp_packets_received\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `rtsp_sessions_rtp_packets_sent\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `rtsp_sessions_rtp_packets_lost\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `rtsp_sessions_rtp_packets_in_error\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `rtsp_sessions_rtp_packets_jitter\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `rtsp_sessions_rtcp_packets_received\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `rtsp_sessions_rtcp_packets_sent\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `rtsp_sessions_rtcp_packets_in_error\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `rtsps_conns\{id=".*?"\} 1`+"\n"+ `rtsps_conns_bytes_received\{id=".*?"\} [0-9]+`+"\n"+ `rtsps_conns_bytes_sent\{id=".*?"\} [0-9]+`+"\n"+ `rtsps_sessions\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} 1`+"\n"+ `rtsps_sessions_bytes_received\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} 0`+"\n"+ `rtsps_sessions_bytes_sent\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `rtsps_sessions_rtp_packets_received\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `rtsps_sessions_rtp_packets_sent\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `rtsps_sessions_rtp_packets_lost\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `rtsps_sessions_rtp_packets_in_error\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `rtsps_sessions_rtp_packets_jitter\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `rtsps_sessions_rtcp_packets_received\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `rtsps_sessions_rtcp_packets_sent\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `rtsps_sessions_rtcp_packets_in_error\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `rtmp_conns\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} 1`+"\n"+ `rtmp_conns_bytes_received\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `rtmp_conns_bytes_sent\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `rtmps_conns\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} 1`+"\n"+ `rtmps_conns_bytes_received\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `rtmps_conns_bytes_sent\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} 1`+"\n"+ `srt_conns_packets_sent\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_received\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_sent_unique\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_received_unique\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} 1`+"\n"+ `srt_conns_packets_send_loss\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_received_loss\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_retrans\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_received_retrans\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_sent_ack\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_received_ack\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_sent_nak\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_received_nak\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_sent_km\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_received_km\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_us_snd_duration\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_send_drop\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_received_drop\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_received_undecrypt\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_bytes_sent\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} 0`+"\n"+ `srt_conns_bytes_received\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_bytes_sent_unique\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_bytes_received_unique\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_bytes_received_loss\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_bytes_retrans\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_bytes_received_retrans\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_bytes_send_drop\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_bytes_received_drop\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_bytes_received_undecrypt\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_us_packets_send_period\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} \d+\.\d+`+"\n"+ `srt_conns_packets_flow_window\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_flight_size\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_ms_rtt\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} \d+\.\d+`+"\n"+ `srt_conns_mbps_send_rate\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_mbps_receive_rate\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_mbps_link_capacity\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_bytes_avail_send_buf\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_bytes_avail_receive_buf\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_mbps_max_bw\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} -1`+"\n"+ `srt_conns_bytes_mss\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_send_buf\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_bytes_send_buf\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_ms_send_buf\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_ms_send_tsb_pd_delay\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_receive_buf\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_bytes_receive_buf\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_ms_receive_buf\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_ms_receive_tsb_pd_delay\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_reorder_tolerance\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_received_avg_belated_time\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_send_loss_rate\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `srt_conns_packets_received_loss_rate\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `webrtc_sessions\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} 1`+"\n"+ `webrtc_sessions_bytes_received\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `webrtc_sessions_bytes_sent\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `webrtc_sessions_rtp_packets_received\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `webrtc_sessions_rtp_packets_sent\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `webrtc_sessions_rtp_packets_lost\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `webrtc_sessions_rtp_packets_jitter\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `webrtc_sessions_rtcp_packets_received\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ `webrtc_sessions_rtcp_packets_sent\{id=".*?",path=".*?",remoteAddr=".*?",state="publish"\} [0-9]+`+"\n"+ "$", string(bo)) close(terminate) wg.Wait() }) t.Run("servers disabled", func(t *testing.T) { httpRequest(t, hc, http.MethodPatch, "http://localhost:9997/v3/config/global/patch", map[string]interface{}{ "rtsp": false, "rtmp": false, "srt": false, "hls": false, "webrtc": false, }, nil) time.Sleep(500 * time.Millisecond) bo := httpPullFile(t, hc, "http://localhost:9998/metrics") require.Equal(t, "paths 0\n"+ "paths_bytes_received 0\n"+ "paths_bytes_sent 0\n"+ "paths_readers 0\n", string(bo)) }) }