From 95255110320e2411955a2567e64bfc78d3f82a36 Mon Sep 17 00:00:00 2001 From: chundonglinlin Date: Sat, 1 Oct 2022 07:35:54 +0800 Subject: [PATCH] Exporter: Listen at port 9972 for Prometheus exporter. (#3195) --- trunk/conf/full.conf | 5 ++++ trunk/conf/prometheus.conf | 44 ++++++++++++++++++++++++++++++ trunk/src/app/srs_app_config.cpp | 30 +++++++++++++++++++- trunk/src/app/srs_app_config.hpp | 1 + trunk/src/app/srs_app_http_api.cpp | 6 +++- trunk/src/app/srs_app_server.cpp | 20 ++++++++++++-- trunk/src/app/srs_app_server.hpp | 3 ++ 7 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 trunk/conf/prometheus.conf diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 8fcb06c05..dfc589754 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -664,6 +664,11 @@ exporter { # Overwrite by env SRS_EXPORTER_ENABLED # Default: off enabled off; + # The http api listen port for exporter metrics. + # Overwrite by env SRS_EXPORTER_LISTEN + # Default: 9972 + # See https://github.com/prometheus/prometheus/wiki/Default-port-allocations + listen 9972; # The logging label to category the cluster servers. # Overwrite by env SRS_EXPORTER_LABEL label cn-beijing; diff --git a/trunk/conf/prometheus.conf b/trunk/conf/prometheus.conf new file mode 100644 index 000000000..50d944754 --- /dev/null +++ b/trunk/conf/prometheus.conf @@ -0,0 +1,44 @@ +# no-daemon and write log to console config for srs. +# @see full.conf for detail config. + +listen 1935; +max_connections 1000; +daemon off; +srs_log_tank console; +http_api { + enabled on; + listen 1985; +} +http_server { + enabled on; + listen 8080; +} +rtc_server { + enabled on; + listen 8000; # UDP port + # @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#config-candidate + candidate $CANDIDATE; +} +# Prometheus exporter config. +exporter { + enabled on; + listen 9972; + label cn-beijing; + tag cn-edge; +} +vhost __defaultVhost__ { + hls { + enabled on; + } + http_remux { + enabled on; + mount [vhost]/[app]/[stream].flv; + } + rtc { + enabled on; + # @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#rtmp-to-rtc + rtmp_to_rtc on; + # @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#rtc-to-rtmp + rtc_to_rtmp on; + } +} diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index e5af11207..da138f7b1 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -2305,7 +2305,16 @@ srs_error_t SrsConfig::check_normal_config() } } } - + if (true) { + SrsConfDirective* conf = root->get("exporter"); + for (int i = 0; conf && i < (int)conf->directives.size(); i++) { + string n = conf->at(i)->name; + if (n != "enabled" && n != "listen" && n != "label" && n != "tag") { + return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal exporter.%s", n.c_str()); + } + } + } + //////////////////////////////////////////////////////////////////////// // check listen for rtmp. //////////////////////////////////////////////////////////////////////// @@ -3583,6 +3592,25 @@ bool SrsConfig::get_exporter_enabled() return SRS_CONF_PERFER_FALSE(conf->arg0()); } +string SrsConfig::get_exporter_listen() +{ + SRS_OVERWRITE_BY_ENV_STRING("SRS_EXPORTER_LISTEN"); + + static string DEFAULT = "9972"; + + SrsConfDirective* conf = root->get("exporter"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("listen"); + if (!conf) { + return DEFAULT; + } + + return conf->arg0(); +} + string SrsConfig::get_exporter_label() { SRS_OVERWRITE_BY_ENV_STRING("SRS_EXPORTER_LABEL"); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 24019ad19..bff6e1759 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -1089,6 +1089,7 @@ public: public: // Get Prometheus exporter config. virtual bool get_exporter_enabled(); + virtual std::string get_exporter_listen(); virtual std::string get_exporter_label(); virtual std::string get_exporter_tag(); }; diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index 4b00e4e17..390acbde4 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -87,7 +87,9 @@ srs_error_t srs_api_response_json(ISrsHttpResponseWriter* w, string data) SrsHttpHeader* h = w->header(); h->set_content_length(data.length()); - h->set_content_type("application/json"); + if (h->content_type().empty()) { + h->set_content_type("application/json"); + } if ((err = w->write((char*)data.data(), (int)data.length())) != srs_success) { return srs_error_wrap(err, "write json"); @@ -1153,5 +1155,7 @@ srs_error_t SrsGoApiMetrics::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessa << nerrs << "\n"; + w->header()->set_content_type("text/plain; charset=utf-8"); + return srs_api_response(w, r, ss.str()); } diff --git a/trunk/src/app/srs_app_server.cpp b/trunk/src/app/srs_app_server.cpp index 0afb938bc..8ae334a84 100644 --- a/trunk/src/app/srs_app_server.cpp +++ b/trunk/src/app/srs_app_server.cpp @@ -335,6 +335,7 @@ SrsServer::SrsServer() webrtc_listener_ = new SrsTcpListener(this); stream_caster_flv_listener_ = new SrsHttpFlvListener(); stream_caster_mpegts_ = new SrsUdpCasterListener(); + exporter_listener_ = new SrsTcpListener(this); // donot new object in constructor, // for some global instance is not ready now, @@ -390,6 +391,7 @@ void SrsServer::destroy() srs_freep(webrtc_listener_); srs_freep(stream_caster_flv_listener_); srs_freep(stream_caster_mpegts_); + srs_freep(exporter_listener_); } void SrsServer::dispose() @@ -405,6 +407,7 @@ void SrsServer::dispose() webrtc_listener_->close(); stream_caster_flv_listener_->close(); stream_caster_mpegts_->close(); + exporter_listener_->close(); // Fast stop to notify FFMPEG to quit, wait for a while then fast kill. ingester->dispose(); @@ -432,6 +435,7 @@ void SrsServer::gracefully_dispose() webrtc_listener_->close(); stream_caster_flv_listener_->close(); stream_caster_mpegts_->close(); + exporter_listener_->close(); srs_trace("listeners closed"); // Fast stop to notify FFMPEG to quit, wait for a while then fast kill. @@ -590,7 +594,7 @@ srs_error_t SrsServer::listen() } } - // Create HTTP server listener. + // Create HTTPS server listener. if (_srs_config->get_https_stream_enabled()) { https_listener_->set_endpoint(_srs_config->get_https_stream_listen())->set_label("HTTPS-Server"); if ((err = https_listener_->listen()) != srs_success) { @@ -637,7 +641,15 @@ srs_error_t SrsServer::listen() return srs_error_wrap(err, "listen"); } } - + + // Create exporter server listener. + if (_srs_config->get_exporter_enabled()) { + exporter_listener_->set_endpoint(_srs_config->get_exporter_listen())->set_label("Exporter-Server"); + if ((err = exporter_listener_->listen()) != srs_success) { + return srs_error_wrap(err, "exporter server listen"); + } + } + if ((err = conn_manager->start()) != srs_success) { return srs_error_wrap(err, "connection manager"); } @@ -1159,6 +1171,10 @@ srs_error_t SrsServer::do_on_tcp_client(ISrsListener* listener, srs_netfd_t& stf // TODO: FIXME: Should manage this connection by _srs_rtc_manager resource = new SrsRtcTcpConn(new SrsTcpConnection(stfd2), ip, port, this); #endif + } else if (listener == exporter_listener_) { + // TODO: FIXME: Maybe should support https metrics. + bool is_https = false; + resource = new SrsHttpxConn(is_https, this, new SrsTcpConnection(stfd2), http_api_mux, ip, port); } else { srs_close_stfd(stfd2); srs_warn("Close for invalid fd=%d, ip=%s:%d", fd, ip.c_str(), port); diff --git a/trunk/src/app/srs_app_server.hpp b/trunk/src/app/srs_app_server.hpp index 4718ceb2a..4bde69c1d 100644 --- a/trunk/src/app/srs_app_server.hpp +++ b/trunk/src/app/srs_app_server.hpp @@ -133,6 +133,9 @@ private: SrsHttpFlvListener* stream_caster_flv_listener_; // Stream Caster for push over MPEGTS-UDP SrsUdpCasterListener* stream_caster_mpegts_; + // Exporter server listener, over TCP. Please note that metrics request of HTTP is served by this + // listener, and it might be reused by HTTP API. + SrsTcpListener* exporter_listener_; private: // Signal manager which convert gignal to io message. SrsSignalManager* signal_manager;