From 435d5e4f35ffd433e5cf9a6b372c9de662a9afa9 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Sun, 6 Aug 2023 23:10:02 +0200 Subject: [PATCH] Move the SRT Prometheus metrics into its own class, for reusability. --- meson.build | 2 +- nageru/mixer.cpp | 187 +-------------------------------------- nageru/mixer.h | 54 +----------- nageru/srt_metrics.cpp | 193 +++++++++++++++++++++++++++++++++++++++++ nageru/srt_metrics.h | 67 ++++++++++++++ 5 files changed, 269 insertions(+), 234 deletions(-) create mode 100644 nageru/srt_metrics.cpp create mode 100644 nageru/srt_metrics.h diff --git a/meson.build b/meson.build index e192971..3c139c7 100644 --- a/meson.build +++ b/meson.build @@ -212,7 +212,7 @@ nageru_link_with += audio # Mixer objects. nageru_srcs += ['nageru/chroma_subsampler.cpp', 'nageru/v210_converter.cpp', 'nageru/mixer.cpp', 'nageru/pbo_frame_allocator.cpp', 'nageru/theme.cpp', 'nageru/scene.cpp', 'nageru/image_input.cpp', 'nageru/alsa_output.cpp', - 'nageru/timecode_renderer.cpp', 'nageru/tweaked_inputs.cpp', 'nageru/mjpeg_encoder.cpp'] + 'nageru/timecode_renderer.cpp', 'nageru/tweaked_inputs.cpp', 'nageru/mjpeg_encoder.cpp', 'nageru/srt_metrics.cpp'] # Streaming and encoding objects (largely the set that is shared between Nageru and Kaeru). stream_srcs = ['nageru/quicksync_encoder.cpp', 'nageru/video_encoder.cpp', diff --git a/nageru/mixer.cpp b/nageru/mixer.cpp index 7635478..3ca249b 100644 --- a/nageru/mixer.cpp +++ b/nageru/mixer.cpp @@ -679,71 +679,7 @@ void Mixer::configure_card(unsigned card_index, CaptureInterface *capture, CardT global_metrics.remove_if_exists("input_frame_rate_den", labels); global_metrics.remove_if_exists("input_sample_rate_hz", labels); - // SRT metrics. - - // Global measurements (counters). - global_metrics.remove_if_exists("srt_uptime_seconds", labels); - global_metrics.remove_if_exists("srt_send_duration_seconds", labels); - global_metrics.remove_if_exists("srt_sent_bytes", labels); - global_metrics.remove_if_exists("srt_received_bytes", labels); - - vector> packet_labels = card->labels; - packet_labels.emplace_back("type", "normal"); - global_metrics.remove_if_exists("srt_sent_packets", packet_labels); - global_metrics.remove_if_exists("srt_received_packets", packet_labels); - - packet_labels.back().second = "lost"; - global_metrics.remove_if_exists("srt_sent_packets", packet_labels); - global_metrics.remove_if_exists("srt_received_packets", packet_labels); - - packet_labels.back().second = "retransmitted"; - global_metrics.remove_if_exists("srt_sent_packets", packet_labels); - global_metrics.remove_if_exists("srt_sent_bytes", packet_labels); - - packet_labels.back().second = "ack"; - global_metrics.remove_if_exists("srt_sent_packets", packet_labels); - global_metrics.remove_if_exists("srt_received_packets", packet_labels); - - packet_labels.back().second = "nak"; - global_metrics.remove_if_exists("srt_sent_packets", packet_labels); - global_metrics.remove_if_exists("srt_received_packets", packet_labels); - - packet_labels.back().second = "dropped"; - global_metrics.remove_if_exists("srt_sent_packets", packet_labels); - global_metrics.remove_if_exists("srt_received_packets", packet_labels); - global_metrics.remove_if_exists("srt_sent_bytes", packet_labels); - global_metrics.remove_if_exists("srt_received_bytes", packet_labels); - - packet_labels.back().second = "undecryptable"; - global_metrics.remove_if_exists("srt_received_packets", packet_labels); - global_metrics.remove_if_exists("srt_received_bytes", packet_labels); - - global_metrics.remove_if_exists("srt_filter_sent_extra_packets", labels); - global_metrics.remove_if_exists("srt_filter_received_extra_packets", labels); - global_metrics.remove_if_exists("srt_filter_received_rebuilt_packets", labels); - global_metrics.remove_if_exists("srt_filter_received_lost_packets", labels); - - // Instant measurements (gauges). - global_metrics.remove_if_exists("srt_packet_sending_period_seconds", labels); - global_metrics.remove_if_exists("srt_flow_window_packets", labels); - global_metrics.remove_if_exists("srt_congestion_window_packets", labels); - global_metrics.remove_if_exists("srt_flight_size_packets", labels); - global_metrics.remove_if_exists("srt_rtt_seconds", labels); - global_metrics.remove_if_exists("srt_estimated_bandwidth_bits_per_second", labels); - global_metrics.remove_if_exists("srt_bandwidth_ceiling_bits_per_second", labels); - global_metrics.remove_if_exists("srt_send_buffer_available_bytes", labels); - global_metrics.remove_if_exists("srt_receive_buffer_available_bytes", labels); - global_metrics.remove_if_exists("srt_mss_bytes", labels); - - global_metrics.remove_if_exists("srt_sender_unacked_packets", labels); - global_metrics.remove_if_exists("srt_sender_unacked_bytes", labels); - global_metrics.remove_if_exists("srt_sender_unacked_timespan_seconds", labels); - global_metrics.remove_if_exists("srt_sender_delivery_delay_seconds", labels); - - global_metrics.remove_if_exists("srt_receiver_unacked_packets", labels); - global_metrics.remove_if_exists("srt_receiver_unacked_bytes", labels); - global_metrics.remove_if_exists("srt_receiver_unacked_timespan_seconds", labels); - global_metrics.remove_if_exists("srt_receiver_delivery_delay_seconds", labels); + card->srt_metrics.deinit(labels); } if (is_active) { @@ -792,69 +728,7 @@ void Mixer::configure_card(unsigned card_index, CaptureInterface *capture, CardT global_metrics.add("input_sample_rate_hz", labels, &card->metric_input_sample_rate_hz, Metrics::TYPE_GAUGE); if (is_srt_card) { - // Global measurements (counters). - global_metrics.add("srt_uptime_seconds", labels, &card->metric_srt_uptime_seconds); - global_metrics.add("srt_send_duration_seconds", labels, &card->metric_srt_send_duration_seconds); - global_metrics.add("srt_sent_bytes", labels, &card->metric_srt_sent_bytes); - global_metrics.add("srt_received_bytes", labels, &card->metric_srt_received_bytes); - - vector> packet_labels = labels; - packet_labels.emplace_back("type", "normal"); - global_metrics.add("srt_sent_packets", packet_labels, &card->metric_srt_sent_packets_normal); - global_metrics.add("srt_received_packets", packet_labels, &card->metric_srt_received_packets_normal); - - packet_labels.back().second = "lost"; - global_metrics.add("srt_sent_packets", packet_labels, &card->metric_srt_sent_packets_lost); - global_metrics.add("srt_received_packets", packet_labels, &card->metric_srt_received_packets_lost); - - packet_labels.back().second = "retransmitted"; - global_metrics.add("srt_sent_packets", packet_labels, &card->metric_srt_sent_packets_retransmitted); - global_metrics.add("srt_sent_bytes", packet_labels, &card->metric_srt_sent_bytes_retransmitted); - - packet_labels.back().second = "ack"; - global_metrics.add("srt_sent_packets", packet_labels, &card->metric_srt_sent_packets_ack); - global_metrics.add("srt_received_packets", packet_labels, &card->metric_srt_received_packets_ack); - - packet_labels.back().second = "nak"; - global_metrics.add("srt_sent_packets", packet_labels, &card->metric_srt_sent_packets_nak); - global_metrics.add("srt_received_packets", packet_labels, &card->metric_srt_received_packets_nak); - - packet_labels.back().second = "dropped"; - global_metrics.add("srt_sent_packets", packet_labels, &card->metric_srt_sent_packets_dropped); - global_metrics.add("srt_received_packets", packet_labels, &card->metric_srt_received_packets_dropped); - global_metrics.add("srt_sent_bytes", packet_labels, &card->metric_srt_sent_bytes_dropped); - global_metrics.add("srt_received_bytes", packet_labels, &card->metric_srt_received_bytes_dropped); - - packet_labels.back().second = "undecryptable"; - global_metrics.add("srt_received_packets", packet_labels, &card->metric_srt_received_packets_undecryptable); - global_metrics.add("srt_received_bytes", packet_labels, &card->metric_srt_received_bytes_undecryptable); - - global_metrics.add("srt_filter_sent_extra_packets", labels, &card->metric_srt_filter_sent_packets); - global_metrics.add("srt_filter_received_extra_packets", labels, &card->metric_srt_filter_received_extra_packets); - global_metrics.add("srt_filter_received_rebuilt_packets", labels, &card->metric_srt_filter_received_rebuilt_packets); - global_metrics.add("srt_filter_received_lost_packets", labels, &card->metric_srt_filter_received_lost_packets); - - // Instant measurements (gauges). - global_metrics.add("srt_packet_sending_period_seconds", labels, &card->metric_srt_packet_sending_period_seconds, Metrics::TYPE_GAUGE); - global_metrics.add("srt_flow_window_packets", labels, &card->metric_srt_flow_window_packets, Metrics::TYPE_GAUGE); - global_metrics.add("srt_congestion_window_packets", labels, &card->metric_srt_congestion_window_packets, Metrics::TYPE_GAUGE); - global_metrics.add("srt_flight_size_packets", labels, &card->metric_srt_flight_size_packets, Metrics::TYPE_GAUGE); - global_metrics.add("srt_rtt_seconds", labels, &card->metric_srt_rtt_seconds, Metrics::TYPE_GAUGE); - global_metrics.add("srt_estimated_bandwidth_bits_per_second", labels, &card->metric_srt_estimated_bandwidth_bits_per_second, Metrics::TYPE_GAUGE); - global_metrics.add("srt_bandwidth_ceiling_bits_per_second", labels, &card->metric_srt_bandwidth_ceiling_bits_per_second, Metrics::TYPE_GAUGE); - global_metrics.add("srt_send_buffer_available_bytes", labels, &card->metric_srt_send_buffer_available_bytes, Metrics::TYPE_GAUGE); - global_metrics.add("srt_receive_buffer_available_bytes", labels, &card->metric_srt_receive_buffer_available_bytes, Metrics::TYPE_GAUGE); - global_metrics.add("srt_mss_bytes", labels, &card->metric_srt_mss_bytes, Metrics::TYPE_GAUGE); - - global_metrics.add("srt_sender_unacked_packets", labels, &card->metric_srt_sender_unacked_packets, Metrics::TYPE_GAUGE); - global_metrics.add("srt_sender_unacked_bytes", labels, &card->metric_srt_sender_unacked_bytes, Metrics::TYPE_GAUGE); - global_metrics.add("srt_sender_unacked_timespan_seconds", labels, &card->metric_srt_sender_unacked_timespan_seconds, Metrics::TYPE_GAUGE); - global_metrics.add("srt_sender_delivery_delay_seconds", labels, &card->metric_srt_sender_delivery_delay_seconds, Metrics::TYPE_GAUGE); - - global_metrics.add("srt_receiver_unacked_packets", labels, &card->metric_srt_receiver_unacked_packets, Metrics::TYPE_GAUGE); - global_metrics.add("srt_receiver_unacked_bytes", labels, &card->metric_srt_receiver_unacked_bytes, Metrics::TYPE_GAUGE); - global_metrics.add("srt_receiver_unacked_timespan_seconds", labels, &card->metric_srt_receiver_unacked_timespan_seconds, Metrics::TYPE_GAUGE); - global_metrics.add("srt_receiver_delivery_delay_seconds", labels, &card->metric_srt_receiver_delivery_delay_seconds, Metrics::TYPE_GAUGE); + card->srt_metrics.init(labels); } card->labels = labels; @@ -1049,7 +923,7 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode, if (card->type == CardType::FFMPEG_INPUT) { int srt_sock = static_cast(card->capture.get())->get_srt_sock(); if (srt_sock != -1) { - update_srt_stats(srt_sock, card); + card->srt_metrics.update_srt_stats(srt_sock); } } #endif @@ -1726,7 +1600,7 @@ void Mixer::handle_hotplugged_cards() FFmpegCapture *capture = new FFmpegCapture(sock, stream_id); capture->set_card_index(free_card_index); configure_card(free_card_index, capture, CardType::FFMPEG_INPUT, /*output=*/nullptr, /*is_srt_card=*/true); - update_srt_stats(sock, card); // Initial zero stats. + card->srt_metrics.update_srt_stats(sock); // Initial zero stats. card->last_srt_stream_id = stream_id; card->jitter_history.clear(); capture->set_card_disconnected_callback(bind(&Mixer::bm_hotplug_remove, this, free_card_index)); @@ -2244,59 +2118,6 @@ void Mixer::start_srt() } #endif -#ifdef HAVE_SRT -void Mixer::update_srt_stats(int srt_sock, Mixer::CaptureCard *card) -{ - SRT_TRACEBSTATS stats; - srt_bistats(srt_sock, &stats, /*clear=*/0, /*instantaneous=*/1); - - card->metric_srt_uptime_seconds = stats.msTimeStamp * 1e-3; - card->metric_srt_send_duration_seconds = stats.usSndDurationTotal * 1e-6; - card->metric_srt_sent_bytes = stats.byteSentTotal; - card->metric_srt_received_bytes = stats.byteRecvTotal; - card->metric_srt_sent_packets_normal = stats.pktSentTotal; - card->metric_srt_received_packets_normal = stats.pktRecvTotal; - card->metric_srt_sent_packets_lost = stats.pktSndLossTotal; - card->metric_srt_received_packets_lost = stats.pktRcvLossTotal; - card->metric_srt_sent_packets_retransmitted = stats.pktRetransTotal; - card->metric_srt_sent_bytes_retransmitted = stats.byteRetransTotal; - card->metric_srt_sent_packets_ack = stats.pktSentACKTotal; - card->metric_srt_received_packets_ack = stats.pktRecvACKTotal; - card->metric_srt_sent_packets_nak = stats.pktSentNAKTotal; - card->metric_srt_received_packets_nak = stats.pktRecvNAKTotal; - card->metric_srt_sent_packets_dropped = stats.pktSndDropTotal; - card->metric_srt_received_packets_dropped = stats.pktRcvDropTotal; - card->metric_srt_sent_bytes_dropped = stats.byteSndDropTotal; - card->metric_srt_received_bytes_dropped = stats.byteRcvDropTotal; - card->metric_srt_received_packets_undecryptable = stats.pktRcvUndecryptTotal; - card->metric_srt_received_bytes_undecryptable = stats.byteRcvUndecryptTotal; - card->metric_srt_filter_sent_packets = stats.pktSndFilterExtraTotal; - card->metric_srt_filter_received_extra_packets = stats.pktRcvFilterExtraTotal; - card->metric_srt_filter_received_rebuilt_packets = stats.pktRcvFilterSupplyTotal; - card->metric_srt_filter_received_lost_packets = stats.pktRcvFilterLossTotal; - - // Gauges. - card->metric_srt_packet_sending_period_seconds = stats.usPktSndPeriod * 1e-6; - card->metric_srt_flow_window_packets = stats.pktFlowWindow; - card->metric_srt_congestion_window_packets = stats.pktCongestionWindow; - card->metric_srt_flight_size_packets = stats.pktFlightSize; - card->metric_srt_rtt_seconds = stats.msRTT * 1e-3; - card->metric_srt_estimated_bandwidth_bits_per_second = stats.mbpsBandwidth * 1e6; - card->metric_srt_bandwidth_ceiling_bits_per_second = stats.mbpsMaxBW * 1e6; - card->metric_srt_send_buffer_available_bytes = stats.byteAvailSndBuf; - card->metric_srt_receive_buffer_available_bytes = stats.byteAvailRcvBuf; - card->metric_srt_mss_bytes = stats.byteMSS; - card->metric_srt_sender_unacked_packets = stats.pktSndBuf; - card->metric_srt_sender_unacked_bytes = stats.byteSndBuf; - card->metric_srt_sender_unacked_timespan_seconds = stats.msSndBuf * 1e-3; - card->metric_srt_sender_delivery_delay_seconds = stats.msSndTsbPdDelay * 1e-3; - card->metric_srt_receiver_unacked_packets = stats.pktRcvBuf; - card->metric_srt_receiver_unacked_bytes = stats.byteRcvBuf; - card->metric_srt_receiver_unacked_timespan_seconds = stats.msRcvBuf * 1e-3; - card->metric_srt_receiver_delivery_delay_seconds = stats.msRcvTsbPdDelay * 1e-3; -} -#endif - string Mixer::description_for_card(unsigned card_index) { CaptureCard *card = &cards[card_index]; diff --git a/nageru/mixer.h b/nageru/mixer.h index 99385fa..18d520f 100644 --- a/nageru/mixer.h +++ b/nageru/mixer.h @@ -37,6 +37,7 @@ #include "queue_length_policy.h" #include "ref_counted_frame.h" #include "shared/ref_counted_gl_sync.h" +#include "srt_metrics.h" #include "theme.h" #include "shared/timebase.h" #include "video_encoder.h" @@ -521,52 +522,9 @@ private: std::atomic metric_input_frame_rate_den{-1}; std::atomic metric_input_sample_rate_hz{-1}; - // SRT metrics. - std::atomic metric_srt_uptime_seconds{0.0 / 0.0}; - std::atomic metric_srt_send_duration_seconds{0.0 / 0.0}; - std::atomic metric_srt_sent_bytes{-1}; - std::atomic metric_srt_received_bytes{-1}; - std::atomic metric_srt_sent_packets_normal{-1}; - std::atomic metric_srt_received_packets_normal{-1}; - std::atomic metric_srt_sent_packets_lost{-1}; - std::atomic metric_srt_received_packets_lost{-1}; - std::atomic metric_srt_sent_packets_retransmitted{-1}; - std::atomic metric_srt_sent_bytes_retransmitted{-1}; - std::atomic metric_srt_sent_packets_ack{-1}; - std::atomic metric_srt_received_packets_ack{-1}; - std::atomic metric_srt_sent_packets_nak{-1}; - std::atomic metric_srt_received_packets_nak{-1}; - std::atomic metric_srt_sent_packets_dropped{-1}; - std::atomic metric_srt_received_packets_dropped{-1}; - std::atomic metric_srt_sent_bytes_dropped{-1}; - std::atomic metric_srt_received_bytes_dropped{-1}; - std::atomic metric_srt_received_packets_undecryptable{-1}; - std::atomic metric_srt_received_bytes_undecryptable{-1}; - - std::atomic metric_srt_filter_received_extra_packets{-1}; - std::atomic metric_srt_filter_received_rebuilt_packets{-1}; - std::atomic metric_srt_filter_received_lost_packets{-1}; - - std::atomic metric_srt_packet_sending_period_seconds{0.0 / 0.0}; - std::atomic metric_srt_flow_window_packets{-1}; - std::atomic metric_srt_congestion_window_packets{-1}; - std::atomic metric_srt_flight_size_packets{-1}; - std::atomic metric_srt_rtt_seconds{0.0 / 0.0}; - std::atomic metric_srt_estimated_bandwidth_bits_per_second{0.0 / 0.0}; - std::atomic metric_srt_bandwidth_ceiling_bits_per_second{0.0 / 0.0}; - std::atomic metric_srt_send_buffer_available_bytes{-1}; - std::atomic metric_srt_receive_buffer_available_bytes{-1}; - std::atomic metric_srt_mss_bytes{-1}; - std::atomic metric_srt_sender_unacked_packets{-1}; - std::atomic metric_srt_sender_unacked_bytes{-1}; - std::atomic metric_srt_sender_unacked_timespan_seconds{0.0 / 0.0}; - std::atomic metric_srt_sender_delivery_delay_seconds{0.0 / 0.0}; - std::atomic metric_srt_receiver_unacked_packets{-1}; - std::atomic metric_srt_receiver_unacked_bytes{-1}; - std::atomic metric_srt_receiver_unacked_timespan_seconds{0.0 / 0.0}; - std::atomic metric_srt_receiver_delivery_delay_seconds{0.0 / 0.0}; - std::atomic metric_srt_filter_sent_packets{-1}; - +#ifdef HAVE_SRT + SRTMetrics srt_metrics; +#endif }; JitterHistory output_jitter_history; CaptureCard cards[MAX_VIDEO_CARDS]; // Protected by . @@ -583,10 +541,6 @@ private: }; OutputFrameInfo get_one_frame_from_each_card(unsigned master_card_index, bool master_card_is_output, CaptureCard::NewFrame new_frames[MAX_VIDEO_CARDS], bool has_new_frame[MAX_VIDEO_CARDS], std::vector raw_audio[MAX_VIDEO_CARDS]); -#ifdef HAVE_SRT - void update_srt_stats(int srt_sock, Mixer::CaptureCard *card); -#endif - std::string description_for_card(unsigned card_index); static bool is_srt_card(const CaptureCard *card); diff --git a/nageru/srt_metrics.cpp b/nageru/srt_metrics.cpp new file mode 100644 index 0000000..22d4729 --- /dev/null +++ b/nageru/srt_metrics.cpp @@ -0,0 +1,193 @@ +#include "srt_metrics.h" +#include "shared/metrics.h" + +#include + +using namespace std; + +void SRTMetrics::init(const vector> &labels) +{ + // Global measurements (counters). + global_metrics.add("srt_uptime_seconds", labels, &metric_srt_uptime_seconds); + global_metrics.add("srt_send_duration_seconds", labels, &metric_srt_send_duration_seconds); + global_metrics.add("srt_sent_bytes", labels, &metric_srt_sent_bytes); + global_metrics.add("srt_received_bytes", labels, &metric_srt_received_bytes); + + vector> packet_labels = labels; + packet_labels.emplace_back("type", "normal"); + global_metrics.add("srt_sent_packets", packet_labels, &metric_srt_sent_packets_normal); + global_metrics.add("srt_received_packets", packet_labels, &metric_srt_received_packets_normal); + + packet_labels.back().second = "lost"; + global_metrics.add("srt_sent_packets", packet_labels, &metric_srt_sent_packets_lost); + global_metrics.add("srt_received_packets", packet_labels, &metric_srt_received_packets_lost); + + packet_labels.back().second = "retransmitted"; + global_metrics.add("srt_sent_packets", packet_labels, &metric_srt_sent_packets_retransmitted); + global_metrics.add("srt_sent_bytes", packet_labels, &metric_srt_sent_bytes_retransmitted); + + packet_labels.back().second = "ack"; + global_metrics.add("srt_sent_packets", packet_labels, &metric_srt_sent_packets_ack); + global_metrics.add("srt_received_packets", packet_labels, &metric_srt_received_packets_ack); + + packet_labels.back().second = "nak"; + global_metrics.add("srt_sent_packets", packet_labels, &metric_srt_sent_packets_nak); + global_metrics.add("srt_received_packets", packet_labels, &metric_srt_received_packets_nak); + + packet_labels.back().second = "dropped"; + global_metrics.add("srt_sent_packets", packet_labels, &metric_srt_sent_packets_dropped); + global_metrics.add("srt_received_packets", packet_labels, &metric_srt_received_packets_dropped); + global_metrics.add("srt_sent_bytes", packet_labels, &metric_srt_sent_bytes_dropped); + global_metrics.add("srt_received_bytes", packet_labels, &metric_srt_received_bytes_dropped); + + packet_labels.back().second = "undecryptable"; + global_metrics.add("srt_received_packets", packet_labels, &metric_srt_received_packets_undecryptable); + global_metrics.add("srt_received_bytes", packet_labels, &metric_srt_received_bytes_undecryptable); + + global_metrics.add("srt_filter_sent_extra_packets", labels, &metric_srt_filter_sent_packets); + global_metrics.add("srt_filter_received_extra_packets", labels, &metric_srt_filter_received_extra_packets); + global_metrics.add("srt_filter_received_rebuilt_packets", labels, &metric_srt_filter_received_rebuilt_packets); + global_metrics.add("srt_filter_received_lost_packets", labels, &metric_srt_filter_received_lost_packets); + + // Instant measurements (gauges). + global_metrics.add("srt_packet_sending_period_seconds", labels, &metric_srt_packet_sending_period_seconds, Metrics::TYPE_GAUGE); + global_metrics.add("srt_flow_window_packets", labels, &metric_srt_flow_window_packets, Metrics::TYPE_GAUGE); + global_metrics.add("srt_congestion_window_packets", labels, &metric_srt_congestion_window_packets, Metrics::TYPE_GAUGE); + global_metrics.add("srt_flight_size_packets", labels, &metric_srt_flight_size_packets, Metrics::TYPE_GAUGE); + global_metrics.add("srt_rtt_seconds", labels, &metric_srt_rtt_seconds, Metrics::TYPE_GAUGE); + global_metrics.add("srt_estimated_bandwidth_bits_per_second", labels, &metric_srt_estimated_bandwidth_bits_per_second, Metrics::TYPE_GAUGE); + global_metrics.add("srt_bandwidth_ceiling_bits_per_second", labels, &metric_srt_bandwidth_ceiling_bits_per_second, Metrics::TYPE_GAUGE); + global_metrics.add("srt_send_buffer_available_bytes", labels, &metric_srt_send_buffer_available_bytes, Metrics::TYPE_GAUGE); + global_metrics.add("srt_receive_buffer_available_bytes", labels, &metric_srt_receive_buffer_available_bytes, Metrics::TYPE_GAUGE); + global_metrics.add("srt_mss_bytes", labels, &metric_srt_mss_bytes, Metrics::TYPE_GAUGE); + + global_metrics.add("srt_sender_unacked_packets", labels, &metric_srt_sender_unacked_packets, Metrics::TYPE_GAUGE); + global_metrics.add("srt_sender_unacked_bytes", labels, &metric_srt_sender_unacked_bytes, Metrics::TYPE_GAUGE); + global_metrics.add("srt_sender_unacked_timespan_seconds", labels, &metric_srt_sender_unacked_timespan_seconds, Metrics::TYPE_GAUGE); + global_metrics.add("srt_sender_delivery_delay_seconds", labels, &metric_srt_sender_delivery_delay_seconds, Metrics::TYPE_GAUGE); + + global_metrics.add("srt_receiver_unacked_packets", labels, &metric_srt_receiver_unacked_packets, Metrics::TYPE_GAUGE); + global_metrics.add("srt_receiver_unacked_bytes", labels, &metric_srt_receiver_unacked_bytes, Metrics::TYPE_GAUGE); + global_metrics.add("srt_receiver_unacked_timespan_seconds", labels, &metric_srt_receiver_unacked_timespan_seconds, Metrics::TYPE_GAUGE); + global_metrics.add("srt_receiver_delivery_delay_seconds", labels, &metric_srt_receiver_delivery_delay_seconds, Metrics::TYPE_GAUGE); +} + +void SRTMetrics::deinit(const vector> &labels) +{ + // Global measurements (counters). + global_metrics.remove_if_exists("srt_uptime_seconds", labels); + global_metrics.remove_if_exists("srt_send_duration_seconds", labels); + global_metrics.remove_if_exists("srt_sent_bytes", labels); + global_metrics.remove_if_exists("srt_received_bytes", labels); + + vector> packet_labels = labels; + packet_labels.emplace_back("type", "normal"); + global_metrics.remove_if_exists("srt_sent_packets", packet_labels); + global_metrics.remove_if_exists("srt_received_packets", packet_labels); + + packet_labels.back().second = "lost"; + global_metrics.remove_if_exists("srt_sent_packets", packet_labels); + global_metrics.remove_if_exists("srt_received_packets", packet_labels); + + packet_labels.back().second = "retransmitted"; + global_metrics.remove_if_exists("srt_sent_packets", packet_labels); + global_metrics.remove_if_exists("srt_sent_bytes", packet_labels); + + packet_labels.back().second = "ack"; + global_metrics.remove_if_exists("srt_sent_packets", packet_labels); + global_metrics.remove_if_exists("srt_received_packets", packet_labels); + + packet_labels.back().second = "nak"; + global_metrics.remove_if_exists("srt_sent_packets", packet_labels); + global_metrics.remove_if_exists("srt_received_packets", packet_labels); + + packet_labels.back().second = "dropped"; + global_metrics.remove_if_exists("srt_sent_packets", packet_labels); + global_metrics.remove_if_exists("srt_received_packets", packet_labels); + global_metrics.remove_if_exists("srt_sent_bytes", packet_labels); + global_metrics.remove_if_exists("srt_received_bytes", packet_labels); + + packet_labels.back().second = "undecryptable"; + global_metrics.remove_if_exists("srt_received_packets", packet_labels); + global_metrics.remove_if_exists("srt_received_bytes", packet_labels); + + global_metrics.remove_if_exists("srt_filter_sent_extra_packets", labels); + global_metrics.remove_if_exists("srt_filter_received_extra_packets", labels); + global_metrics.remove_if_exists("srt_filter_received_rebuilt_packets", labels); + global_metrics.remove_if_exists("srt_filter_received_lost_packets", labels); + + // Instant measurements (gauges). + global_metrics.remove_if_exists("srt_packet_sending_period_seconds", labels); + global_metrics.remove_if_exists("srt_flow_window_packets", labels); + global_metrics.remove_if_exists("srt_congestion_window_packets", labels); + global_metrics.remove_if_exists("srt_flight_size_packets", labels); + global_metrics.remove_if_exists("srt_rtt_seconds", labels); + global_metrics.remove_if_exists("srt_estimated_bandwidth_bits_per_second", labels); + global_metrics.remove_if_exists("srt_bandwidth_ceiling_bits_per_second", labels); + global_metrics.remove_if_exists("srt_send_buffer_available_bytes", labels); + global_metrics.remove_if_exists("srt_receive_buffer_available_bytes", labels); + global_metrics.remove_if_exists("srt_mss_bytes", labels); + + global_metrics.remove_if_exists("srt_sender_unacked_packets", labels); + global_metrics.remove_if_exists("srt_sender_unacked_bytes", labels); + global_metrics.remove_if_exists("srt_sender_unacked_timespan_seconds", labels); + global_metrics.remove_if_exists("srt_sender_delivery_delay_seconds", labels); + + global_metrics.remove_if_exists("srt_receiver_unacked_packets", labels); + global_metrics.remove_if_exists("srt_receiver_unacked_bytes", labels); + global_metrics.remove_if_exists("srt_receiver_unacked_timespan_seconds", labels); + global_metrics.remove_if_exists("srt_receiver_delivery_delay_seconds", labels); +} + +#ifdef HAVE_SRT +void SRTMetrics::update_srt_stats(int srt_sock) +{ + SRT_TRACEBSTATS stats; + srt_bistats(srt_sock, &stats, /*clear=*/0, /*instantaneous=*/1); + + metric_srt_uptime_seconds = stats.msTimeStamp * 1e-3; + metric_srt_send_duration_seconds = stats.usSndDurationTotal * 1e-6; + metric_srt_sent_bytes = stats.byteSentTotal; + metric_srt_received_bytes = stats.byteRecvTotal; + metric_srt_sent_packets_normal = stats.pktSentTotal; + metric_srt_received_packets_normal = stats.pktRecvTotal; + metric_srt_sent_packets_lost = stats.pktSndLossTotal; + metric_srt_received_packets_lost = stats.pktRcvLossTotal; + metric_srt_sent_packets_retransmitted = stats.pktRetransTotal; + metric_srt_sent_bytes_retransmitted = stats.byteRetransTotal; + metric_srt_sent_packets_ack = stats.pktSentACKTotal; + metric_srt_received_packets_ack = stats.pktRecvACKTotal; + metric_srt_sent_packets_nak = stats.pktSentNAKTotal; + metric_srt_received_packets_nak = stats.pktRecvNAKTotal; + metric_srt_sent_packets_dropped = stats.pktSndDropTotal; + metric_srt_received_packets_dropped = stats.pktRcvDropTotal; + metric_srt_sent_bytes_dropped = stats.byteSndDropTotal; + metric_srt_received_bytes_dropped = stats.byteRcvDropTotal; + metric_srt_received_packets_undecryptable = stats.pktRcvUndecryptTotal; + metric_srt_received_bytes_undecryptable = stats.byteRcvUndecryptTotal; + metric_srt_filter_sent_packets = stats.pktSndFilterExtraTotal; + metric_srt_filter_received_extra_packets = stats.pktRcvFilterExtraTotal; + metric_srt_filter_received_rebuilt_packets = stats.pktRcvFilterSupplyTotal; + metric_srt_filter_received_lost_packets = stats.pktRcvFilterLossTotal; + + // Gauges. + metric_srt_packet_sending_period_seconds = stats.usPktSndPeriod * 1e-6; + metric_srt_flow_window_packets = stats.pktFlowWindow; + metric_srt_congestion_window_packets = stats.pktCongestionWindow; + metric_srt_flight_size_packets = stats.pktFlightSize; + metric_srt_rtt_seconds = stats.msRTT * 1e-3; + metric_srt_estimated_bandwidth_bits_per_second = stats.mbpsBandwidth * 1e6; + metric_srt_bandwidth_ceiling_bits_per_second = stats.mbpsMaxBW * 1e6; + metric_srt_send_buffer_available_bytes = stats.byteAvailSndBuf; + metric_srt_receive_buffer_available_bytes = stats.byteAvailRcvBuf; + metric_srt_mss_bytes = stats.byteMSS; + metric_srt_sender_unacked_packets = stats.pktSndBuf; + metric_srt_sender_unacked_bytes = stats.byteSndBuf; + metric_srt_sender_unacked_timespan_seconds = stats.msSndBuf * 1e-3; + metric_srt_sender_delivery_delay_seconds = stats.msSndTsbPdDelay * 1e-3; + metric_srt_receiver_unacked_packets = stats.pktRcvBuf; + metric_srt_receiver_unacked_bytes = stats.byteRcvBuf; + metric_srt_receiver_unacked_timespan_seconds = stats.msRcvBuf * 1e-3; + metric_srt_receiver_delivery_delay_seconds = stats.msRcvTsbPdDelay * 1e-3; +} +#endif diff --git a/nageru/srt_metrics.h b/nageru/srt_metrics.h new file mode 100644 index 0000000..b2560b0 --- /dev/null +++ b/nageru/srt_metrics.h @@ -0,0 +1,67 @@ +#ifndef _SRT_METRICS_H +#define _SRT_METRICS_H 1 + +#include +#include +#include +#include + +// Metrics related to an SRT stream (input or output). + +struct SRTMetrics { + std::atomic metric_srt_uptime_seconds{0.0 / 0.0}; + std::atomic metric_srt_send_duration_seconds{0.0 / 0.0}; + std::atomic metric_srt_sent_bytes{-1}; + std::atomic metric_srt_received_bytes{-1}; + std::atomic metric_srt_sent_packets_normal{-1}; + std::atomic metric_srt_received_packets_normal{-1}; + std::atomic metric_srt_sent_packets_lost{-1}; + std::atomic metric_srt_received_packets_lost{-1}; + std::atomic metric_srt_sent_packets_retransmitted{-1}; + std::atomic metric_srt_sent_bytes_retransmitted{-1}; + std::atomic metric_srt_sent_packets_ack{-1}; + std::atomic metric_srt_received_packets_ack{-1}; + std::atomic metric_srt_sent_packets_nak{-1}; + std::atomic metric_srt_received_packets_nak{-1}; + std::atomic metric_srt_sent_packets_dropped{-1}; + std::atomic metric_srt_received_packets_dropped{-1}; + std::atomic metric_srt_sent_bytes_dropped{-1}; + std::atomic metric_srt_received_bytes_dropped{-1}; + std::atomic metric_srt_received_packets_undecryptable{-1}; + std::atomic metric_srt_received_bytes_undecryptable{-1}; + + std::atomic metric_srt_filter_received_extra_packets{-1}; + std::atomic metric_srt_filter_received_rebuilt_packets{-1}; + std::atomic metric_srt_filter_received_lost_packets{-1}; + + std::atomic metric_srt_packet_sending_period_seconds{0.0 / 0.0}; + std::atomic metric_srt_flow_window_packets{-1}; + std::atomic metric_srt_congestion_window_packets{-1}; + std::atomic metric_srt_flight_size_packets{-1}; + std::atomic metric_srt_rtt_seconds{0.0 / 0.0}; + std::atomic metric_srt_estimated_bandwidth_bits_per_second{0.0 / 0.0}; + std::atomic metric_srt_bandwidth_ceiling_bits_per_second{0.0 / 0.0}; + std::atomic metric_srt_send_buffer_available_bytes{-1}; + std::atomic metric_srt_receive_buffer_available_bytes{-1}; + std::atomic metric_srt_mss_bytes{-1}; + std::atomic metric_srt_sender_unacked_packets{-1}; + std::atomic metric_srt_sender_unacked_bytes{-1}; + std::atomic metric_srt_sender_unacked_timespan_seconds{0.0 / 0.0}; + std::atomic metric_srt_sender_delivery_delay_seconds{0.0 / 0.0}; + std::atomic metric_srt_receiver_unacked_packets{-1}; + std::atomic metric_srt_receiver_unacked_bytes{-1}; + std::atomic metric_srt_receiver_unacked_timespan_seconds{0.0 / 0.0}; + std::atomic metric_srt_receiver_delivery_delay_seconds{0.0 / 0.0}; + std::atomic metric_srt_filter_sent_packets{-1}; + + // Registers in global_metrics. + void init(const std::vector> &labels); + + // Unregisters similarly. + void deinit(const std::vector> &labels); + + void update_srt_stats(int srt_sock); +}; + +#endif + -- 2.39.2