MediaMTX 指标监控完全指南:启用 Prometheus 兼容的 Metrics 服务与全量指标解读
【免费下载链接】mediamtxReady-to-use Media-over-QUIC / SRT / WebRTC / RTSP / RTMP / LL-HLS / MPEG-TS / RTP live media server and media proxy that allows to read, publish, proxy, record and playback real-time video and audio streams.项目地址: https://gitcode.com/GitHub_Trending/me/mediamtx
MediaMTX 内置一套与 Prometheus 兼容的指标(metrics)服务,通过独立 HTTP 端口对外提供 Path、HLS、RTSP/RTSPS、RTMP/RTMPS、SRT、WebRTC、MoQ 会话以及转发目的地的实时运行数据。本文以官方文档 docs/2-features/22-metrics.md 为主体,结合 内部实现源码 与 默认配置 逐步讲清如何开启该服务、如何用 curl 或 Prometheus 抓取指标、每一组指标的含义,以及如何用查询参数精确筛选出关心的那一小部分数据,最终支撑 Grafana 等分析器完成码率、丢包、延迟等可视化监控。
一、开启 Metrics 服务:一条配置项即可上线
MediaMTX 的指标服务默认关闭,只需在配置文件中设置metrics: yes(或true)即可启用:
# Enable the metrics server, which allows to extract Prometheus-compatible metrics. metrics: false启用后,服务会在独立端口监听,默认地址为:9998。完整相关的配置项位于 mediamtx.yml 的Global settings -> Metrics server一节,说明如下:
| 配置项 | 默认值 | 说明 |
|---|---|---|
metrics | false | 是否启用指标服务器 |
metricsAddress | :9998 | TCP/HTTP 监听地址 |
metricsEncryption | false | 是否启用 HTTPS |
metricsServerKey | server.key | HTTPS 所需的服务器私钥(仅在启用加密时需要) |
metricsServerCert | server.crt | HTTPS 所需的服务器证书(仅在启用加密时需要) |
metricsAllowOrigins | [] | 允许的 CORS 来源,支持通配符,如['http://*.example.com'] |
metricsTrustedProxies | [] | 位于 HTTP 服务器前面的代理 IP/CIDR,这些代理可通过X-Forwarded-For设置客户端真实 IP、通过X-Forwarded-Proto设置原始协议 |
如果启用 HTTPS,可参照配置注释中的方式生成自签名证书:
openssl genrsa -out server.key 2048 openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650从源码层面看,核心装配发生在 internal/core/core.go:当currentConf.Metrics为真且实例尚未创建时,程序会构造metrics.Metrics,把地址、加密、证书、CORS 来源、可信代理、读写超时以及认证管理器逐一注入后调用Initialize()启动监听。随后日志会输出started with listener on <address> (TCP/HTTP)或(TCP/HTTPS),见 internal/metrics/metrics.go。
二、抓取指标:一条 curl 命令即可验证
启用服务后,即可通过 Prometheus 或直接发送 HTTP 请求抓取指标:
curl http://localhost:9998/metrics返回体是标准的 Prometheus 文本格式,形如:
# Paths paths{name="[path_name]",state="[state]"} 1 paths_readers{name="[path_name]",state="[state]",readerType="[readerType]"} 5 paths_inbound_bytes{name="[path_name]",state="[state]"} 1234 paths_outbound_bytes{name="[path_name]",state="[state]"} 1234 paths_inbound_frames_in_error{name="[path_name]",state="[state]"} 1234 # HLS sessions hls_sessions{id="[id]",path="[path]"} 1 hls_sessions_outbound_bytes{id="[id]",path="[path]"} 187 # HLS muxers hls_muxers{name="[name]"} 1 hls_muxers_outbound_bytes{name="[name]"} 187 hls_muxers_outbound_frames_discarded{name="[name]"} 12 # RTSP connections rtsp_conns{id="[id]"} 1 rtsp_conns_inbound_bytes{id="[id]"} 1234 rtsp_conns_outbound_bytes{id="[id]"} 187 # RTSP sessions rtsp_sessions{id="[id]",path="[path]",state="[state]"} 1 rtsp_sessions_inbound_bytes{id="[id]",path="[path]",state="[state]"} 1234 rtsp_sessions_inbound_rtp_packets{id="[id]",path="[path]",state="[state]"} 123 rtsp_sessions_inbound_rtp_packets_lost{id="[id]",path="[path]",state="[state]"} 123 rtsp_sessions_inbound_rtp_packets_in_error{id="[id]",path="[path]",state="[state]"} 123 rtsp_sessions_inbound_rtp_packets_jitter{id="[id]",path="[path]",state="[state]"} 123 rtsp_sessions_inbound_rtcp_packets{id="[id]",path="[path]",state="[state]"} 123 rtsp_sessions_inbound_rtcp_packets_in_error{id="[id]",path="[path]",state="[state]"} 123 rtsp_sessions_outbound_bytes{id="[id]",path="[path]",state="[state]"} 187 rtsp_sessions_outbound_rtp_packets{id="[id]",path="[path]",state="[state]"} 123 rtsp_sessions_outbound_rtp_packets_reported_lost{id="[id]",path="[path]",state="[state]"} 123 rtsp_sessions_outbound_rtp_packets_discarded{id="[id]",path="[path]",state="[state]"} 123 rtsp_sessions_outbound_rtcp_packets{id="[id]",path="[path]",state="[state]"} 123 # RTSPS connections rtsps_conns{id="[id]"} 1 rtsps_conns_inbound_bytes{id="[id]"} 1234 rtsps_conns_outbound_bytes{id="[id]"} 187 # RTSPS sessions rtsps_sessions{id="[id]",path="[path]",state="[state]"} 1 rtsps_sessions_inbound_bytes{id="[id]",path="[path]",state="[state]"} 1234 rtsps_sessions_inbound_rtp_packets{id="[id]",path="[path]",state="[state]"} 123 rtsps_sessions_inbound_rtp_packets_lost{id="[id]",path="[path]",state="[state]"} 123 rtsps_sessions_inbound_rtp_packets_in_error{id="[id]",path="[path]",state="[state]"} 123 rtsps_sessions_inbound_rtp_packets_jitter{id="[id]",path="[path]",state="[state]"} 123 rtsps_sessions_inbound_rtcp_packets{id="[id]",path="[path]",state="[state]"} 123 rtsps_sessions_inbound_rtcp_packets_in_error{id="[id]",path="[path]",state="[state]"} 123 rtsps_sessions_outbound_bytes{id="[id]",path="[path]",state="[state]"} 187 rtsps_sessions_outbound_rtp_packets{id="[id]",path="[path]",state="[state]"} 123 rtsps_sessions_outbound_rtp_packets_reported_lost{id="[id]",path="[path]",state="[state]"} 123 rtsps_sessions_outbound_rtp_packets_discarded{id="[id]",path="[path]",state="[state]"} 123 rtsps_sessions_outbound_rtcp_packets{id="[id]",path="[path]",state="[state]"} 123 # RTMP connections rtmp_conns{id="[id]",path="[path]",state="[state]"} 1 rtmp_conns_inbound_bytes{id="[id]",path="[path]",state="[state]"} 1234 rtmp_conns_outbound_bytes{id="[id]",path="[path]",state="[state]"} 187 rtmp_conns_outbound_frames_discarded{id="[id]",path="[path]",state="[state]"} 12 # RTMPS connections rtmps_conns{id="[id]",path="[path]",state="[state]"} 1 rtmps_conns_inbound_bytes{id="[id]",path="[path]",state="[state]"} 1234 rtmps_conns_outbound_bytes{id="[id]",path="[path]",state="[state]"} 187 rtmps_conns_outbound_frames_discarded{id="[id]",path="[path]",state="[state]"} 12 # SRT connections srt_conns{id="[id]",path="[path]",state="[state]"} 1 srt_conns_packets_sent{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_received{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_sent_unique{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_received_unique{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_send_loss{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_received_loss{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_retrans{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_received_retrans{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_sent_ack{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_received_ack{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_sent_nak{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_received_nak{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_sent_km{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_received_km{id="[id]",path="[path]",state="[state]"} 123 srt_conns_us_snd_duration{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_received_belated{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_send_drop{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_received_drop{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_received_undecrypt{id="[id]",path="[path]",state="[state]"} 123 srt_conns_bytes_sent{id="[id]",path="[path]",state="[state]"} 187 srt_conns_bytes_received{id="[id]",path="[path]",state="[state]"} 1234 srt_conns_bytes_sent_unique{id="[id]",path="[path]",state="[state]"} 123 srt_conns_bytes_received_unique{id="[id]",path="[path]",state="[state]"} 123 srt_conns_bytes_received_loss{id="[id]",path="[path]",state="[state]"} 123 srt_conns_bytes_retrans{id="[id]",path="[path]",state="[state]"} 123 srt_conns_bytes_received_retrans{id="[id]",path="[path]",state="[state]"} 123 srt_conns_bytes_received_belated{id="[id]",path="[path]",state="[state]"} 123 srt_conns_bytes_send_drop{id="[id]",path="[path]",state="[state]"} 123 srt_conns_bytes_received_drop{id="[id]",path="[path]",state="[state]"} 123 srt_conns_bytes_received_undecrypt{id="[id]",path="[path]",state="[state]"} 123 srt_conns_us_packets_send_period{id="[id]",path="[path]",state="[state]"} 123.123 srt_conns_packets_flow_window{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_flight_size{id="[id]",path="[path]",state="[state]"} 123 srt_conns_ms_rtt{id="[id]",path="[path]",state="[state]"} 123.123 srt_conns_mbps_send_rate{id="[id]",path="[path]",state="[state]"} 123.123 srt_conns_mbps_receive_rate{id="[id]",path="[path]",state="[state]"} 123.123 srt_conns_mbps_link_capacity{id="[id]",path="[path]",state="[state]"} 123.123 srt_conns_bytes_avail_send_buf{id="[id]",path="[path]",state="[state]"} 123 srt_conns_bytes_avail_receive_buf{id="[id]",path="[path]",state="[state]"} 123 srt_conns_mbps_max_bw{id="[id]",path="[path]",state="[state]"} -123 srt_conns_bytes_mss{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_send_buf{id="[id]",path="[path]",state="[state]"} 123 srt_conns_bytes_send_buf{id="[id]",path="[path]",state="[state]"} 123 srt_conns_ms_send_buf{id="[id]",path="[path]",state="[state]"} 123 srt_conns_ms_send_tsb_pd_delay{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_receive_buf{id="[id]",path="[path]",state="[state]"} 123 srt_conns_bytes_receive_buf{id="[id]",path="[path]",state="[state]"} 123 srt_conns_ms_receive_buf{id="[id]",path="[path]",state="[state]"} 123 srt_conns_ms_receive_tsb_pd_delay{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_reorder_tolerance{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_received_avg_belated_time{id="[id]",path="[path]",state="[state]"} 123 srt_conns_packets_send_loss_rate{id="[id]",path="[path]",state="[state]"} 123.123 srt_conns_packets_received_loss_rate{id="[id]",path="[path]",state="[state]"} 123.123 srt_conns_outbound_frames_discarded{id="[id]",path="[path]",state="[state]"} 12 # WebRTC sessions webrtc_sessions{id="[id]",path="[path]",state="[state]"} 1 webrtc_sessions_inbound_bytes{id="[id]",path="[path]",state="[state]"} 1234 webrtc_sessions_inbound_rtp_packets{id="[id]",path="[path]",state="[state]"} 123 webrtc_sessions_inbound_rtp_packets_lost{id="[id]",path="[path]",state="[state]"} 123 webrtc_sessions_inbound_rtp_packets_jitter{id="[id]",path="[path]",state="[state]"} 123 webrtc_sessions_inbound_rtcp_packets{id="[id]",path="[path]",state="[state]"} 123 webrtc_sessions_outbound_bytes{id="[id]",path="[path]",state="[state]"} 187 webrtc_sessions_outbound_rtp_packets{id="[id]",path="[path]",state="[state]"} 123 webrtc_sessions_outbound_rtcp_packets{id="[id]",path="[path]",state="[state]"} 123 webrtc_sessions_outbound_frames_discarded{id="[id]",path="[path]",state="[state]"} 12 # MoQ sessions moq_sessions{id="[id]",path="[path]",state="[state]"} 1 moq_sessions_inbound_bytes{id="[id]",path="[path]",state="[state]"} 1234 moq_sessions_outbound_bytes{id="[id]",path="[path]",state="[state]"} 187 # Forward destinations forward_dests{pos="[pos]",id="[id]",path="[path]",type="[type]",state="[state]"} 1 forward_dests_outbound_bytes{pos="[pos]",id="[id]",path="[path]",type="[type]",state="[state]"} 1234指标序列化的实现细节
上述输出并非预先写死的模板,而是每次请求时由 internal/metrics/metrics.go 中的onMetrics处理器动态收集各服务组件的数据后逐行拼装而成:
- 指标名与标签统一通过
metric()/metricFloat()两个辅助函数输出,前者输出 64 位整数,后者输出浮点数(见 internal/metrics/metrics.go); - 标签(label)会被按键名排序后输出(
tags()内部使用sortedKeys),因此同一指标的标签顺序是稳定、确定的,便于程序解析; - 每个指标分组之间以
# 分组名注释行分隔,Prometheus 抓取器会忽略这些注释; - 当对应组件没有数据时,服务仍会输出键名为 0 的兜底指标(见测试
TestZeroMetricsFallback),保证监控面板上不存在"指标消失"导致的空洞。
三、各组指标逐个拆解:它们度量了什么
1. Paths(路径级汇总)
paths组是整个服务的"总览视图",按路径名(name)与状态(state,取值为ready或notReady)聚合:
paths:值为固定 1,用来指示该路径当前存在;paths_readers:当前正在从该路径拉流的读者数量,并按readerType(如rtspSession、rtmpConn等)细分;paths_inbound_bytes/paths_outbound_bytes:该路径累计接收 / 发送的字节数,是计算码率的核心数据源;paths_inbound_frames_in_error:推流端送入但解析失败的帧数,可用于快速发现源端编码问题。
其中state的取值逻辑在 internal/metrics/metrics.go:路径Ready为真时为ready,否则为notReady。
2. HLS:会话与 Muxer
hls_sessions{id,path}:每个 HLS 拉流会话计数值为 1,hls_sessions_outbound_bytes为该会话累计下发的字节数;hls_muxers{name}:每个 HLS muxer(按路径名标识)计数值为 1,配合hls_muxers_outbound_bytes(下发字节)与hls_muxers_outbound_frames_discarded(被丢弃的帧数)观察 HLS 转封装环节的健康度。帧被丢弃通常意味着 HLS 分段窗口过短或客户端消费不及时。
3. RTSP / RTSPS:连接与会话
连接(connection)层按id记录控制连接的累计收发字节:rtsp_conns_inbound_bytes/rtsp_conns_outbound_bytes(RTSPS 同理,前缀为rtsps_)。
会话(session)层按{id, path, state}三标签细分,字段最为丰富,几乎覆盖 RTP/RTCP 的全部关键计数:
- 字节:
*_sessions_inbound_bytes/*_sessions_outbound_bytes; - 入向 RTP:
inbound_rtp_packets(总包数)、inbound_rtp_packets_lost(丢失)、inbound_rtp_packets_in_error(出错)、inbound_rtp_packets_jitter(抖动); - 入向 RTCP:
inbound_rtcp_packets/inbound_rtcp_packets_in_error; - 出向 RTP:
outbound_rtp_packets、outbound_rtp_packets_reported_lost(对端通过 RTCP 反馈的丢失数)、outbound_rtp_packets_discarded(本地主动丢弃); - 出向 RTCP:
outbound_rtcp_packets。
这组指标对排查"画面卡顿但网络没断"之类的问题很有价值:将inbound_rtp_packets_lost与outbound_rtp_packets_reported_lost对照,就能区分丢包发生在推流链路还是拉流链路。
4. RTMP / RTMPS:连接级
RTMP 与 RTMPS 以连接为粒度输出rtmp_conns(值为 1)、rtmp_conns_inbound_bytes、rtmp_conns_outbound_bytes以及rtmp_conns_outbound_frames_discarded(出向被丢弃的帧数),标签为{id, path, state}。帧被丢弃往往与 RTMP 播放器带宽不足或流中关键帧间隔有关。
5. SRT:最丰富的链路质量指标体系
SRT 连接(srt_conns{id,path,state})暴露了一整套源自 SRT 协议栈自身的统计量,是判断公网链路质量的关键:
- 丢包与重传:
packets_send_loss/packets_received_loss(丢包数)、packets_retrans/packets_received_retrans(重传数)、packets_send_loss_rate/packets_received_loss_rate(丢包率,浮点); - 延迟与拥塞:
ms_rtt(往返时延)、us_packets_send_period(发包间隔)、packets_flow_window(流控窗口)、packets_flight_size(在途包数); - 带宽:
mbps_send_rate/mbps_receive_rate(收发速率)、mbps_link_capacity(链路容量)、mbps_max_bw(最大带宽,无限制时为负值); - 缓冲:
bytes_avail_send_buf/bytes_avail_receive_buf、packets_send_buf/bytes_send_buf/ms_send_buf、packets_receive_buf/bytes_receive_buf/ms_receive_buf,以及 TSBPD 延迟ms_send_tsb_pd_delay/ms_receive_tsb_pd_delay; - 其他:
packets_sent_ack/packets_received_nak(ACK/NAK 计数)、packets_sent_km(密钥消息)、packets_received_belated(迟到包)、packets_send_drop/packets_received_drop(丢弃)、packets_received_undecrypt(无法解密)、bytes_mss(最大分段大小)、packets_reorder_tolerance(乱序容限)与outbound_frames_discarded。
对使用 SRT 做公网远距离传输(例如从野外摄像机回传)的场景,ms_rtt、packets_received_loss与packets_received_belated三个指标基本就能刻画一条链路的实时健康状况。
6. WebRTC:会话级 RTP/RTCP
webrtc_sessions{id,path,state}覆盖入向/出向字节、RTP 包数、丢包、抖动(inbound_rtp_packets_jitter)与 RTCP 包数,另有webrtc_sessions_outbound_frames_discarded反映因拥塞或播放端处理不及时而丢弃的帧数。
7. MoQ:会话级收发字节
moq_sessions{id,path,state}仅暴露moq_sessions_inbound_bytes与moq_sessions_outbound_bytes两个字节计数,用于观察基于 Media-over-QUIC 的会话流量。
8. Forward destinations(转发目的地)
forward_dests{pos,id,path,type,state}按转发目的地维度输出,forward_dests_outbound_bytes统计转发出去的字节数。type标签用于标识转发协议类型(RTSP、RTMP、SRT、WebRTC、MoQ 等)。需要留意的是,源码注释明确说明该指标的protocol标签已废弃,由type取代(见 internal/metrics/metrics.go)。
关于"废弃指标"
为保持向下兼容,输出中还存在一批以(deprecated)注释标出的旧指标,例如paths_bytes_received/paths_bytes_sent、rtsp_conns_bytes_received/rtsp_conns_bytes_sent、hls_muxers_bytes_sent等,以及大量会话上的remoteAddr标签。新接入监控时应优先使用上面表格中列出的新指标与标签,避免未来版本移除废弃项后监控面板失效。
四、为什么没有直接的码率指标
设计上,MediaMTX不直接提供码率(bitrate)指标。原因是码率本质上是一个"随时间变化的速度",而指标端点返回的是累计字节数。任何指标分析器(例如 Grafana 搭配 Prometheus)都可以通过对累计字节做时间微分轻松得到码率:
# 某路径的出站码率(bytes per second) rate(paths_outbound_bytes{name="mypath"}[5m]) * 8这样既避免了在服务端维护额外状态,也让消费端可以按自己的时间窗口灵活计算瞬时码率或平均码率。
五、精确筛选:用查询参数只看关心的一部分
默认情况下/metrics会返回全部指标。当服务上有大量路径和连接时,可以通过 HTTP 查询参数按类型、路径或具体对象 ID 过滤:
type=[TYPE]:只显示某一种类型的指标。TYPE可取paths、forward_dests、hls_sessions、hls_muxers、rtsp_conns、rtsp_sessions、rtsps_conns、rtsps_sessions、rtmp_conns、rtmps_conns、srt_conns、webrtc_sessions、moq_sessions;path=[PATH]:只显示属于某个具体路径的指标;hls_muxer=[PATH]:只显示某个具体 HLS muxer 的指标;hls_session=[ID]:只显示某个具体 HLS 会话的指标;rtsp_conn=[ID]:只显示某个具体 RTSP 连接的指标;rtsp_session=[SESSION]:只显示某个具体 RTSP 会话的指标;rtsps_conn=[ID]:只显示某个具体 RTSPS 连接的指标;rtsps_session=[SESSION]:只显示某个具体 RTSPS 会话的指标;rtmp_conn=[ID]:只显示某个具体 RTMP 连接的指标;rtmps_conn=[ID]:只显示某个具体 RTMPS 连接的指标;srt_conn=[ID]:只显示某个具体 SRT 连接的指标;webrtc_session=[ID]:只显示某个具体 WebRTC 会话的指标;forward_dest=[ID]:只显示某个具体转发目的地的指标;moq_session=[ID]:只显示某个具体 MoQ 会话的指标。
查询参数既支持单独使用也支持组合。例如只查看路径camera1的汇总与转发指标:
curl "http://localhost:9998/metrics?path=camera1"或只看 SRT 连接类型:
curl "http://localhost:9998/metrics?type=srt_conns"这些过滤条件在 internal/metrics/metrics.go 中被逐个解析为过滤器变量,并作为各组指标是否输出的判定条件;type的取值集合与 13 种指标类型常量一一对应(见 internal/metrics/metrics.go)。
六、与 Prometheus + Grafana 集成
MediaMTX 的指标端点不需要任何专属 exporter,直接把它声明为一个 Prometheus 抓取目标即可。假设 MediaMTX 与 Prometheus 同机部署:
scrape_configs: - job_name: mediamtx metrics_path: /metrics static_configs: - targets: ["localhost:9998"]随后即可在 Prometheus 中查询paths、rtsp_sessions_inbound_rtp_packets_lost等指标,并在 Grafana 中按标签分组绘制面板。几个常用的监控表达式:
# 实时在线路径数 count(paths{state="ready"} == 1) # 各路径出站码率 sum by (name) (rate(paths_outbound_bytes[5m]) * 8) # RTSP 会话入向 RTP 丢包率 sum by (path) (increase(rtsp_sessions_inbound_rtp_packets_lost[5m])) / sum by (path) (increase(rtsp_sessions_inbound_rtp_packets[5m])) # SRT 连接往返时延 srt_conns_ms_rtt七、访问控制与 CORS
指标端点并非完全公开。服务在启动时会挂载认证中间件(见 internal/metrics/metrics.go):每个请求都会以metrics动作走统一认证流程,支持内部用户、HTTP 外部认证、JWT 等多种认证方式(相关配置见 mediamtx.yml 的Internal authentication一节,可用动作包括publish、read、playback、api、metrics、pprof)。默认配置下,127.0.0.1与::1的本机用户拥有metrics权限,因此本机curl无需额外传凭据即可访问;跨主机访问时则需要配置相应用户或认证,请求会触发 HTTP Basic 认证(响应头为WWW-Authenticate: Basic realm="mediamtx")。
此外,服务支持 CORS 预检(OPTIONS)请求,允许通过metricsAllowOrigins配置跨域来源,方便前端工具或跨域部署的 Prometheus 直接抓取。
八、实现与测试佐证
- 指标端点的完整实现位于 internal/metrics/metrics.go,
Metrics结构体在 internal/core/core.go 中被装配,并通过SetPathManager、SetHLSServer、SetRTSPServer、SetSRTServer、SetWebRTCServer、SetMoQServer等 setter 注入各服务组件的 API 句柄(见 internal/metrics/metrics.go),指标数据全部来自这些组件实时提供的列表接口; - internal/metrics/metrics_test.go 中的
TestMetrics使用带完整数据的桩服务对输出文本做了逐字节断言,可当作一份"指标输出规范"阅读;TestZeroMetricsFallback验证空数据时的兜底输出;TestPreflightRequest验证 CORS 预检行为; - 各指标对应的数据结构定义可进一步查阅 internal/defs 目录下的
api_path.go、api_hls.go、api_rtsp.go、api_srt.go、api_rtmp.go、api_webrtc.go、api_moq.go、api_forward_dest.go等文件。
九、小结
MediaMTX 的 metrics 服务用一条metrics: yes配置即可开启,默认监听:9998,以标准 Prometheus 文本格式输出路径、HLS、RTSP/RTSPS、RTMP/RTMPS、SRT、WebRTC、MoQ 与转发目的地八类指标。理解这些指标的分组与标签语义,配合type、path、*_conn、*_session等查询参数按需过滤,再交给 Prometheus 与 Grafana 完成码率、丢包率、时延等衍生计算,就可以构建出一套从"源端推流质量"到"各协议分发链路"全覆盖的实时媒体监控体系。
【免费下载链接】mediamtxReady-to-use Media-over-QUIC / SRT / WebRTC / RTSP / RTMP / LL-HLS / MPEG-TS / RTP live media server and media proxy that allows to read, publish, proxy, record and playback real-time video and audio streams.项目地址: https://gitcode.com/GitHub_Trending/me/mediamtx
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考