From 9e077744fdfb760bedb8d680a0b2f827b7d112dc Mon Sep 17 00:00:00 2001 From: Johan Gustavsson Date: Tue, 21 Apr 2026 19:37:31 +0200 Subject: [PATCH] metrics: improve performance (#5663) use string.Builder instead of string concatenation --------- Co-authored-by: aler9 <46489434+aler9@users.noreply.github.com> --- internal/metrics/metrics.go | 651 ++++++++++++++++--------------- internal/metrics/metrics_test.go | 148 +++++++ 2 files changed, 478 insertions(+), 321 deletions(-) diff --git a/internal/metrics/metrics.go b/internal/metrics/metrics.go index 48fc2fff..c781d307 100644 --- a/internal/metrics/metrics.go +++ b/internal/metrics/metrics.go @@ -3,12 +3,12 @@ package metrics //nolint:revive import ( "fmt" - "io" "net" "net/http" "reflect" "sort" "strconv" + "strings" "sync" "time" @@ -37,28 +37,37 @@ func sortedKeys(paths map[string]string) []string { } func tags(m map[string]string) string { - o := "{" - + var b strings.Builder + b.WriteByte('{') first := true for _, k := range sortedKeys(m) { - if first { - first = false - } else { - o += "," + if !first { + b.WriteByte(',') } - o += k + "=\"" + m[k] + "\"" + first = false + b.WriteString(k) + b.WriteString("=\"") + b.WriteString(m[k]) + b.WriteByte('"') } - - o += "}" - return o + b.WriteByte('}') + return b.String() } -func metric(key string, tags string, value int64) string { - return key + tags + " " + strconv.FormatInt(value, 10) + "\n" +func metric(out *strings.Builder, key string, tags string, value int64) { + out.WriteString(key) + out.WriteString(tags) + out.WriteByte(' ') + out.WriteString(strconv.FormatInt(value, 10)) + out.WriteByte('\n') } -func metricFloat(key string, tags string, value float64) string { - return key + tags + " " + strconv.FormatFloat(value, 'f', -1, 64) + "\n" +func metricFloat(out *strings.Builder, key string, tags string, value float64) { + out.WriteString(key) + out.WriteString(tags) + out.WriteByte(' ') + out.WriteString(strconv.FormatFloat(value, 'f', -1, 64)) + out.WriteByte('\n') } type metricsAuthManager interface { @@ -212,7 +221,7 @@ func (m *Metrics) onMetrics(ctx *gin.Context) { srtConnFilter != "" || webrtcSessionFilter != "" - out := "" + var out strings.Builder if (typ == "" || typ == "paths") && (!anyFilterActive || pathFilter != "") { data, err := m.pathManager.APIPathsList() @@ -230,25 +239,25 @@ func (m *Metrics) onMetrics(ctx *gin.Context) { "name": i.Name, "state": state, }) - out += metric("paths", ta, 1) - out += metric("paths_inbound_bytes", ta, int64(i.InboundBytes)) - out += metric("paths_outbound_bytes", ta, int64(i.OutboundBytes)) - out += metric("paths_inbound_frames_in_error", ta, int64(i.InboundFramesInError)) + metric(&out, "paths", ta, 1) + metric(&out, "paths_inbound_bytes", ta, int64(i.InboundBytes)) + metric(&out, "paths_outbound_bytes", ta, int64(i.OutboundBytes)) + metric(&out, "paths_inbound_frames_in_error", ta, int64(i.InboundFramesInError)) // deprecated - out += metric("paths_bytes_received", ta, int64(i.BytesReceived)) - out += metric("paths_bytes_sent", ta, int64(i.BytesSent)) - out += metric("paths_readers", ta, int64(len(i.Readers))) + metric(&out, "paths_bytes_received", ta, int64(i.BytesReceived)) + metric(&out, "paths_bytes_sent", ta, int64(i.BytesSent)) + metric(&out, "paths_readers", ta, int64(len(i.Readers))) } } } else if pathFilter == "" { - out += metric("paths", "", 0) - out += metric("paths_inbound_bytes", "", 0) - out += metric("paths_outbound_bytes", "", 0) - out += metric("paths_inbound_frames_in_error", "", 0) + metric(&out, "paths", "", 0) + metric(&out, "paths_inbound_bytes", "", 0) + metric(&out, "paths_outbound_bytes", "", 0) + metric(&out, "paths_inbound_frames_in_error", "", 0) // deprecated - out += metric("paths_bytes_received", "", 0) - out += metric("paths_bytes_sent", "", 0) - out += metric("paths_readers", "", 0) + metric(&out, "paths_bytes_received", "", 0) + metric(&out, "paths_bytes_sent", "", 0) + metric(&out, "paths_readers", "", 0) } } @@ -263,19 +272,19 @@ func (m *Metrics) onMetrics(ctx *gin.Context) { ta := tags(map[string]string{ "name": i.Path, }) - out += metric("hls_muxers", ta, 1) - out += metric("hls_muxers_outbound_bytes", ta, int64(i.OutboundBytes)) - out += metric("hls_muxers_outbound_frames_discarded", ta, int64(i.OutboundFramesDiscarded)) + metric(&out, "hls_muxers", ta, 1) + metric(&out, "hls_muxers_outbound_bytes", ta, int64(i.OutboundBytes)) + metric(&out, "hls_muxers_outbound_frames_discarded", ta, int64(i.OutboundFramesDiscarded)) // deprecated - out += metric("hls_muxers_bytes_sent", ta, int64(i.BytesSent)) + metric(&out, "hls_muxers_bytes_sent", ta, int64(i.BytesSent)) } } } else if hlsMuxerFilter == "" { - out += metric("hls_muxers", "", 0) - out += metric("hls_muxers_outbound_bytes", "", 0) - out += metric("hls_muxers_outbound_frames_discarded", "", 0) + metric(&out, "hls_muxers", "", 0) + metric(&out, "hls_muxers_outbound_bytes", "", 0) + metric(&out, "hls_muxers_outbound_frames_discarded", "", 0) // deprecated - out += metric("hls_muxers_bytes_sent", "", 0) + metric(&out, "hls_muxers_bytes_sent", "", 0) } } @@ -289,21 +298,21 @@ func (m *Metrics) onMetrics(ctx *gin.Context) { ta := tags(map[string]string{ "id": i.ID.String(), }) - out += metric("rtsp_conns", ta, 1) - out += metric("rtsp_conns_inbound_bytes", ta, int64(i.InboundBytes)) - out += metric("rtsp_conns_outbound_bytes", ta, int64(i.OutboundBytes)) + metric(&out, "rtsp_conns", ta, 1) + metric(&out, "rtsp_conns_inbound_bytes", ta, int64(i.InboundBytes)) + metric(&out, "rtsp_conns_outbound_bytes", ta, int64(i.OutboundBytes)) // deprecated - out += metric("rtsp_conns_bytes_received", ta, int64(i.BytesReceived)) - out += metric("rtsp_conns_bytes_sent", ta, int64(i.BytesSent)) + metric(&out, "rtsp_conns_bytes_received", ta, int64(i.BytesReceived)) + metric(&out, "rtsp_conns_bytes_sent", ta, int64(i.BytesSent)) } } } else if rtspConnFilter == "" { - out += metric("rtsp_conns", "", 0) - out += metric("rtsp_conns_inbound_bytes", "", 0) - out += metric("rtsp_conns_outbound_bytes", "", 0) + metric(&out, "rtsp_conns", "", 0) + metric(&out, "rtsp_conns_inbound_bytes", "", 0) + metric(&out, "rtsp_conns_outbound_bytes", "", 0) // deprecated - out += metric("rtsp_conns_bytes_received", "", 0) - out += metric("rtsp_conns_bytes_sent", "", 0) + metric(&out, "rtsp_conns_bytes_received", "", 0) + metric(&out, "rtsp_conns_bytes_sent", "", 0) } } @@ -319,57 +328,57 @@ func (m *Metrics) onMetrics(ctx *gin.Context) { "path": i.Path, "remoteAddr": i.RemoteAddr, }) - out += metric("rtsp_sessions", ta, 1) - out += metric("rtsp_sessions_inbound_bytes", ta, int64(i.InboundBytes)) - out += metric("rtsp_sessions_inbound_rtp_packets", ta, int64(i.InboundRTPPackets)) - out += metric("rtsp_sessions_inbound_rtp_packets_lost", ta, int64(i.InboundRTPPacketsLost)) - out += metric("rtsp_sessions_inbound_rtp_packets_in_error", ta, int64(i.InboundRTPPacketsInError)) - out += metricFloat("rtsp_sessions_inbound_rtp_packets_jitter", ta, i.InboundRTPPacketsJitter) - out += metric("rtsp_sessions_inbound_rtcp_packets", ta, int64(i.InboundRTCPPackets)) - out += metric("rtsp_sessions_inbound_rtcp_packets_in_error", ta, int64(i.InboundRTCPPacketsInError)) - out += metric("rtsp_sessions_outbound_bytes", ta, int64(i.OutboundBytes)) - out += metric("rtsp_sessions_outbound_rtp_packets", ta, int64(i.OutboundRTPPackets)) - out += metric("rtsp_sessions_outbound_rtp_packets_reported_lost", ta, int64(i.OutboundRTPPacketsReportedLost)) - out += metric("rtsp_sessions_outbound_rtp_packets_discarded", ta, int64(i.OutboundRTPPacketsDiscarded)) - out += metric("rtsp_sessions_outbound_rtcp_packets", ta, int64(i.OutboundRTCPPackets)) + metric(&out, "rtsp_sessions", ta, 1) + metric(&out, "rtsp_sessions_inbound_bytes", ta, int64(i.InboundBytes)) + metric(&out, "rtsp_sessions_inbound_rtp_packets", ta, int64(i.InboundRTPPackets)) + metric(&out, "rtsp_sessions_inbound_rtp_packets_lost", ta, int64(i.InboundRTPPacketsLost)) + metric(&out, "rtsp_sessions_inbound_rtp_packets_in_error", ta, int64(i.InboundRTPPacketsInError)) + metricFloat(&out, "rtsp_sessions_inbound_rtp_packets_jitter", ta, i.InboundRTPPacketsJitter) + metric(&out, "rtsp_sessions_inbound_rtcp_packets", ta, int64(i.InboundRTCPPackets)) + metric(&out, "rtsp_sessions_inbound_rtcp_packets_in_error", ta, int64(i.InboundRTCPPacketsInError)) + metric(&out, "rtsp_sessions_outbound_bytes", ta, int64(i.OutboundBytes)) + metric(&out, "rtsp_sessions_outbound_rtp_packets", ta, int64(i.OutboundRTPPackets)) + metric(&out, "rtsp_sessions_outbound_rtp_packets_reported_lost", ta, int64(i.OutboundRTPPacketsReportedLost)) + metric(&out, "rtsp_sessions_outbound_rtp_packets_discarded", ta, int64(i.OutboundRTPPacketsDiscarded)) + metric(&out, "rtsp_sessions_outbound_rtcp_packets", ta, int64(i.OutboundRTCPPackets)) // deprecated - out += metric("rtsp_sessions_bytes_received", ta, int64(i.BytesReceived)) - out += metric("rtsp_sessions_bytes_sent", ta, int64(i.BytesSent)) - out += metric("rtsp_sessions_rtp_packets_received", ta, int64(i.RTPPacketsReceived)) - out += metric("rtsp_sessions_rtp_packets_sent", ta, int64(i.RTPPacketsSent)) - out += metric("rtsp_sessions_rtp_packets_lost", ta, int64(i.RTPPacketsLost)) - out += metric("rtsp_sessions_rtp_packets_in_error", ta, int64(i.RTPPacketsInError)) - out += metricFloat("rtsp_sessions_rtp_packets_jitter", ta, i.RTPPacketsJitter) - out += metric("rtsp_sessions_rtcp_packets_received", ta, int64(i.RTCPPacketsReceived)) - out += metric("rtsp_sessions_rtcp_packets_sent", ta, int64(i.RTCPPacketsSent)) - out += metric("rtsp_sessions_rtcp_packets_in_error", ta, int64(i.RTCPPacketsInError)) + metric(&out, "rtsp_sessions_bytes_received", ta, int64(i.BytesReceived)) + metric(&out, "rtsp_sessions_bytes_sent", ta, int64(i.BytesSent)) + metric(&out, "rtsp_sessions_rtp_packets_received", ta, int64(i.RTPPacketsReceived)) + metric(&out, "rtsp_sessions_rtp_packets_sent", ta, int64(i.RTPPacketsSent)) + metric(&out, "rtsp_sessions_rtp_packets_lost", ta, int64(i.RTPPacketsLost)) + metric(&out, "rtsp_sessions_rtp_packets_in_error", ta, int64(i.RTPPacketsInError)) + metricFloat(&out, "rtsp_sessions_rtp_packets_jitter", ta, i.RTPPacketsJitter) + metric(&out, "rtsp_sessions_rtcp_packets_received", ta, int64(i.RTCPPacketsReceived)) + metric(&out, "rtsp_sessions_rtcp_packets_sent", ta, int64(i.RTCPPacketsSent)) + metric(&out, "rtsp_sessions_rtcp_packets_in_error", ta, int64(i.RTCPPacketsInError)) } } } else if rtspSessionFilter == "" { - out += metric("rtsp_sessions", "", 0) - out += metric("rtsp_sessions_inbound_bytes", "", 0) - out += metric("rtsp_sessions_inbound_rtp_packets", "", 0) - out += metric("rtsp_sessions_inbound_rtp_packets_lost", "", 0) - out += metric("rtsp_sessions_inbound_rtp_packets_in_error", "", 0) - out += metricFloat("rtsp_sessions_inbound_rtp_packets_jitter", "", 0) - out += metric("rtsp_sessions_inbound_rtcp_packets", "", 0) - out += metric("rtsp_sessions_inbound_rtcp_packets_in_error", "", 0) - out += metric("rtsp_sessions_outbound_bytes", "", 0) - out += metric("rtsp_sessions_outbound_rtp_packets", "", 0) - out += metric("rtsp_sessions_outbound_rtp_packets_reported_lost", "", 0) - out += metric("rtsp_sessions_outbound_rtp_packets_discarded", "", 0) - out += metric("rtsp_sessions_outbound_rtcp_packets", "", 0) + metric(&out, "rtsp_sessions", "", 0) + metric(&out, "rtsp_sessions_inbound_bytes", "", 0) + metric(&out, "rtsp_sessions_inbound_rtp_packets", "", 0) + metric(&out, "rtsp_sessions_inbound_rtp_packets_lost", "", 0) + metric(&out, "rtsp_sessions_inbound_rtp_packets_in_error", "", 0) + metricFloat(&out, "rtsp_sessions_inbound_rtp_packets_jitter", "", 0) + metric(&out, "rtsp_sessions_inbound_rtcp_packets", "", 0) + metric(&out, "rtsp_sessions_inbound_rtcp_packets_in_error", "", 0) + metric(&out, "rtsp_sessions_outbound_bytes", "", 0) + metric(&out, "rtsp_sessions_outbound_rtp_packets", "", 0) + metric(&out, "rtsp_sessions_outbound_rtp_packets_reported_lost", "", 0) + metric(&out, "rtsp_sessions_outbound_rtp_packets_discarded", "", 0) + metric(&out, "rtsp_sessions_outbound_rtcp_packets", "", 0) // deprecated - out += metric("rtsp_sessions_bytes_received", "", 0) - out += metric("rtsp_sessions_bytes_sent", "", 0) - out += metric("rtsp_sessions_rtp_packets_received", "", 0) - out += metric("rtsp_sessions_rtp_packets_sent", "", 0) - out += metric("rtsp_sessions_rtp_packets_lost", "", 0) - out += metric("rtsp_sessions_rtp_packets_in_error", "", 0) - out += metricFloat("rtsp_sessions_rtp_packets_jitter", "", 0) - out += metric("rtsp_sessions_rtcp_packets_received", "", 0) - out += metric("rtsp_sessions_rtcp_packets_sent", "", 0) - out += metric("rtsp_sessions_rtcp_packets_in_error", "", 0) + metric(&out, "rtsp_sessions_bytes_received", "", 0) + metric(&out, "rtsp_sessions_bytes_sent", "", 0) + metric(&out, "rtsp_sessions_rtp_packets_received", "", 0) + metric(&out, "rtsp_sessions_rtp_packets_sent", "", 0) + metric(&out, "rtsp_sessions_rtp_packets_lost", "", 0) + metric(&out, "rtsp_sessions_rtp_packets_in_error", "", 0) + metricFloat(&out, "rtsp_sessions_rtp_packets_jitter", "", 0) + metric(&out, "rtsp_sessions_rtcp_packets_received", "", 0) + metric(&out, "rtsp_sessions_rtcp_packets_sent", "", 0) + metric(&out, "rtsp_sessions_rtcp_packets_in_error", "", 0) } } } @@ -384,21 +393,21 @@ func (m *Metrics) onMetrics(ctx *gin.Context) { ta := tags(map[string]string{ "id": i.ID.String(), }) - out += metric("rtsps_conns", ta, 1) - out += metric("rtsps_conns_inbound_bytes", ta, int64(i.InboundBytes)) - out += metric("rtsps_conns_outbound_bytes", ta, int64(i.OutboundBytes)) + metric(&out, "rtsps_conns", ta, 1) + metric(&out, "rtsps_conns_inbound_bytes", ta, int64(i.InboundBytes)) + metric(&out, "rtsps_conns_outbound_bytes", ta, int64(i.OutboundBytes)) // deprecated - out += metric("rtsps_conns_bytes_received", ta, int64(i.BytesReceived)) - out += metric("rtsps_conns_bytes_sent", ta, int64(i.BytesSent)) + metric(&out, "rtsps_conns_bytes_received", ta, int64(i.BytesReceived)) + metric(&out, "rtsps_conns_bytes_sent", ta, int64(i.BytesSent)) } } } else if rtspsConnFilter == "" { - out += metric("rtsps_conns", "", 0) - out += metric("rtsps_conns_inbound_bytes", "", 0) - out += metric("rtsps_conns_outbound_bytes", "", 0) + metric(&out, "rtsps_conns", "", 0) + metric(&out, "rtsps_conns_inbound_bytes", "", 0) + metric(&out, "rtsps_conns_outbound_bytes", "", 0) // deprecated - out += metric("rtsps_conns_bytes_received", "", 0) - out += metric("rtsps_conns_bytes_sent", "", 0) + metric(&out, "rtsps_conns_bytes_received", "", 0) + metric(&out, "rtsps_conns_bytes_sent", "", 0) } } @@ -414,57 +423,57 @@ func (m *Metrics) onMetrics(ctx *gin.Context) { "path": i.Path, "remoteAddr": i.RemoteAddr, }) - out += metric("rtsps_sessions", ta, 1) - out += metric("rtsps_sessions_inbound_bytes", ta, int64(i.InboundBytes)) - out += metric("rtsps_sessions_inbound_rtp_packets", ta, int64(i.InboundRTPPackets)) - out += metric("rtsps_sessions_inbound_rtp_packets_lost", ta, int64(i.InboundRTPPacketsLost)) - out += metric("rtsps_sessions_inbound_rtp_packets_in_error", ta, int64(i.InboundRTPPacketsInError)) - out += metricFloat("rtsps_sessions_inbound_rtp_packets_jitter", ta, i.InboundRTPPacketsJitter) - out += metric("rtsps_sessions_inbound_rtcp_packets", ta, int64(i.InboundRTCPPackets)) - out += metric("rtsps_sessions_inbound_rtcp_packets_in_error", ta, int64(i.InboundRTCPPacketsInError)) - out += metric("rtsps_sessions_outbound_bytes", ta, int64(i.OutboundBytes)) - out += metric("rtsps_sessions_outbound_rtp_packets", ta, int64(i.OutboundRTPPackets)) - out += metric("rtsps_sessions_outbound_rtp_packets_reported_lost", ta, int64(i.OutboundRTPPacketsReportedLost)) - out += metric("rtsps_sessions_outbound_rtp_packets_discarded", ta, int64(i.OutboundRTPPacketsDiscarded)) - out += metric("rtsps_sessions_outbound_rtcp_packets", ta, int64(i.OutboundRTCPPackets)) + metric(&out, "rtsps_sessions", ta, 1) + metric(&out, "rtsps_sessions_inbound_bytes", ta, int64(i.InboundBytes)) + metric(&out, "rtsps_sessions_inbound_rtp_packets", ta, int64(i.InboundRTPPackets)) + metric(&out, "rtsps_sessions_inbound_rtp_packets_lost", ta, int64(i.InboundRTPPacketsLost)) + metric(&out, "rtsps_sessions_inbound_rtp_packets_in_error", ta, int64(i.InboundRTPPacketsInError)) + metricFloat(&out, "rtsps_sessions_inbound_rtp_packets_jitter", ta, i.InboundRTPPacketsJitter) + metric(&out, "rtsps_sessions_inbound_rtcp_packets", ta, int64(i.InboundRTCPPackets)) + metric(&out, "rtsps_sessions_inbound_rtcp_packets_in_error", ta, int64(i.InboundRTCPPacketsInError)) + metric(&out, "rtsps_sessions_outbound_bytes", ta, int64(i.OutboundBytes)) + metric(&out, "rtsps_sessions_outbound_rtp_packets", ta, int64(i.OutboundRTPPackets)) + metric(&out, "rtsps_sessions_outbound_rtp_packets_reported_lost", ta, int64(i.OutboundRTPPacketsReportedLost)) + metric(&out, "rtsps_sessions_outbound_rtp_packets_discarded", ta, int64(i.OutboundRTPPacketsDiscarded)) + metric(&out, "rtsps_sessions_outbound_rtcp_packets", ta, int64(i.OutboundRTCPPackets)) // deprecated - out += metric("rtsps_sessions_bytes_received", ta, int64(i.BytesReceived)) - out += metric("rtsps_sessions_bytes_sent", ta, int64(i.BytesSent)) - out += metric("rtsps_sessions_rtp_packets_received", ta, int64(i.RTPPacketsReceived)) - out += metric("rtsps_sessions_rtp_packets_sent", ta, int64(i.RTPPacketsSent)) - out += metric("rtsps_sessions_rtp_packets_lost", ta, int64(i.RTPPacketsLost)) - out += metric("rtsps_sessions_rtp_packets_in_error", ta, int64(i.RTPPacketsInError)) - out += metricFloat("rtsps_sessions_rtp_packets_jitter", ta, i.RTPPacketsJitter) - out += metric("rtsps_sessions_rtcp_packets_received", ta, int64(i.RTCPPacketsReceived)) - out += metric("rtsps_sessions_rtcp_packets_sent", ta, int64(i.RTCPPacketsSent)) - out += metric("rtsps_sessions_rtcp_packets_in_error", ta, int64(i.RTCPPacketsInError)) + metric(&out, "rtsps_sessions_bytes_received", ta, int64(i.BytesReceived)) + metric(&out, "rtsps_sessions_bytes_sent", ta, int64(i.BytesSent)) + metric(&out, "rtsps_sessions_rtp_packets_received", ta, int64(i.RTPPacketsReceived)) + metric(&out, "rtsps_sessions_rtp_packets_sent", ta, int64(i.RTPPacketsSent)) + metric(&out, "rtsps_sessions_rtp_packets_lost", ta, int64(i.RTPPacketsLost)) + metric(&out, "rtsps_sessions_rtp_packets_in_error", ta, int64(i.RTPPacketsInError)) + metricFloat(&out, "rtsps_sessions_rtp_packets_jitter", ta, i.RTPPacketsJitter) + metric(&out, "rtsps_sessions_rtcp_packets_received", ta, int64(i.RTCPPacketsReceived)) + metric(&out, "rtsps_sessions_rtcp_packets_sent", ta, int64(i.RTCPPacketsSent)) + metric(&out, "rtsps_sessions_rtcp_packets_in_error", ta, int64(i.RTCPPacketsInError)) } } } else if rtspsSessionFilter == "" { - out += metric("rtsps_sessions", "", 0) - out += metric("rtsps_sessions_inbound_bytes", "", 0) - out += metric("rtsps_sessions_inbound_rtp_packets", "", 0) - out += metric("rtsps_sessions_inbound_rtp_packets_lost", "", 0) - out += metric("rtsps_sessions_inbound_rtp_packets_in_error", "", 0) - out += metricFloat("rtsps_sessions_inbound_rtp_packets_jitter", "", 0) - out += metric("rtsps_sessions_inbound_rtcp_packets", "", 0) - out += metric("rtsps_sessions_inbound_rtcp_packets_in_error", "", 0) - out += metric("rtsps_sessions_outbound_bytes", "", 0) - out += metric("rtsps_sessions_outbound_rtp_packets", "", 0) - out += metric("rtsps_sessions_outbound_rtp_packets_reported_lost", "", 0) - out += metric("rtsps_sessions_outbound_rtp_packets_discarded", "", 0) - out += metric("rtsps_sessions_outbound_rtcp_packets", "", 0) + metric(&out, "rtsps_sessions", "", 0) + metric(&out, "rtsps_sessions_inbound_bytes", "", 0) + metric(&out, "rtsps_sessions_inbound_rtp_packets", "", 0) + metric(&out, "rtsps_sessions_inbound_rtp_packets_lost", "", 0) + metric(&out, "rtsps_sessions_inbound_rtp_packets_in_error", "", 0) + metricFloat(&out, "rtsps_sessions_inbound_rtp_packets_jitter", "", 0) + metric(&out, "rtsps_sessions_inbound_rtcp_packets", "", 0) + metric(&out, "rtsps_sessions_inbound_rtcp_packets_in_error", "", 0) + metric(&out, "rtsps_sessions_outbound_bytes", "", 0) + metric(&out, "rtsps_sessions_outbound_rtp_packets", "", 0) + metric(&out, "rtsps_sessions_outbound_rtp_packets_reported_lost", "", 0) + metric(&out, "rtsps_sessions_outbound_rtp_packets_discarded", "", 0) + metric(&out, "rtsps_sessions_outbound_rtcp_packets", "", 0) // deprecated - out += metric("rtsps_sessions_bytes_received", "", 0) - out += metric("rtsps_sessions_bytes_sent", "", 0) - out += metric("rtsps_sessions_rtp_packets_received", "", 0) - out += metric("rtsps_sessions_rtp_packets_sent", "", 0) - out += metric("rtsps_sessions_rtp_packets_lost", "", 0) - out += metric("rtsps_sessions_rtp_packets_in_error", "", 0) - out += metricFloat("rtsps_sessions_rtp_packets_jitter", "", 0) - out += metric("rtsps_sessions_rtcp_packets_received", "", 0) - out += metric("rtsps_sessions_rtcp_packets_sent", "", 0) - out += metric("rtsps_sessions_rtcp_packets_in_error", "", 0) + metric(&out, "rtsps_sessions_bytes_received", "", 0) + metric(&out, "rtsps_sessions_bytes_sent", "", 0) + metric(&out, "rtsps_sessions_rtp_packets_received", "", 0) + metric(&out, "rtsps_sessions_rtp_packets_sent", "", 0) + metric(&out, "rtsps_sessions_rtp_packets_lost", "", 0) + metric(&out, "rtsps_sessions_rtp_packets_in_error", "", 0) + metricFloat(&out, "rtsps_sessions_rtp_packets_jitter", "", 0) + metric(&out, "rtsps_sessions_rtcp_packets_received", "", 0) + metric(&out, "rtsps_sessions_rtcp_packets_sent", "", 0) + metric(&out, "rtsps_sessions_rtcp_packets_in_error", "", 0) } } } @@ -483,23 +492,23 @@ func (m *Metrics) onMetrics(ctx *gin.Context) { "path": i.Path, "remoteAddr": i.RemoteAddr, }) - out += metric("rtmp_conns", ta, 1) - out += metric("rtmp_conns_inbound_bytes", ta, int64(i.InboundBytes)) - out += metric("rtmp_conns_outbound_bytes", ta, int64(i.OutboundBytes)) - out += metric("rtmp_conns_outbound_frames_discarded", ta, int64(i.OutboundFramesDiscarded)) + metric(&out, "rtmp_conns", ta, 1) + metric(&out, "rtmp_conns_inbound_bytes", ta, int64(i.InboundBytes)) + metric(&out, "rtmp_conns_outbound_bytes", ta, int64(i.OutboundBytes)) + metric(&out, "rtmp_conns_outbound_frames_discarded", ta, int64(i.OutboundFramesDiscarded)) // deprecated - out += metric("rtmp_conns_bytes_received", ta, int64(i.BytesReceived)) - out += metric("rtmp_conns_bytes_sent", ta, int64(i.BytesSent)) + metric(&out, "rtmp_conns_bytes_received", ta, int64(i.BytesReceived)) + metric(&out, "rtmp_conns_bytes_sent", ta, int64(i.BytesSent)) } } } else if rtmpConnFilter == "" { - out += metric("rtmp_conns", "", 0) - out += metric("rtmp_conns_inbound_bytes", "", 0) - out += metric("rtmp_conns_outbound_bytes", "", 0) - out += metric("rtmp_conns_outbound_frames_discarded", "", 0) + metric(&out, "rtmp_conns", "", 0) + metric(&out, "rtmp_conns_inbound_bytes", "", 0) + metric(&out, "rtmp_conns_outbound_bytes", "", 0) + metric(&out, "rtmp_conns_outbound_frames_discarded", "", 0) // deprecated - out += metric("rtmp_conns_bytes_received", "", 0) - out += metric("rtmp_conns_bytes_sent", "", 0) + metric(&out, "rtmp_conns_bytes_received", "", 0) + metric(&out, "rtmp_conns_bytes_sent", "", 0) } } @@ -517,23 +526,23 @@ func (m *Metrics) onMetrics(ctx *gin.Context) { "path": i.Path, "remoteAddr": i.RemoteAddr, }) - out += metric("rtmps_conns", ta, 1) - out += metric("rtmps_conns_inbound_bytes", ta, int64(i.InboundBytes)) - out += metric("rtmps_conns_outbound_bytes", ta, int64(i.OutboundBytes)) - out += metric("rtmps_conns_outbound_frames_discarded", ta, int64(i.OutboundFramesDiscarded)) + metric(&out, "rtmps_conns", ta, 1) + metric(&out, "rtmps_conns_inbound_bytes", ta, int64(i.InboundBytes)) + metric(&out, "rtmps_conns_outbound_bytes", ta, int64(i.OutboundBytes)) + metric(&out, "rtmps_conns_outbound_frames_discarded", ta, int64(i.OutboundFramesDiscarded)) // deprecated - out += metric("rtmps_conns_bytes_received", ta, int64(i.BytesReceived)) - out += metric("rtmps_conns_bytes_sent", ta, int64(i.BytesSent)) + metric(&out, "rtmps_conns_bytes_received", ta, int64(i.BytesReceived)) + metric(&out, "rtmps_conns_bytes_sent", ta, int64(i.BytesSent)) } } } else if rtmpsConnFilter == "" { - out += metric("rtmps_conns", "", 0) - out += metric("rtmps_conns_inbound_bytes", "", 0) - out += metric("rtmps_conns_outbound_bytes", "", 0) - out += metric("rtmps_conns_outbound_frames_discarded", "", 0) + metric(&out, "rtmps_conns", "", 0) + metric(&out, "rtmps_conns_inbound_bytes", "", 0) + metric(&out, "rtmps_conns_outbound_bytes", "", 0) + metric(&out, "rtmps_conns_outbound_frames_discarded", "", 0) // deprecated - out += metric("rtmps_conns_bytes_received", "", 0) - out += metric("rtmps_conns_bytes_sent", "", 0) + metric(&out, "rtmps_conns_bytes_received", "", 0) + metric(&out, "rtmps_conns_bytes_sent", "", 0) } } @@ -551,119 +560,119 @@ func (m *Metrics) onMetrics(ctx *gin.Context) { "path": i.Path, "remoteAddr": i.RemoteAddr, }) - out += metric("srt_conns", ta, 1) - out += metric("srt_conns_packets_sent", ta, int64(i.PacketsSent)) - out += metric("srt_conns_packets_received", ta, int64(i.PacketsReceived)) - out += metric("srt_conns_packets_sent_unique", ta, int64(i.PacketsSentUnique)) - out += metric("srt_conns_packets_received_unique", ta, int64(i.PacketsReceivedUnique)) - out += metric("srt_conns_packets_send_loss", ta, int64(i.PacketsSendLoss)) - out += metric("srt_conns_packets_received_loss", ta, int64(i.PacketsReceivedLoss)) - out += metric("srt_conns_packets_retrans", ta, int64(i.PacketsRetrans)) - out += metric("srt_conns_packets_received_retrans", ta, int64(i.PacketsReceivedRetrans)) - out += metric("srt_conns_packets_sent_ack", ta, int64(i.PacketsSentACK)) - out += metric("srt_conns_packets_received_ack", ta, int64(i.PacketsReceivedACK)) - out += metric("srt_conns_packets_sent_nak", ta, int64(i.PacketsSentNAK)) - out += metric("srt_conns_packets_received_nak", ta, int64(i.PacketsReceivedNAK)) - out += metric("srt_conns_packets_sent_km", ta, int64(i.PacketsSentKM)) - out += metric("srt_conns_packets_received_km", ta, int64(i.PacketsReceivedKM)) - out += metric("srt_conns_us_snd_duration", ta, int64(i.UsSndDuration)) - out += metric("srt_conns_packets_received_belated", ta, int64(i.PacketsReceivedBelated)) - out += metric("srt_conns_packets_send_drop", ta, int64(i.PacketsSendDrop)) - out += metric("srt_conns_packets_received_drop", ta, int64(i.PacketsReceivedDrop)) - out += metric("srt_conns_packets_received_undecrypt", ta, int64(i.PacketsReceivedUndecrypt)) - out += metric("srt_conns_bytes_sent", ta, int64(i.BytesSent)) - out += metric("srt_conns_bytes_received", ta, int64(i.BytesReceived)) - out += metric("srt_conns_bytes_sent_unique", ta, int64(i.BytesSentUnique)) - out += metric("srt_conns_bytes_received_unique", ta, int64(i.BytesReceivedUnique)) - out += metric("srt_conns_bytes_received_loss", ta, int64(i.BytesReceivedLoss)) - out += metric("srt_conns_bytes_retrans", ta, int64(i.BytesRetrans)) - out += metric("srt_conns_bytes_received_retrans", ta, int64(i.BytesReceivedRetrans)) - out += metric("srt_conns_bytes_received_belated", ta, int64(i.BytesReceivedBelated)) - out += metric("srt_conns_bytes_send_drop", ta, int64(i.BytesSendDrop)) - out += metric("srt_conns_bytes_received_drop", ta, int64(i.BytesReceivedDrop)) - out += metric("srt_conns_bytes_received_undecrypt", ta, int64(i.BytesReceivedUndecrypt)) - out += metricFloat("srt_conns_us_packets_send_period", ta, i.UsPacketsSendPeriod) - out += metric("srt_conns_packets_flow_window", ta, int64(i.PacketsFlowWindow)) - out += metric("srt_conns_packets_flight_size", ta, int64(i.PacketsFlightSize)) - out += metricFloat("srt_conns_ms_rtt", ta, i.MsRTT) - out += metricFloat("srt_conns_mbps_send_rate", ta, i.MbpsSendRate) - out += metricFloat("srt_conns_mbps_receive_rate", ta, i.MbpsReceiveRate) - out += metricFloat("srt_conns_mbps_link_capacity", ta, i.MbpsLinkCapacity) - out += metric("srt_conns_bytes_avail_send_buf", ta, int64(i.BytesAvailSendBuf)) - out += metric("srt_conns_bytes_avail_receive_buf", ta, int64(i.BytesAvailReceiveBuf)) - out += metricFloat("srt_conns_mbps_max_bw", ta, i.MbpsMaxBW) - out += metric("srt_conns_bytes_mss", ta, int64(i.ByteMSS)) - out += metric("srt_conns_packets_send_buf", ta, int64(i.PacketsSendBuf)) - out += metric("srt_conns_bytes_send_buf", ta, int64(i.BytesSendBuf)) - out += metric("srt_conns_ms_send_buf", ta, int64(i.MsSendBuf)) - out += metric("srt_conns_ms_send_tsb_pd_delay", ta, int64(i.MsSendTsbPdDelay)) - out += metric("srt_conns_packets_receive_buf", ta, int64(i.PacketsReceiveBuf)) - out += metric("srt_conns_bytes_receive_buf", ta, int64(i.BytesReceiveBuf)) - out += metric("srt_conns_ms_receive_buf", ta, int64(i.MsReceiveBuf)) - out += metric("srt_conns_ms_receive_tsb_pd_delay", ta, int64(i.MsReceiveTsbPdDelay)) - out += metric("srt_conns_packets_reorder_tolerance", ta, int64(i.PacketsReorderTolerance)) - out += metric("srt_conns_packets_received_avg_belated_time", ta, int64(i.PacketsReceivedAvgBelatedTime)) - out += metricFloat("srt_conns_packets_send_loss_rate", ta, i.PacketsSendLossRate) - out += metricFloat("srt_conns_packets_received_loss_rate", ta, i.PacketsReceivedLossRate) - out += metric("srt_conns_outbound_frames_discarded", ta, int64(i.OutboundFramesDiscarded)) + metric(&out, "srt_conns", ta, 1) + metric(&out, "srt_conns_packets_sent", ta, int64(i.PacketsSent)) + metric(&out, "srt_conns_packets_received", ta, int64(i.PacketsReceived)) + metric(&out, "srt_conns_packets_sent_unique", ta, int64(i.PacketsSentUnique)) + metric(&out, "srt_conns_packets_received_unique", ta, int64(i.PacketsReceivedUnique)) + metric(&out, "srt_conns_packets_send_loss", ta, int64(i.PacketsSendLoss)) + metric(&out, "srt_conns_packets_received_loss", ta, int64(i.PacketsReceivedLoss)) + metric(&out, "srt_conns_packets_retrans", ta, int64(i.PacketsRetrans)) + metric(&out, "srt_conns_packets_received_retrans", ta, int64(i.PacketsReceivedRetrans)) + metric(&out, "srt_conns_packets_sent_ack", ta, int64(i.PacketsSentACK)) + metric(&out, "srt_conns_packets_received_ack", ta, int64(i.PacketsReceivedACK)) + metric(&out, "srt_conns_packets_sent_nak", ta, int64(i.PacketsSentNAK)) + metric(&out, "srt_conns_packets_received_nak", ta, int64(i.PacketsReceivedNAK)) + metric(&out, "srt_conns_packets_sent_km", ta, int64(i.PacketsSentKM)) + metric(&out, "srt_conns_packets_received_km", ta, int64(i.PacketsReceivedKM)) + metric(&out, "srt_conns_us_snd_duration", ta, int64(i.UsSndDuration)) + metric(&out, "srt_conns_packets_received_belated", ta, int64(i.PacketsReceivedBelated)) + metric(&out, "srt_conns_packets_send_drop", ta, int64(i.PacketsSendDrop)) + metric(&out, "srt_conns_packets_received_drop", ta, int64(i.PacketsReceivedDrop)) + metric(&out, "srt_conns_packets_received_undecrypt", ta, int64(i.PacketsReceivedUndecrypt)) + metric(&out, "srt_conns_bytes_sent", ta, int64(i.BytesSent)) + metric(&out, "srt_conns_bytes_received", ta, int64(i.BytesReceived)) + metric(&out, "srt_conns_bytes_sent_unique", ta, int64(i.BytesSentUnique)) + metric(&out, "srt_conns_bytes_received_unique", ta, int64(i.BytesReceivedUnique)) + metric(&out, "srt_conns_bytes_received_loss", ta, int64(i.BytesReceivedLoss)) + metric(&out, "srt_conns_bytes_retrans", ta, int64(i.BytesRetrans)) + metric(&out, "srt_conns_bytes_received_retrans", ta, int64(i.BytesReceivedRetrans)) + metric(&out, "srt_conns_bytes_received_belated", ta, int64(i.BytesReceivedBelated)) + metric(&out, "srt_conns_bytes_send_drop", ta, int64(i.BytesSendDrop)) + metric(&out, "srt_conns_bytes_received_drop", ta, int64(i.BytesReceivedDrop)) + metric(&out, "srt_conns_bytes_received_undecrypt", ta, int64(i.BytesReceivedUndecrypt)) + metricFloat(&out, "srt_conns_us_packets_send_period", ta, i.UsPacketsSendPeriod) + metric(&out, "srt_conns_packets_flow_window", ta, int64(i.PacketsFlowWindow)) + metric(&out, "srt_conns_packets_flight_size", ta, int64(i.PacketsFlightSize)) + metricFloat(&out, "srt_conns_ms_rtt", ta, i.MsRTT) + metricFloat(&out, "srt_conns_mbps_send_rate", ta, i.MbpsSendRate) + metricFloat(&out, "srt_conns_mbps_receive_rate", ta, i.MbpsReceiveRate) + metricFloat(&out, "srt_conns_mbps_link_capacity", ta, i.MbpsLinkCapacity) + metric(&out, "srt_conns_bytes_avail_send_buf", ta, int64(i.BytesAvailSendBuf)) + metric(&out, "srt_conns_bytes_avail_receive_buf", ta, int64(i.BytesAvailReceiveBuf)) + metricFloat(&out, "srt_conns_mbps_max_bw", ta, i.MbpsMaxBW) + metric(&out, "srt_conns_bytes_mss", ta, int64(i.ByteMSS)) + metric(&out, "srt_conns_packets_send_buf", ta, int64(i.PacketsSendBuf)) + metric(&out, "srt_conns_bytes_send_buf", ta, int64(i.BytesSendBuf)) + metric(&out, "srt_conns_ms_send_buf", ta, int64(i.MsSendBuf)) + metric(&out, "srt_conns_ms_send_tsb_pd_delay", ta, int64(i.MsSendTsbPdDelay)) + metric(&out, "srt_conns_packets_receive_buf", ta, int64(i.PacketsReceiveBuf)) + metric(&out, "srt_conns_bytes_receive_buf", ta, int64(i.BytesReceiveBuf)) + metric(&out, "srt_conns_ms_receive_buf", ta, int64(i.MsReceiveBuf)) + metric(&out, "srt_conns_ms_receive_tsb_pd_delay", ta, int64(i.MsReceiveTsbPdDelay)) + metric(&out, "srt_conns_packets_reorder_tolerance", ta, int64(i.PacketsReorderTolerance)) + metric(&out, "srt_conns_packets_received_avg_belated_time", ta, int64(i.PacketsReceivedAvgBelatedTime)) + metricFloat(&out, "srt_conns_packets_send_loss_rate", ta, i.PacketsSendLossRate) + metricFloat(&out, "srt_conns_packets_received_loss_rate", ta, i.PacketsReceivedLossRate) + metric(&out, "srt_conns_outbound_frames_discarded", ta, int64(i.OutboundFramesDiscarded)) } } } else if srtConnFilter == "" { - out += metric("srt_conns", "", 0) - out += metric("srt_conns_packets_sent", "", 0) - out += metric("srt_conns_packets_received", "", 0) - out += metric("srt_conns_packets_sent_unique", "", 0) - out += metric("srt_conns_packets_received_unique", "", 0) - out += metric("srt_conns_packets_send_loss", "", 0) - out += metric("srt_conns_packets_received_loss", "", 0) - out += metric("srt_conns_packets_retrans", "", 0) - out += metric("srt_conns_packets_received_retrans", "", 0) - out += metric("srt_conns_packets_sent_ack", "", 0) - out += metric("srt_conns_packets_received_ack", "", 0) - out += metric("srt_conns_packets_sent_nak", "", 0) - out += metric("srt_conns_packets_received_nak", "", 0) - out += metric("srt_conns_packets_sent_km", "", 0) - out += metric("srt_conns_packets_received_km", "", 0) - out += metric("srt_conns_us_snd_duration", "", 0) - out += metric("srt_conns_packets_received_belated", "", 0) - out += metric("srt_conns_packets_send_drop", "", 0) - out += metric("srt_conns_packets_received_drop", "", 0) - out += metric("srt_conns_packets_received_undecrypt", "", 0) - out += metric("srt_conns_bytes_sent", "", 0) - out += metric("srt_conns_bytes_received", "", 0) - out += metric("srt_conns_bytes_sent_unique", "", 0) - out += metric("srt_conns_bytes_received_unique", "", 0) - out += metric("srt_conns_bytes_received_loss", "", 0) - out += metric("srt_conns_bytes_retrans", "", 0) - out += metric("srt_conns_bytes_received_retrans", "", 0) - out += metric("srt_conns_bytes_received_belated", "", 0) - out += metric("srt_conns_bytes_send_drop", "", 0) - out += metric("srt_conns_bytes_received_drop", "", 0) - out += metric("srt_conns_bytes_received_undecrypt", "", 0) - out += metricFloat("srt_conns_us_packets_send_period", "", 0) - out += metric("srt_conns_packets_flow_window", "", 0) - out += metric("srt_conns_packets_flight_size", "", 0) - out += metricFloat("srt_conns_ms_rtt", "", 0) - out += metricFloat("srt_conns_mbps_send_rate", "", 0) - out += metricFloat("srt_conns_mbps_receive_rate", "", 0) - out += metricFloat("srt_conns_mbps_link_capacity", "", 0) - out += metric("srt_conns_bytes_avail_send_buf", "", 0) - out += metric("srt_conns_bytes_avail_receive_buf", "", 0) - out += metricFloat("srt_conns_mbps_max_bw", "", 0) - out += metric("srt_conns_bytes_mss", "", 0) - out += metric("srt_conns_packets_send_buf", "", 0) - out += metric("srt_conns_bytes_send_buf", "", 0) - out += metric("srt_conns_ms_send_buf", "", 0) - out += metric("srt_conns_ms_send_tsb_pd_delay", "", 0) - out += metric("srt_conns_packets_receive_buf", "", 0) - out += metric("srt_conns_bytes_receive_buf", "", 0) - out += metric("srt_conns_ms_receive_buf", "", 0) - out += metric("srt_conns_ms_receive_tsb_pd_delay", "", 0) - out += metric("srt_conns_packets_reorder_tolerance", "", 0) - out += metric("srt_conns_packets_received_avg_belated_time", "", 0) - out += metricFloat("srt_conns_packets_send_loss_rate", "", 0) - out += metricFloat("srt_conns_packets_received_loss_rate", "", 0) - out += metric("srt_conns_outbound_frames_discarded", "", 0) + metric(&out, "srt_conns", "", 0) + metric(&out, "srt_conns_packets_sent", "", 0) + metric(&out, "srt_conns_packets_received", "", 0) + metric(&out, "srt_conns_packets_sent_unique", "", 0) + metric(&out, "srt_conns_packets_received_unique", "", 0) + metric(&out, "srt_conns_packets_send_loss", "", 0) + metric(&out, "srt_conns_packets_received_loss", "", 0) + metric(&out, "srt_conns_packets_retrans", "", 0) + metric(&out, "srt_conns_packets_received_retrans", "", 0) + metric(&out, "srt_conns_packets_sent_ack", "", 0) + metric(&out, "srt_conns_packets_received_ack", "", 0) + metric(&out, "srt_conns_packets_sent_nak", "", 0) + metric(&out, "srt_conns_packets_received_nak", "", 0) + metric(&out, "srt_conns_packets_sent_km", "", 0) + metric(&out, "srt_conns_packets_received_km", "", 0) + metric(&out, "srt_conns_us_snd_duration", "", 0) + metric(&out, "srt_conns_packets_received_belated", "", 0) + metric(&out, "srt_conns_packets_send_drop", "", 0) + metric(&out, "srt_conns_packets_received_drop", "", 0) + metric(&out, "srt_conns_packets_received_undecrypt", "", 0) + metric(&out, "srt_conns_bytes_sent", "", 0) + metric(&out, "srt_conns_bytes_received", "", 0) + metric(&out, "srt_conns_bytes_sent_unique", "", 0) + metric(&out, "srt_conns_bytes_received_unique", "", 0) + metric(&out, "srt_conns_bytes_received_loss", "", 0) + metric(&out, "srt_conns_bytes_retrans", "", 0) + metric(&out, "srt_conns_bytes_received_retrans", "", 0) + metric(&out, "srt_conns_bytes_received_belated", "", 0) + metric(&out, "srt_conns_bytes_send_drop", "", 0) + metric(&out, "srt_conns_bytes_received_drop", "", 0) + metric(&out, "srt_conns_bytes_received_undecrypt", "", 0) + metricFloat(&out, "srt_conns_us_packets_send_period", "", 0) + metric(&out, "srt_conns_packets_flow_window", "", 0) + metric(&out, "srt_conns_packets_flight_size", "", 0) + metricFloat(&out, "srt_conns_ms_rtt", "", 0) + metricFloat(&out, "srt_conns_mbps_send_rate", "", 0) + metricFloat(&out, "srt_conns_mbps_receive_rate", "", 0) + metricFloat(&out, "srt_conns_mbps_link_capacity", "", 0) + metric(&out, "srt_conns_bytes_avail_send_buf", "", 0) + metric(&out, "srt_conns_bytes_avail_receive_buf", "", 0) + metricFloat(&out, "srt_conns_mbps_max_bw", "", 0) + metric(&out, "srt_conns_bytes_mss", "", 0) + metric(&out, "srt_conns_packets_send_buf", "", 0) + metric(&out, "srt_conns_bytes_send_buf", "", 0) + metric(&out, "srt_conns_ms_send_buf", "", 0) + metric(&out, "srt_conns_ms_send_tsb_pd_delay", "", 0) + metric(&out, "srt_conns_packets_receive_buf", "", 0) + metric(&out, "srt_conns_bytes_receive_buf", "", 0) + metric(&out, "srt_conns_ms_receive_buf", "", 0) + metric(&out, "srt_conns_ms_receive_tsb_pd_delay", "", 0) + metric(&out, "srt_conns_packets_reorder_tolerance", "", 0) + metric(&out, "srt_conns_packets_received_avg_belated_time", "", 0) + metricFloat(&out, "srt_conns_packets_send_loss_rate", "", 0) + metricFloat(&out, "srt_conns_packets_received_loss_rate", "", 0) + metric(&out, "srt_conns_outbound_frames_discarded", "", 0) } } @@ -681,52 +690,52 @@ func (m *Metrics) onMetrics(ctx *gin.Context) { "path": i.Path, "remoteAddr": i.RemoteAddr, }) - out += metric("webrtc_sessions", ta, 1) - out += metric("webrtc_sessions_inbound_bytes", ta, int64(i.InboundBytes)) - out += metric("webrtc_sessions_inbound_rtp_packets", ta, int64(i.InboundRTPPackets)) - out += metric("webrtc_sessions_inbound_rtp_packets_lost", ta, int64(i.InboundRTPPacketsLost)) - out += metricFloat("webrtc_sessions_inbound_rtp_packets_jitter", ta, i.InboundRTPPacketsJitter) - out += metric("webrtc_sessions_inbound_rtcp_packets", ta, int64(i.InboundRTCPPackets)) - out += metric("webrtc_sessions_outbound_bytes", ta, int64(i.OutboundBytes)) - out += metric("webrtc_sessions_outbound_rtp_packets", ta, int64(i.OutboundRTPPackets)) - out += metric("webrtc_sessions_outbound_rtcp_packets", ta, int64(i.OutboundRTCPPackets)) - out += metric("webrtc_sessions_outbound_frames_discarded", ta, int64(i.OutboundFramesDiscarded)) + metric(&out, "webrtc_sessions", ta, 1) + metric(&out, "webrtc_sessions_inbound_bytes", ta, int64(i.InboundBytes)) + metric(&out, "webrtc_sessions_inbound_rtp_packets", ta, int64(i.InboundRTPPackets)) + metric(&out, "webrtc_sessions_inbound_rtp_packets_lost", ta, int64(i.InboundRTPPacketsLost)) + metricFloat(&out, "webrtc_sessions_inbound_rtp_packets_jitter", ta, i.InboundRTPPacketsJitter) + metric(&out, "webrtc_sessions_inbound_rtcp_packets", ta, int64(i.InboundRTCPPackets)) + metric(&out, "webrtc_sessions_outbound_bytes", ta, int64(i.OutboundBytes)) + metric(&out, "webrtc_sessions_outbound_rtp_packets", ta, int64(i.OutboundRTPPackets)) + metric(&out, "webrtc_sessions_outbound_rtcp_packets", ta, int64(i.OutboundRTCPPackets)) + metric(&out, "webrtc_sessions_outbound_frames_discarded", ta, int64(i.OutboundFramesDiscarded)) // deprecated - out += metric("webrtc_sessions_bytes_received", ta, int64(i.BytesReceived)) - out += metric("webrtc_sessions_bytes_sent", ta, int64(i.BytesSent)) - out += metric("webrtc_sessions_rtp_packets_received", ta, int64(i.RTPPacketsReceived)) - out += metric("webrtc_sessions_rtp_packets_sent", ta, int64(i.RTPPacketsSent)) - out += metric("webrtc_sessions_rtp_packets_lost", ta, int64(i.RTPPacketsLost)) - out += metricFloat("webrtc_sessions_rtp_packets_jitter", ta, i.RTPPacketsJitter) - out += metric("webrtc_sessions_rtcp_packets_received", ta, int64(i.RTCPPacketsReceived)) - out += metric("webrtc_sessions_rtcp_packets_sent", ta, int64(i.RTCPPacketsSent)) + metric(&out, "webrtc_sessions_bytes_received", ta, int64(i.BytesReceived)) + metric(&out, "webrtc_sessions_bytes_sent", ta, int64(i.BytesSent)) + metric(&out, "webrtc_sessions_rtp_packets_received", ta, int64(i.RTPPacketsReceived)) + metric(&out, "webrtc_sessions_rtp_packets_sent", ta, int64(i.RTPPacketsSent)) + metric(&out, "webrtc_sessions_rtp_packets_lost", ta, int64(i.RTPPacketsLost)) + metricFloat(&out, "webrtc_sessions_rtp_packets_jitter", ta, i.RTPPacketsJitter) + metric(&out, "webrtc_sessions_rtcp_packets_received", ta, int64(i.RTCPPacketsReceived)) + metric(&out, "webrtc_sessions_rtcp_packets_sent", ta, int64(i.RTCPPacketsSent)) } } } else if webrtcSessionFilter == "" { - out += metric("webrtc_sessions", "", 0) - out += metric("webrtc_sessions_inbound_bytes", "", 0) - out += metric("webrtc_sessions_inbound_rtp_packets", "", 0) - out += metric("webrtc_sessions_inbound_rtp_packets_lost", "", 0) - out += metricFloat("webrtc_sessions_inbound_rtp_packets_jitter", "", 0) - out += metric("webrtc_sessions_inbound_rtcp_packets", "", 0) - out += metric("webrtc_sessions_outbound_bytes", "", 0) - out += metric("webrtc_sessions_outbound_rtp_packets", "", 0) - out += metric("webrtc_sessions_outbound_rtcp_packets", "", 0) - out += metric("webrtc_sessions_outbound_frames_discarded", "", 0) + metric(&out, "webrtc_sessions", "", 0) + metric(&out, "webrtc_sessions_inbound_bytes", "", 0) + metric(&out, "webrtc_sessions_inbound_rtp_packets", "", 0) + metric(&out, "webrtc_sessions_inbound_rtp_packets_lost", "", 0) + metricFloat(&out, "webrtc_sessions_inbound_rtp_packets_jitter", "", 0) + metric(&out, "webrtc_sessions_inbound_rtcp_packets", "", 0) + metric(&out, "webrtc_sessions_outbound_bytes", "", 0) + metric(&out, "webrtc_sessions_outbound_rtp_packets", "", 0) + metric(&out, "webrtc_sessions_outbound_rtcp_packets", "", 0) + metric(&out, "webrtc_sessions_outbound_frames_discarded", "", 0) // deprecated - out += metric("webrtc_sessions_bytes_received", "", 0) - out += metric("webrtc_sessions_bytes_sent", "", 0) - out += metric("webrtc_sessions_rtp_packets_received", "", 0) - out += metric("webrtc_sessions_rtp_packets_sent", "", 0) - out += metric("webrtc_sessions_rtp_packets_lost", "", 0) - out += metricFloat("webrtc_sessions_rtp_packets_jitter", "", 0) - out += metric("webrtc_sessions_rtcp_packets_received", "", 0) - out += metric("webrtc_sessions_rtcp_packets_sent", "", 0) + metric(&out, "webrtc_sessions_bytes_received", "", 0) + metric(&out, "webrtc_sessions_bytes_sent", "", 0) + metric(&out, "webrtc_sessions_rtp_packets_received", "", 0) + metric(&out, "webrtc_sessions_rtp_packets_sent", "", 0) + metric(&out, "webrtc_sessions_rtp_packets_lost", "", 0) + metricFloat(&out, "webrtc_sessions_rtp_packets_jitter", "", 0) + metric(&out, "webrtc_sessions_rtcp_packets_received", "", 0) + metric(&out, "webrtc_sessions_rtcp_packets_sent", "", 0) } } ctx.Writer.WriteHeader(http.StatusOK) - io.WriteString(ctx.Writer, out) //nolint:errcheck + ctx.Writer.WriteString(out.String()) //nolint:errcheck } // SetPathManager is called by core. diff --git a/internal/metrics/metrics_test.go b/internal/metrics/metrics_test.go index e1544403..23fc3180 100644 --- a/internal/metrics/metrics_test.go +++ b/internal/metrics/metrics_test.go @@ -191,6 +191,85 @@ func (dummyRTMPServer) APIConnsKick(uuid.UUID) error { panic("unused") } +type dummySRTServer struct{} + +func (dummySRTServer) APIConnsList() (*defs.APISRTConnList, error) { + return &defs.APISRTConnList{ + ItemCount: 1, + PageCount: 1, + Items: []defs.APISRTConn{{ + ID: uuid.MustParse("a0b1c2d3-e4f5-6789-abcd-ef0123456789"), + Created: time.Date(2003, 11, 4, 23, 15, 7, 0, time.UTC), + RemoteAddr: "5.5.5.5:4321", + State: defs.APISRTConnStatePublish, + Path: "mypath", + Query: "myquery", + PacketsSent: 100, + PacketsReceived: 200, + PacketsSentUnique: 90, + PacketsReceivedUnique: 180, + PacketsSendLoss: 10, + PacketsReceivedLoss: 20, + PacketsRetrans: 5, + PacketsReceivedRetrans: 3, + PacketsSentACK: 50, + PacketsReceivedACK: 40, + PacketsSentNAK: 2, + PacketsReceivedNAK: 1, + PacketsSentKM: 4, + PacketsReceivedKM: 3, + UsSndDuration: 1000000, + PacketsReceivedBelated: 7, + PacketsSendDrop: 8, + PacketsReceivedDrop: 6, + PacketsReceivedUndecrypt: 0, + BytesSent: 12345, + BytesReceived: 67890, + BytesSentUnique: 11000, + BytesReceivedUnique: 60000, + BytesReceivedLoss: 500, + BytesRetrans: 300, + BytesReceivedRetrans: 200, + BytesReceivedBelated: 100, + BytesSendDrop: 400, + BytesReceivedDrop: 350, + BytesReceivedUndecrypt: 0, + UsPacketsSendPeriod: 10.5, + PacketsFlowWindow: 8192, + PacketsFlightSize: 25, + MsRTT: 1.5, + MbpsSendRate: 50.0, + MbpsReceiveRate: 48.0, + MbpsLinkCapacity: 100.0, + BytesAvailSendBuf: 65536, + BytesAvailReceiveBuf: 65536, + MbpsMaxBW: 100.0, + ByteMSS: 1500, + PacketsSendBuf: 10, + BytesSendBuf: 15000, + MsSendBuf: 120, + MsSendTsbPdDelay: 120, + PacketsReceiveBuf: 15, + BytesReceiveBuf: 22500, + MsReceiveBuf: 120, + MsReceiveTsbPdDelay: 120, + PacketsReorderTolerance: 3, + PacketsReceivedAvgBelatedTime: 50, + PacketsSendLossRate: 0.01, + PacketsReceivedLossRate: 0.02, + OutboundFramesDiscarded: 5, + }}, + }, nil +} + +func (dummySRTServer) APIConnsGet(uuid.UUID) (*defs.APISRTConn, error) { + panic("unused") +} + +func (dummySRTServer) APIConnsKick(uuid.UUID) error { + panic("unused") +} + type dummyWebRTCServer struct{} func (dummyWebRTCServer) APISessionsList() (*defs.APIWebRTCSessionList, error) { @@ -303,6 +382,7 @@ func TestMetrics(t *testing.T) { m.SetRTSPSServer(&dummyRTSPServer{}) m.SetRTMPServer(&dummyRTMPServer{}) m.SetRTMPSServer(&dummyRTMPServer{}) + m.SetSRTServer(&dummySRTServer{}) m.SetWebRTCServer(&dummyWebRTCServer{}) tr := &http.Transport{} @@ -537,3 +617,71 @@ func TestFilter(t *testing.T) { }) } } + +func BenchmarkTags(b *testing.B) { + m := map[string]string{ + "id": "124b22ce-9c34-4387-b045-44caf98049f7", + "state": "publish", + "path": "mypath", + "remoteAddr": "124.5.5.5:34542", + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + tags(m) + } +} + +func BenchmarkMetric(b *testing.B) { + ta := tags(map[string]string{ + "id": "124b22ce-9c34-4387-b045-44caf98049f7", + "state": "publish", + "path": "mypath", + "remoteAddr": "124.5.5.5:34542", + }) + var out strings.Builder + b.ResetTimer() + for i := 0; i < b.N; i++ { + out.Reset() + metric(&out, "rtsp_sessions_inbound_bytes", ta, 123) + } +} + +func BenchmarkFullMetricsHandler(b *testing.B) { + m := Metrics{ + Address: "localhost:9998", + AllowOrigins: []string{"*"}, + ReadTimeout: conf.Duration(10 * time.Second), + WriteTimeout: conf.Duration(10 * time.Second), + AuthManager: test.NilAuthManager, + Parent: test.NilLogger, + } + err := m.Initialize() + if err != nil { + b.Fatal(err) + } + defer m.Close() + + m.SetPathManager(&dummyPathManager{}) + m.SetHLSServer(&dummyHLSServer{}) + m.SetRTSPServer(&dummyRTSPServer{}) + m.SetRTSPSServer(&dummyRTSPServer{}) + m.SetRTMPServer(&dummyRTMPServer{}) + m.SetRTMPSServer(&dummyRTMPServer{}) + m.SetSRTServer(&dummySRTServer{}) + m.SetWebRTCServer(&dummyWebRTCServer{}) + + tr := &http.Transport{} + defer tr.CloseIdleConnections() + hc := &http.Client{Transport: tr} + + b.ResetTimer() + for i := 0; i < b.N; i++ { + var res *http.Response + res, err = hc.Get("http://localhost:9998/metrics") + if err != nil { + b.Fatal(err) + } + io.Copy(io.Discard, res.Body) + res.Body.Close() + } +}