diff --git a/momo_exporter.go b/momo_exporter.go index 0029754..2f6c70a 100644 --- a/momo_exporter.go +++ b/momo_exporter.go @@ -102,6 +102,9 @@ func (e *Exporter) Describe(ch chan<- *prometheus.Desc) { for _, m := range dataChannelMetrics { ch <- m.Desc } + for _, m := range inboundRTPMetrics { + ch <- m.Desc + } for _, m := range outboundRTPMetrics { ch <- m.Desc } @@ -198,6 +201,8 @@ func (e *Exporter) parseStats(stats interface{}, ch chan<- prometheus.Metric) { switch t { case "data-channel": e.exportDataChannelMetrics(s, ch) + case "inbound-rtp": + e.exportInboundRTPMetrics(s, ch) case "outbound-rtp": e.exportOutboundRTPMetrics(s, ch) case "peer-connection": @@ -217,6 +222,18 @@ func (e *Exporter) exportDataChannelMetrics(m dproxy.Proxy, ch chan<- prometheus } } +func (e *Exporter) exportInboundRTPMetrics(m dproxy.Proxy, ch chan<- prometheus.Metric) { + id, _ := m.M("id").String() + codecID, _ := m.M("codecId").String() + decoderImplementation, _ := m.M("decoderImplementation").String() + kind, _ := m.M("kind").String() + + for key, metric := range inboundRTPMetrics { + val, _ := m.M(strcase.ToLowerCamel(key)).Float64() + ch <- prometheus.MustNewConstMetric(metric.Desc, metric.Type, val, id, codecID, decoderImplementation, kind) + } +} + func (e *Exporter) exportOutboundRTPMetrics(m dproxy.Proxy, ch chan<- prometheus.Metric) { id, _ := m.M("id").String() codecID, _ := m.M("codecId").String() @@ -260,6 +277,27 @@ var ( "messagesReceived": newDataChannelMetric("messages_received_total", "Total number of API \"message\" events received.", prometheus.CounterValue, nil), } + // https://www.w3.org/TR/webrtc-stats/#dom-rtcinboundrtpstreamstats + inboundRTPLabelNames = []string{"id", "codecId", "decoderImplementation", "kind"} + inboundRTPMetrics = metrics{ + "bytesReceived": newInboundRTPMetric("bytes_received_total", "Total number of bytes received for this SSRC.", prometheus.CounterValue, nil), + "headerBytesReceived": newInboundRTPMetric("header_bytes_received_total", "Total number of RTP header and padding bytes received for this SSRC.", prometheus.CounterValue, nil), + "packetsReceived": newInboundRTPMetric("packets_received_total", "Total number of RTP packets received for this SSRC.", prometheus.CounterValue, nil), + "framesReceived": newInboundRTPMetric("frames_received_total", "Total number of complete frames received on this RTP stream.", prometheus.CounterValue, nil), + "firCount": newInboundRTPMetric("fir_count_total", "Total number of Full Intra Request (FIR) packets sent by this receiver.", prometheus.CounterValue, nil), + "pliCount": newInboundRTPMetric("pli_count_total", "Total number of Picture Loss Indication (PLI) packets sent by this receiver.", prometheus.CounterValue, nil), + "sliCount": newInboundRTPMetric("sli_count_total", "Total number of Slice Loss Indication (SLI) packets sent by this receiver.", prometheus.CounterValue, nil), + "nackCount": newInboundRTPMetric("nack_count_total", "Total number of Negative ACKnowledgement (NACK) packets sent by this receiver.", prometheus.CounterValue, nil), + "qpSum": newInboundRTPMetric("qp_sum", "Sum of the QP values of frames decoded by this receiver.", prometheus.CounterValue, nil), + "framesDecoded": newInboundRTPMetric("frames_decoded_total", "Total number of frames correctly decoded for this RTP stream.", prometheus.CounterValue, nil), + "keyFramesDecoded": newInboundRTPMetric("key_frames_decoded_total", "Total number of key frames successfully decoded for this RTP media stream.", prometheus.CounterValue, nil), + "totalDecodeTime": newInboundRTPMetric("decode_time_total", "Total number of seconds that have been spent decoding the framesDecoded frames of this stream.", prometheus.CounterValue, nil), + "frameWidth": newInboundRTPMetric("frame_width", "Width of the last decoded frame.", prometheus.GaugeValue, nil), + "frameHeight": newInboundRTPMetric("frame_height", "Height of the last decoded frame.", prometheus.GaugeValue, nil), + "framesPerSecond": newInboundRTPMetric("frames_per_second", "Number of decoded frames in the last second.", prometheus.GaugeValue, nil), + "totalSamplesReceived": newInboundRTPMetric("samples_received_total", "Total number of samples that have been received on this RTP stream.", prometheus.CounterValue, nil), + } + // https://www.w3.org/TR/webrtc-stats/#dom-rtcoutboundrtpstreamstats outboundRTPLabelNames = []string{"id", "codecId", "encoderImplementation", "kind", "mediaSourceId"} outboundRTPMetrics = metrics{ @@ -319,6 +357,10 @@ func newDataChannelMetric(metricName string, docString string, t prometheus.Valu return newMetric("datachannel", metricName, docString, t, dataChannelLabelNames, constLabels) } +func newInboundRTPMetric(metricName string, docString string, t prometheus.ValueType, constLabels prometheus.Labels) metricInfo { + return newMetric("inbound_rtp", metricName, docString, t, inboundRTPLabelNames, constLabels) +} + func newOutboundRTPMetric(metricName string, docString string, t prometheus.ValueType, constLabels prometheus.Labels) metricInfo { return newMetric("outbound_rtp", metricName, docString, t, outboundRTPLabelNames, constLabels) } diff --git a/momo_exporter_test.go b/momo_exporter_test.go index 4ba77b4..a4ae270 100644 --- a/momo_exporter_test.go +++ b/momo_exporter_test.go @@ -76,6 +76,48 @@ func TestEmptyStats(t *testing.T) { compare(t, resp, "empty_stats") } +func TestInboundRTP(t *testing.T) { + resp := `{ + "environment": "[x86_64] macOS Version 10.15.7 (Build 19H15)", + "libwebrtc": "Shiguredo-Build M88.4324@{#3} (88.4324.3.0 b15b2915)", + "stats": [ + { + "bytesReceived": 10278549, + "codecId": "RTCCodec_video_qDqHgY_Inbound_120", + "decoderImplementation": "libvpx", + "firCount": 0, + "frameHeight": 720, + "frameWidth": 1280, + "framesDecoded": 2111, + "framesDropped": 0, + "framesPerSecond": 14, + "framesReceived": 2112, + "headerBytesReceived": 156448, + "id": "RTCInboundRTPVideoStream_2189915641", + "isRemote": false, + "keyFramesDecoded": 1, + "kind": "video", + "lastPacketReceivedTimestamp": 4270.359, + "mediaType": "video", + "nackCount": 67, + "packetsLost": 0, + "packetsReceived": 9778, + "pliCount": 0, + "qpSum": 291917, + "ssrc": 2189915641, + "timestamp": 1609585297509136, + "totalDecodeTime": 3.831, + "totalInterFrameDelay": 160.8540000000006, + "totalSquaredInterFrameDelay": 26.77570400000011, + "trackId": "RTCMediaStreamTrack_receiver_3", + "transportId": "RTCTransport_video_Nl0AIE_1", + "type": "inbound-rtp" + } + ] + }` + compare(t, resp, "inbound_rtp") +} + func TestOutboundRTP(t *testing.T) { resp := `{ "version": "WebRTC Native Client Momo 2020.11 (db9d97e)", diff --git a/test/inbound_rtp.metrics b/test/inbound_rtp.metrics new file mode 100644 index 0000000..2cb042a --- /dev/null +++ b/test/inbound_rtp.metrics @@ -0,0 +1,60 @@ +# HELP momo_exporter_json_parse_failures_total Number of failures while parsing JSON. +# TYPE momo_exporter_json_parse_failures_total counter +momo_exporter_json_parse_failures_total 0 +# HELP momo_exporter_scrapes_total Current total momo scrapes. +# TYPE momo_exporter_scrapes_total counter +momo_exporter_scrapes_total 1 +# HELP momo_inbound_rtp_bytes_received_total Total number of bytes received for this SSRC. +# TYPE momo_inbound_rtp_bytes_received_total counter +momo_inbound_rtp_bytes_received_total{codecId="RTCCodec_video_qDqHgY_Inbound_120",decoderImplementation="libvpx",id="RTCInboundRTPVideoStream_2189915641",kind="video"} 1.0278549e+07 +# HELP momo_inbound_rtp_decode_time_total Total number of seconds that have been spent decoding the framesDecoded frames of this stream. +# TYPE momo_inbound_rtp_decode_time_total counter +momo_inbound_rtp_decode_time_total{codecId="RTCCodec_video_qDqHgY_Inbound_120",decoderImplementation="libvpx",id="RTCInboundRTPVideoStream_2189915641",kind="video"} 3.831 +# HELP momo_inbound_rtp_fir_count_total Total number of Full Intra Request (FIR) packets sent by this receiver. +# TYPE momo_inbound_rtp_fir_count_total counter +momo_inbound_rtp_fir_count_total{codecId="RTCCodec_video_qDqHgY_Inbound_120",decoderImplementation="libvpx",id="RTCInboundRTPVideoStream_2189915641",kind="video"} 0 +# HELP momo_inbound_rtp_frame_height Height of the last decoded frame. +# TYPE momo_inbound_rtp_frame_height gauge +momo_inbound_rtp_frame_height{codecId="RTCCodec_video_qDqHgY_Inbound_120",decoderImplementation="libvpx",id="RTCInboundRTPVideoStream_2189915641",kind="video"} 720 +# HELP momo_inbound_rtp_frame_width Width of the last decoded frame. +# TYPE momo_inbound_rtp_frame_width gauge +momo_inbound_rtp_frame_width{codecId="RTCCodec_video_qDqHgY_Inbound_120",decoderImplementation="libvpx",id="RTCInboundRTPVideoStream_2189915641",kind="video"} 1280 +# HELP momo_inbound_rtp_frames_decoded_total Total number of frames correctly decoded for this RTP stream. +# TYPE momo_inbound_rtp_frames_decoded_total counter +momo_inbound_rtp_frames_decoded_total{codecId="RTCCodec_video_qDqHgY_Inbound_120",decoderImplementation="libvpx",id="RTCInboundRTPVideoStream_2189915641",kind="video"} 2111 +# HELP momo_inbound_rtp_frames_per_second Number of decoded frames in the last second. +# TYPE momo_inbound_rtp_frames_per_second gauge +momo_inbound_rtp_frames_per_second{codecId="RTCCodec_video_qDqHgY_Inbound_120",decoderImplementation="libvpx",id="RTCInboundRTPVideoStream_2189915641",kind="video"} 14 +# HELP momo_inbound_rtp_frames_received_total Total number of complete frames received on this RTP stream. +# TYPE momo_inbound_rtp_frames_received_total counter +momo_inbound_rtp_frames_received_total{codecId="RTCCodec_video_qDqHgY_Inbound_120",decoderImplementation="libvpx",id="RTCInboundRTPVideoStream_2189915641",kind="video"} 2112 +# HELP momo_inbound_rtp_header_bytes_received_total Total number of RTP header and padding bytes received for this SSRC. +# TYPE momo_inbound_rtp_header_bytes_received_total counter +momo_inbound_rtp_header_bytes_received_total{codecId="RTCCodec_video_qDqHgY_Inbound_120",decoderImplementation="libvpx",id="RTCInboundRTPVideoStream_2189915641",kind="video"} 156448 +# HELP momo_inbound_rtp_key_frames_decoded_total Total number of key frames successfully decoded for this RTP media stream. +# TYPE momo_inbound_rtp_key_frames_decoded_total counter +momo_inbound_rtp_key_frames_decoded_total{codecId="RTCCodec_video_qDqHgY_Inbound_120",decoderImplementation="libvpx",id="RTCInboundRTPVideoStream_2189915641",kind="video"} 1 +# HELP momo_inbound_rtp_nack_count_total Total number of Negative ACKnowledgement (NACK) packets sent by this receiver. +# TYPE momo_inbound_rtp_nack_count_total counter +momo_inbound_rtp_nack_count_total{codecId="RTCCodec_video_qDqHgY_Inbound_120",decoderImplementation="libvpx",id="RTCInboundRTPVideoStream_2189915641",kind="video"} 67 +# HELP momo_inbound_rtp_packets_received_total Total number of RTP packets received for this SSRC. +# TYPE momo_inbound_rtp_packets_received_total counter +momo_inbound_rtp_packets_received_total{codecId="RTCCodec_video_qDqHgY_Inbound_120",decoderImplementation="libvpx",id="RTCInboundRTPVideoStream_2189915641",kind="video"} 9778 +# HELP momo_inbound_rtp_pli_count_total Total number of Picture Loss Indication (PLI) packets sent by this receiver. +# TYPE momo_inbound_rtp_pli_count_total counter +momo_inbound_rtp_pli_count_total{codecId="RTCCodec_video_qDqHgY_Inbound_120",decoderImplementation="libvpx",id="RTCInboundRTPVideoStream_2189915641",kind="video"} 0 +# HELP momo_inbound_rtp_qp_sum Sum of the QP values of frames decoded by this receiver. +# TYPE momo_inbound_rtp_qp_sum counter +momo_inbound_rtp_qp_sum{codecId="RTCCodec_video_qDqHgY_Inbound_120",decoderImplementation="libvpx",id="RTCInboundRTPVideoStream_2189915641",kind="video"} 291917 +# HELP momo_inbound_rtp_samples_received_total Total number of samples that have been received on this RTP stream. +# TYPE momo_inbound_rtp_samples_received_total counter +momo_inbound_rtp_samples_received_total{codecId="RTCCodec_video_qDqHgY_Inbound_120",decoderImplementation="libvpx",id="RTCInboundRTPVideoStream_2189915641",kind="video"} 0 +# HELP momo_inbound_rtp_sli_count_total Total number of Slice Loss Indication (SLI) packets sent by this receiver. +# TYPE momo_inbound_rtp_sli_count_total counter +momo_inbound_rtp_sli_count_total{codecId="RTCCodec_video_qDqHgY_Inbound_120",decoderImplementation="libvpx",id="RTCInboundRTPVideoStream_2189915641",kind="video"} 0 +# HELP momo_up Was the last scrape of WebRTC Native Client Momo successful. +# TYPE momo_up gauge +momo_up 1 +# HELP momo_version_info WebRTC Native Client Momo version info. +# TYPE momo_version_info gauge +momo_version_info{environment="[x86_64] macOS Version 10.15.7 (Build 19H15)",libwebrtc="Shiguredo-Build M88.4324@{#3} (88.4324.3.0 b15b2915)",version=""} 1