metrics: return metrics even if there are no paths or clients (#1688)
This commit is contained in:
parent
88953f36a6
commit
79872cabd6
|
@ -16,8 +16,8 @@ import (
|
|||
"github.com/aler9/mediamtx/internal/logger"
|
||||
)
|
||||
|
||||
func metric(key string, value int64) string {
|
||||
return key + " " + strconv.FormatInt(value, 10) + "\n"
|
||||
func metric(key string, tags string, value int64) string {
|
||||
return key + tags + " " + strconv.FormatInt(value, 10) + "\n"
|
||||
}
|
||||
|
||||
type metricsParent interface {
|
||||
|
@ -87,7 +87,7 @@ func (m *metrics) onMetrics(ctx *gin.Context) {
|
|||
out := ""
|
||||
|
||||
res := m.pathManager.apiPathsList()
|
||||
if res.err == nil {
|
||||
if res.err == nil && len(res.data.Items) != 0 {
|
||||
for name, i := range res.data.Items {
|
||||
var state string
|
||||
if i.SourceReady {
|
||||
|
@ -97,44 +97,57 @@ func (m *metrics) onMetrics(ctx *gin.Context) {
|
|||
}
|
||||
|
||||
tags := "{name=\"" + name + "\",state=\"" + state + "\"}"
|
||||
out += metric("paths"+tags, 1)
|
||||
out += metric("paths_bytes_received"+tags, int64(i.BytesReceived))
|
||||
out += metric("paths", tags, 1)
|
||||
out += metric("paths_bytes_received", tags, int64(i.BytesReceived))
|
||||
}
|
||||
} else {
|
||||
out += metric("paths", "", 0)
|
||||
}
|
||||
|
||||
if !interfaceIsEmpty(m.hlsServer) {
|
||||
res := m.hlsServer.apiMuxersList()
|
||||
if res.err == nil {
|
||||
if res.err == nil && len(res.data.Items) != 0 {
|
||||
for name, i := range res.data.Items {
|
||||
tags := "{name=\"" + name + "\"}"
|
||||
out += metric("hls_muxers"+tags, 1)
|
||||
out += metric("hls_muxers_bytes_sent"+tags, int64(i.BytesSent))
|
||||
out += metric("hls_muxers", tags, 1)
|
||||
out += metric("hls_muxers_bytes_sent", tags, int64(i.BytesSent))
|
||||
}
|
||||
} else {
|
||||
out += metric("hls_muxers", "", 0)
|
||||
out += metric("hls_muxers_bytes_sent", "", 0)
|
||||
}
|
||||
}
|
||||
|
||||
if !interfaceIsEmpty(m.rtspServer) { //nolint:dupl
|
||||
func() {
|
||||
res := m.rtspServer.apiConnsList()
|
||||
if res.err == nil {
|
||||
if res.err == nil && len(res.data.Items) != 0 {
|
||||
for id, i := range res.data.Items {
|
||||
tags := "{id=\"" + id + "\"}"
|
||||
out += metric("rtsp_conns"+tags, 1)
|
||||
out += metric("rtsp_conns_bytes_received"+tags, int64(i.BytesReceived))
|
||||
out += metric("rtsp_conns_bytes_sent"+tags, int64(i.BytesSent))
|
||||
out += metric("rtsp_conns", tags, 1)
|
||||
out += metric("rtsp_conns_bytes_received", tags, int64(i.BytesReceived))
|
||||
out += metric("rtsp_conns_bytes_sent", tags, int64(i.BytesSent))
|
||||
}
|
||||
} else {
|
||||
out += metric("rtsp_conns", "", 0)
|
||||
out += metric("rtsp_conns_bytes_received", "", 0)
|
||||
out += metric("rtsp_conns_bytes_sent", "", 0)
|
||||
}
|
||||
}()
|
||||
|
||||
func() {
|
||||
res := m.rtspServer.apiSessionsList()
|
||||
if res.err == nil {
|
||||
if res.err == nil && len(res.data.Items) != 0 {
|
||||
for id, i := range res.data.Items {
|
||||
tags := "{id=\"" + id + "\",state=\"" + i.State + "\"}"
|
||||
out += metric("rtsp_sessions"+tags, 1)
|
||||
out += metric("rtsp_sessions_bytes_received"+tags, int64(i.BytesReceived))
|
||||
out += metric("rtsp_sessions_bytes_sent"+tags, int64(i.BytesSent))
|
||||
out += metric("rtsp_sessions", tags, 1)
|
||||
out += metric("rtsp_sessions_bytes_received", tags, int64(i.BytesReceived))
|
||||
out += metric("rtsp_sessions_bytes_sent", tags, int64(i.BytesSent))
|
||||
}
|
||||
} else {
|
||||
out += metric("rtsp_sessions", "", 0)
|
||||
out += metric("rtsp_sessions_bytes_received", "", 0)
|
||||
out += metric("rtsp_sessions_bytes_sent", "", 0)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
@ -142,50 +155,66 @@ func (m *metrics) onMetrics(ctx *gin.Context) {
|
|||
if !interfaceIsEmpty(m.rtspsServer) { //nolint:dupl
|
||||
func() {
|
||||
res := m.rtspsServer.apiConnsList()
|
||||
if res.err == nil {
|
||||
if res.err == nil && len(res.data.Items) != 0 {
|
||||
for id, i := range res.data.Items {
|
||||
tags := "{id=\"" + id + "\"}"
|
||||
out += metric("rtsps_conns"+tags, 1)
|
||||
out += metric("rtsps_conns_bytes_received"+tags, int64(i.BytesReceived))
|
||||
out += metric("rtsps_conns_bytes_sent"+tags, int64(i.BytesSent))
|
||||
out += metric("rtsps_conns", tags, 1)
|
||||
out += metric("rtsps_conns_bytes_received", tags, int64(i.BytesReceived))
|
||||
out += metric("rtsps_conns_bytes_sent", tags, int64(i.BytesSent))
|
||||
}
|
||||
} else {
|
||||
out += metric("rtsps_conns", "", 0)
|
||||
out += metric("rtsps_conns_bytes_received", "", 0)
|
||||
out += metric("rtsps_conns_bytes_sent", "", 0)
|
||||
}
|
||||
}()
|
||||
|
||||
func() {
|
||||
res := m.rtspsServer.apiSessionsList()
|
||||
if res.err == nil {
|
||||
if res.err == nil && len(res.data.Items) != 0 {
|
||||
for id, i := range res.data.Items {
|
||||
tags := "{id=\"" + id + "\",state=\"" + i.State + "\"}"
|
||||
out += metric("rtsps_sessions"+tags, 1)
|
||||
out += metric("rtsps_sessions_bytes_received"+tags, int64(i.BytesReceived))
|
||||
out += metric("rtsps_sessions_bytes_sent"+tags, int64(i.BytesSent))
|
||||
out += metric("rtsps_sessions", tags, 1)
|
||||
out += metric("rtsps_sessions_bytes_received", tags, int64(i.BytesReceived))
|
||||
out += metric("rtsps_sessions_bytes_sent", tags, int64(i.BytesSent))
|
||||
}
|
||||
} else {
|
||||
out += metric("rtsps_sessions", "", 0)
|
||||
out += metric("rtsps_sessions_bytes_received", "", 0)
|
||||
out += metric("rtsps_sessions_bytes_sent", "", 0)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
if !interfaceIsEmpty(m.rtmpServer) {
|
||||
res := m.rtmpServer.apiConnsList()
|
||||
if res.err == nil {
|
||||
if res.err == nil && len(res.data.Items) != 0 {
|
||||
for id, i := range res.data.Items {
|
||||
tags := "{id=\"" + id + "\",state=\"" + i.State + "\"}"
|
||||
out += metric("rtmp_conns"+tags, 1)
|
||||
out += metric("rtmp_conns_bytes_received"+tags, int64(i.BytesReceived))
|
||||
out += metric("rtmp_conns_bytes_sent"+tags, int64(i.BytesSent))
|
||||
out += metric("rtmp_conns", tags, 1)
|
||||
out += metric("rtmp_conns_bytes_received", tags, int64(i.BytesReceived))
|
||||
out += metric("rtmp_conns_bytes_sent", tags, int64(i.BytesSent))
|
||||
}
|
||||
} else {
|
||||
out += metric("rtmp_conns", "", 0)
|
||||
out += metric("rtmp_conns_bytes_received", "", 0)
|
||||
out += metric("rtmp_conns_bytes_sent", "", 0)
|
||||
}
|
||||
}
|
||||
|
||||
if !interfaceIsEmpty(m.webRTCServer) {
|
||||
res := m.webRTCServer.apiConnsList()
|
||||
if res.err == nil {
|
||||
if res.err == nil && len(res.data.Items) != 0 {
|
||||
for id, i := range res.data.Items {
|
||||
tags := "{id=\"" + id + "\"}"
|
||||
out += metric("webrtc_conns"+tags, 1)
|
||||
out += metric("webrtc_conns_bytes_received"+tags, int64(i.BytesReceived))
|
||||
out += metric("webrtc_conns_bytes_sent"+tags, int64(i.BytesSent))
|
||||
out += metric("webrtc_conns", tags, 1)
|
||||
out += metric("webrtc_conns_bytes_received", tags, int64(i.BytesReceived))
|
||||
out += metric("webrtc_conns_bytes_sent", tags, int64(i.BytesSent))
|
||||
}
|
||||
} else {
|
||||
out += metric("webrtc_conns", "", 0)
|
||||
out += metric("webrtc_conns_bytes_received", "", 0)
|
||||
out += metric("webrtc_conns_bytes_sent", "", 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package core
|
|||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
|
@ -17,6 +18,25 @@ import (
|
|||
"github.com/aler9/mediamtx/internal/rtmp"
|
||||
)
|
||||
|
||||
func pullMetrics() ([]byte, error) {
|
||||
req, err := http.NewRequest(http.MethodGet, "http://localhost:9998/metrics", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("bad status code: %v", res.StatusCode)
|
||||
}
|
||||
|
||||
return io.ReadAll(res.Body)
|
||||
}
|
||||
|
||||
func TestMetrics(t *testing.T) {
|
||||
serverCertFpath, err := writeTempFile(serverCert)
|
||||
require.NoError(t, err)
|
||||
|
@ -37,6 +57,32 @@ func TestMetrics(t *testing.T) {
|
|||
require.Equal(t, true, ok)
|
||||
defer p.Close()
|
||||
|
||||
bo, err := pullMetrics()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, `paths 0
|
||||
hls_muxers 0
|
||||
hls_muxers_bytes_sent 0
|
||||
rtsp_conns 0
|
||||
rtsp_conns_bytes_received 0
|
||||
rtsp_conns_bytes_sent 0
|
||||
rtsp_sessions 0
|
||||
rtsp_sessions_bytes_received 0
|
||||
rtsp_sessions_bytes_sent 0
|
||||
rtsps_conns 0
|
||||
rtsps_conns_bytes_received 0
|
||||
rtsps_conns_bytes_sent 0
|
||||
rtsps_sessions 0
|
||||
rtsps_sessions_bytes_received 0
|
||||
rtsps_sessions_bytes_sent 0
|
||||
rtmp_conns 0
|
||||
rtmp_conns_bytes_received 0
|
||||
rtmp_conns_bytes_sent 0
|
||||
webrtc_conns 0
|
||||
webrtc_conns_bytes_received 0
|
||||
webrtc_conns_bytes_sent 0
|
||||
`, string(bo))
|
||||
|
||||
medi := testMediaH264
|
||||
|
||||
source := gortsplib.Client{}
|
||||
|
@ -83,15 +129,7 @@ func TestMetrics(t *testing.T) {
|
|||
require.Equal(t, 200, res.StatusCode)
|
||||
}()
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "http://localhost:9998/metrics", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer res.Body.Close()
|
||||
require.Equal(t, http.StatusOK, res.StatusCode)
|
||||
|
||||
bo, err := io.ReadAll(res.Body)
|
||||
bo, err = pullMetrics()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Regexp(t,
|
||||
|
@ -118,6 +156,9 @@ func TestMetrics(t *testing.T) {
|
|||
`rtmp_conns\{id=".*?",state="publish"\} 1`+"\n"+
|
||||
`rtmp_conns_bytes_received\{id=".*?",state="publish"\} [0-9]+`+"\n"+
|
||||
`rtmp_conns_bytes_sent\{id=".*?",state="publish"\} [0-9]+`+"\n"+
|
||||
`webrtc_conns 0`+"\n"+
|
||||
`webrtc_conns_bytes_received 0`+"\n"+
|
||||
`webrtc_conns_bytes_sent 0`+"\n"+
|
||||
"$",
|
||||
string(bo))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue