From ab4620870ddec9eec47918723b90aeaf3c7cdc04 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 21 Aug 2015 15:51:20 +0800 Subject: [PATCH] refine the stat api, support query specified stream. --- trunk/src/app/srs_app_http_api.cpp | 80 +++++++------- trunk/src/app/srs_app_statistic.cpp | 157 ++++++++++++++++------------ trunk/src/app/srs_app_statistic.hpp | 6 ++ 3 files changed, 144 insertions(+), 99 deletions(-) diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index c80de04d24..e05a286765 100755 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -470,40 +470,37 @@ int SrsGoApiStreams::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) int ret = ERROR_SUCCESS; SrsStatistic* stat = SrsStatistic::instance(); std::stringstream ss; - - if (r->is_http_delete()) { - // path: {pattern}{stream_id} - // e.g. /api/v1/streams/100 pattern= /api/v1/streams/, stream_id=100 - string sid = r->path().substr((int)entry->pattern.length()); - if (sid.empty()) { - ret = ERROR_REQUEST_DATA; - srs_error("invalid param, stream_id=%s. ret=%d", sid.c_str(), ret); - - ss << SRS_JOBJECT_START - << SRS_JFIELD_ERROR(ret) - << SRS_JOBJECT_END; - - return srs_http_response_json(w, ss.str()); - } - - int stream_id = ::atoi(sid.c_str()); - SrsStatisticStream* stream = stat->find_stream(stream_id); - if (stream == NULL) { - ret = ERROR_RTMP_STREAM_NOT_FOUND; - srs_error("stream stream_id=%s not found. ret=%d", sid.c_str(), ret); - - ss << SRS_JOBJECT_START - << SRS_JFIELD_ERROR(ret) - << SRS_JOBJECT_END; - - return srs_http_response_json(w, ss.str()); + + // path: {pattern}{stream_id} + // e.g. /api/v1/streams/100 pattern= /api/v1/streams/, stream_id=100 + int sid = -1; + if (true) { + string stream_id = r->path().substr((int)entry->pattern.length()); + if (!stream_id.empty()) { + sid = ::atoi(stream_id.c_str()); } + } + + SrsStatisticStream* stream = NULL; + if (sid >= 0 && (stream = stat->find_stream(sid)) == NULL) { + ret = ERROR_RTMP_STREAM_NOT_FOUND; + srs_error("stream stream_id=%d not found. ret=%d", sid, ret); + + ss << SRS_JOBJECT_START + << SRS_JFIELD_ERROR(ret) + << SRS_JOBJECT_END; + + return srs_http_response_json(w, ss.str()); + } + if (r->is_http_delete()) { + srs_assert(stream); + SrsSource* source = SrsSource::fetch(stream->vhost->vhost, stream->app, stream->stream); if (source) { source->set_expired(); srs_warn("disconnent stream=%d successfully. vhost=%s, app=%s, stream=%s.", - stream_id, stream->vhost->vhost.c_str(), stream->app.c_str(), stream->stream.c_str()); + sid, stream->vhost->vhost.c_str(), stream->app.c_str(), stream->stream.c_str()); } else { ret = ERROR_SOURCE_NOT_FOUND; } @@ -513,18 +510,31 @@ int SrsGoApiStreams::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) << SRS_JOBJECT_END; return srs_http_response_json(w, ss.str()); - } else { + } else if (r->is_http_get()) { std::stringstream data; - int ret = stat->dumps_streams(data); - ss << SRS_JOBJECT_START - << SRS_JFIELD_ERROR(ret) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("server", stat->server_id()) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("streams", data.str()) - << SRS_JOBJECT_END; + if (!stream) { + ret = stat->dumps_streams(data); + + ss << SRS_JOBJECT_START + << SRS_JFIELD_ERROR(ret) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("server", stat->server_id()) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("streams", data.str()) + << SRS_JOBJECT_END; + } else { + ret = stream->dumps(data); + + ss << SRS_JOBJECT_START + << SRS_JFIELD_ERROR(ret) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("server", stat->server_id()) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("stream", data.str()) + << SRS_JOBJECT_END; + } return srs_http_response_json(w, ss.str()); } + + return ret; } SrsGoApiError::SrsGoApiError() diff --git a/trunk/src/app/srs_app_statistic.cpp b/trunk/src/app/srs_app_statistic.cpp index ff971e8d7a..6666be305b 100755 --- a/trunk/src/app/srs_app_statistic.cpp +++ b/trunk/src/app/srs_app_statistic.cpp @@ -47,6 +47,8 @@ SrsStatisticVhost::SrsStatisticVhost() kbps = new SrsKbps(); kbps->set_io(NULL, NULL); + + nb_clients = 0; } SrsStatisticVhost::~SrsStatisticVhost() @@ -54,6 +56,31 @@ SrsStatisticVhost::~SrsStatisticVhost() srs_freep(kbps); } +int SrsStatisticVhost::dumps(stringstream& ss) +{ + int ret = ERROR_SUCCESS; + + // dumps the config of vhost. + bool hls_enabled = _srs_config->get_hls_enabled(vhost); + + ss << SRS_JOBJECT_START + << SRS_JFIELD_ORG("id", id) << SRS_JFIELD_CONT + << SRS_JFIELD_STR("name", vhost) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("cleints", nb_clients) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("send_bytes", kbps->get_send_bytes()) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("recv_bytes", kbps->get_recv_bytes()) << SRS_JFIELD_CONT + << SRS_JFIELD_NAME("hls") << SRS_JOBJECT_START + << SRS_JFIELD_BOOL("enabled", hls_enabled); + if (hls_enabled) { + ss << SRS_JFIELD_CONT; + ss << SRS_JFIELD_ORG("fragment", _srs_config->get_hls_fragment(vhost)); + } + ss << SRS_JOBJECT_END + << SRS_JOBJECT_END; + + return ret; +} + SrsStatisticStream::SrsStatisticStream() { id = srs_generate_id(); @@ -73,6 +100,8 @@ SrsStatisticStream::SrsStatisticStream() kbps = new SrsKbps(); kbps->set_io(NULL, NULL); + + nb_clients = 0; } SrsStatisticStream::~SrsStatisticStream() @@ -80,6 +109,48 @@ SrsStatisticStream::~SrsStatisticStream() srs_freep(kbps); } +int SrsStatisticStream::dumps(stringstream& ss) +{ + int ret = ERROR_SUCCESS; + + ss << SRS_JOBJECT_START + << SRS_JFIELD_ORG("id", id) << SRS_JFIELD_CONT + << SRS_JFIELD_STR("name", stream) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("vhost", vhost->id) << SRS_JFIELD_CONT + << SRS_JFIELD_STR("app", app) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("clients", nb_clients) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("send_bytes", kbps->get_send_bytes()) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("recv_bytes", kbps->get_recv_bytes()) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("live_ms", srs_get_system_time_ms()) << SRS_JFIELD_CONT + << SRS_JFIELD_STR("status", status) << SRS_JFIELD_CONT; + + if (!has_video) { + ss << SRS_JFIELD_NULL("video") << SRS_JFIELD_CONT; + } else { + ss << SRS_JFIELD_NAME("video") << SRS_JOBJECT_START + << SRS_JFIELD_STR("codec", srs_codec_video2str(vcodec)) << SRS_JFIELD_CONT + << SRS_JFIELD_STR("profile", srs_codec_avc_profile2str(avc_profile)) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("level", srs_codec_avc_level2str(avc_level)) + << SRS_JOBJECT_END + << SRS_JFIELD_CONT; + } + + if (!has_audio) { + ss << SRS_JFIELD_NULL("audio"); + } else { + ss << SRS_JFIELD_NAME("audio") << SRS_JOBJECT_START + << SRS_JFIELD_STR("codec", srs_codec_audio2str(acodec)) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("sample_rate", (int)flv_sample_rates[asample_rate]) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("channel", (int)asound_type + 1) << SRS_JFIELD_CONT + << SRS_JFIELD_STR("profile", srs_codec_aac_object2str(aac_object)) + << SRS_JOBJECT_END; + } + + ss << SRS_JOBJECT_END; + + return ret; +} + void SrsStatisticStream::publish() { status = STATISTIC_STREAM_STATUS_PUBLISHING; @@ -215,6 +286,10 @@ int SrsStatistic::on_client(int id, SrsRequest* req) } else { client = clients[id]; } + + // got client. + stream->nb_clients++; + vhost->nb_clients++; return ret; } @@ -222,12 +297,19 @@ int SrsStatistic::on_client(int id, SrsRequest* req) void SrsStatistic::on_disconnect(int id) { std::map::iterator it; - it = clients.find(id); - if (it != clients.end()) { - SrsStatisticClient* client = it->second; - srs_freep(client); - clients.erase(it); + if ((it = clients.find(id)) == clients.end()) { + return; } + + SrsStatisticClient* client = it->second; + SrsStatisticStream* stream = client->stream; + SrsStatisticVhost* vhost = stream->vhost; + + srs_freep(client); + clients.erase(it); + + stream->nb_clients--; + vhost->nb_clients--; } void SrsStatistic::kbps_add_delta(SrsConnection* conn) @@ -286,26 +368,14 @@ int SrsStatistic::dumps_vhosts(stringstream& ss) std::map::iterator it; for (it = vhosts.begin(); it != vhosts.end(); it++) { SrsStatisticVhost* vhost = it->second; + if (it != vhosts.begin()) { ss << SRS_JFIELD_CONT; } - // dumps the config of vhost. - bool hls_enabled = _srs_config->get_hls_enabled(vhost->vhost); - - ss << SRS_JOBJECT_START - << SRS_JFIELD_ORG("id", vhost->id) << SRS_JFIELD_CONT - << SRS_JFIELD_STR("name", vhost->vhost) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("send_bytes", vhost->kbps->get_send_bytes()) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("recv_bytes", vhost->kbps->get_recv_bytes()) << SRS_JFIELD_CONT - << SRS_JFIELD_NAME("hls") << SRS_JOBJECT_START - << SRS_JFIELD_BOOL("enabled", hls_enabled); - if (hls_enabled) { - ss << SRS_JFIELD_CONT; - ss << SRS_JFIELD_ORG("fragment", _srs_config->get_hls_fragment(vhost->vhost)); + if ((ret = vhost->dumps(ss)) != ERROR_SUCCESS) { + return ret; } - ss << SRS_JOBJECT_END - << SRS_JOBJECT_END; } ss << SRS_JARRAY_END; @@ -320,55 +390,14 @@ int SrsStatistic::dumps_streams(stringstream& ss) std::map::iterator it; for (it = streams.begin(); it != streams.end(); it++) { SrsStatisticStream* stream = it->second; + if (it != streams.begin()) { ss << SRS_JFIELD_CONT; } - int client_num = 0; - std::map::iterator it_client; - for (it_client = clients.begin(); it_client != clients.end(); it_client++) { - SrsStatisticClient* client = it_client->second; - if (client->stream == stream) { - client_num++; - } + if ((ret = stream->dumps(ss)) != ERROR_SUCCESS) { + return ret; } - - ss << SRS_JOBJECT_START - << SRS_JFIELD_ORG("id", stream->id) << SRS_JFIELD_CONT - << SRS_JFIELD_STR("name", stream->stream) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("vhost", stream->vhost->id) << SRS_JFIELD_CONT - << SRS_JFIELD_STR("app", stream->app) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("clients", client_num) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("send_bytes", stream->kbps->get_send_bytes()) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("recv_bytes", stream->kbps->get_recv_bytes()) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("live_ms", srs_get_system_time_ms()) << SRS_JFIELD_CONT - << SRS_JFIELD_STR("status", stream->status) << SRS_JFIELD_CONT; - - if (!stream->has_video) { - ss << SRS_JFIELD_NULL("video") << SRS_JFIELD_CONT; - } else { - ss << SRS_JFIELD_NAME("video") - << SRS_JOBJECT_START - << SRS_JFIELD_STR("codec", srs_codec_video2str(stream->vcodec)) << SRS_JFIELD_CONT - << SRS_JFIELD_STR("profile", srs_codec_avc_profile2str(stream->avc_profile)) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("level", srs_codec_avc_level2str(stream->avc_level)) - << SRS_JOBJECT_END - << SRS_JFIELD_CONT; - } - - if (!stream->has_audio) { - ss << SRS_JFIELD_NULL("audio"); - } else { - ss << SRS_JFIELD_NAME("audio") - << SRS_JOBJECT_START - << SRS_JFIELD_STR("codec", srs_codec_audio2str(stream->acodec)) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("sample_rate", (int)flv_sample_rates[stream->asample_rate]) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("channel", (int)stream->asound_type + 1) << SRS_JFIELD_CONT - << SRS_JFIELD_STR("profile", srs_codec_aac_object2str(stream->aac_object)) - << SRS_JOBJECT_END; - } - - ss << SRS_JOBJECT_END; } ss << SRS_JARRAY_END; diff --git a/trunk/src/app/srs_app_statistic.hpp b/trunk/src/app/srs_app_statistic.hpp index fb56d04f82..bb1ed29ae5 100755 --- a/trunk/src/app/srs_app_statistic.hpp +++ b/trunk/src/app/srs_app_statistic.hpp @@ -47,6 +47,7 @@ struct SrsStatisticVhost public: int64_t id; std::string vhost; + int nb_clients; public: /** * vhost total kbps. @@ -55,6 +56,8 @@ struct SrsStatisticVhost public: SrsStatisticVhost(); virtual ~SrsStatisticVhost(); +public: + virtual int dumps(std::stringstream& ss); }; struct SrsStatisticStream @@ -66,6 +69,7 @@ struct SrsStatisticStream std::string stream; std::string url; std::string status; + int nb_clients; public: /** * stream total kbps. @@ -93,6 +97,8 @@ struct SrsStatisticStream public: SrsStatisticStream(); virtual ~SrsStatisticStream(); +public: + virtual int dumps(std::stringstream& ss); public: /** * publish the stream.