diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index 19ce0d2dc..63562eb7a 100755 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -443,17 +443,45 @@ SrsGoApiVhosts::~SrsGoApiVhosts() int SrsGoApiVhosts::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) { - std::stringstream data; - SrsStatistic* stat = SrsStatistic::instance(); - int ret = stat->dumps_vhosts(data); + int ret = ERROR_SUCCESS; + SrsStatistic* stat = SrsStatistic::instance(); std::stringstream ss; - ss << SRS_JOBJECT_START - << SRS_JFIELD_ERROR(ret) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("server", stat->server_id()) << SRS_JFIELD_CONT - << SRS_JFIELD_ORG("vhosts", data.str()) - << SRS_JOBJECT_END; + // path: {pattern}{vhost_id} + // e.g. /api/v1/vhosts/100 pattern= /api/v1/vhosts/, vhost_id=100 + int vid = r->parse_rest_id(entry->pattern); + SrsStatisticVhost* vhost = NULL; + + if (vid > 0 && (vhost = stat->find_vhost(vid)) == NULL) { + ret = ERROR_RTMP_STREAM_NOT_FOUND; + srs_error("vhost id=%d not found. ret=%d", vid, ret); + return srs_http_response_code(w, ret); + } + + if (r->is_http_get()) { + std::stringstream data; + + if (!vhost) { + ret = stat->dumps_vhosts(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("vhosts", data.str()) + << SRS_JOBJECT_END; + } else { + ret = vhost->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("vhost", data.str()) + << SRS_JOBJECT_END; + } + + return srs_http_response_json(w, ss.str()); + } return srs_http_response_json(w, ss.str()); } @@ -553,8 +581,7 @@ int SrsGoApiClients::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) int cid = r->parse_rest_id(entry->pattern); SrsStatisticClient* client = NULL; - // TODO: FIXME: implements it. - /*if (cid >= 0 && (client = stat->find_client(cid)) == NULL) { + if (cid >= 0 && (client = stat->find_client(cid)) == NULL) { ret = ERROR_RTMP_STREAM_NOT_FOUND; srs_error("stream client_id=%d not found. ret=%d", cid, ret); @@ -562,12 +589,32 @@ int SrsGoApiClients::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) return srs_http_response_json(w, ss.str()); - }*/ - - if (r->is_http_get()) { - } + if (r->is_http_get()) { + std::stringstream data; + + if (!client) { + ret = stat->dumps_clients(data, 0, 10); + + ss << SRS_JOBJECT_START + << SRS_JFIELD_ERROR(ret) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("server", stat->server_id()) << SRS_JFIELD_CONT + << SRS_JFIELD_ORG("clients", data.str()) + << SRS_JOBJECT_END; + } else { + ret = client->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("client", data.str()) + << SRS_JOBJECT_END; + } + + return srs_http_response_json(w, ss.str()); + } + return ret; } diff --git a/trunk/src/app/srs_app_statistic.cpp b/trunk/src/app/srs_app_statistic.cpp index 1caee33f7..0453c46d3 100755 --- a/trunk/src/app/srs_app_statistic.cpp +++ b/trunk/src/app/srs_app_statistic.cpp @@ -62,11 +62,13 @@ int SrsStatisticVhost::dumps(stringstream& ss) // dumps the config of vhost. bool hls_enabled = _srs_config->get_hls_enabled(vhost); + bool enabled = _srs_config->get_vhost_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_BOOL("enabled", enabled) << 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_NAME("hls") << SRS_JOBJECT_START @@ -163,6 +165,26 @@ void SrsStatisticStream::close() status = STATISTIC_STREAM_STATUS_IDLING; } +SrsStatisticClient::SrsStatisticClient() +{ + id = 0; +} + +SrsStatisticClient::~SrsStatisticClient() +{ +} + +int SrsStatisticClient::dumps(stringstream& ss) +{ + int ret = ERROR_SUCCESS; + + ss << SRS_JOBJECT_START + << SRS_JFIELD_ORG("id", id) + << SRS_JOBJECT_END; + + return ret; +} + SrsStatistic* SrsStatistic::_instance = new SrsStatistic(); SrsStatistic::SrsStatistic() @@ -178,14 +200,14 @@ SrsStatistic::~SrsStatistic() srs_freep(kbps); if (true) { - std::map::iterator it; + std::map::iterator it; for (it = vhosts.begin(); it != vhosts.end(); it++) { SrsStatisticVhost* vhost = it->second; srs_freep(vhost); } } if (true) { - std::map::iterator it; + std::map::iterator it; for (it = streams.begin(); it != streams.end(); it++) { SrsStatisticStream* stream = it->second; srs_freep(stream); @@ -198,6 +220,11 @@ SrsStatistic::~SrsStatistic() srs_freep(client); } } + + vhosts.clear(); + rvhosts.clear(); + streams.clear(); + rstreams.clear(); } SrsStatistic* SrsStatistic::instance() @@ -205,16 +232,29 @@ SrsStatistic* SrsStatistic::instance() return _instance; } -SrsStatisticStream* SrsStatistic::find_stream(int stream_id) +SrsStatisticVhost* SrsStatistic::find_vhost(int vid) +{ + std::map::iterator it; + if ((it = vhosts.find(vid)) != vhosts.end()) { + return it->second; + } + return NULL; +} + +SrsStatisticStream* SrsStatistic::find_stream(int sid) +{ + std::map::iterator it; + if ((it = streams.find(sid)) != streams.end()) { + return it->second; + } + return NULL; +} + +SrsStatisticClient* SrsStatistic::find_client(int cid) { std::map::iterator it; - for (it = clients.begin(); it != clients.end(); it++) { - SrsStatisticClient* client = it->second; - SrsStatisticStream* stream = client->stream; - - if (stream_id == stream->id) { - return stream; - } + if ((it = clients.find(cid)) != clients.end()) { + return it->second; } return NULL; } @@ -338,14 +378,14 @@ SrsKbps* SrsStatistic::kbps_sample() { kbps->sample(); if (true) { - std::map::iterator it; + std::map::iterator it; for (it = vhosts.begin(); it != vhosts.end(); it++) { SrsStatisticVhost* vhost = it->second; vhost->kbps->sample(); } } if (true) { - std::map::iterator it; + std::map::iterator it; for (it = streams.begin(); it != streams.end(); it++) { SrsStatisticStream* stream = it->second; stream->kbps->sample(); @@ -365,7 +405,7 @@ int SrsStatistic::dumps_vhosts(stringstream& ss) int ret = ERROR_SUCCESS; ss << SRS_JARRAY_START; - std::map::iterator it; + std::map::iterator it; for (it = vhosts.begin(); it != vhosts.end(); it++) { SrsStatisticVhost* vhost = it->second; @@ -387,7 +427,7 @@ int SrsStatistic::dumps_streams(stringstream& ss) int ret = ERROR_SUCCESS; ss << SRS_JARRAY_START; - std::map::iterator it; + std::map::iterator it; for (it = streams.begin(); it != streams.end(); it++) { SrsStatisticStream* stream = it->second; @@ -404,19 +444,47 @@ int SrsStatistic::dumps_streams(stringstream& ss) return ret; } +int SrsStatistic::dumps_clients(stringstream& ss, int start, int count) +{ + int ret = ERROR_SUCCESS; + + ss << SRS_JARRAY_START; + std::map::iterator it = clients.begin(); + for (int i = 0; i < count && it != clients.end(); it++) { + if (i < start) { + continue; + } + + SrsStatisticClient* client = it->second; + + if (i != start) { + ss << SRS_JFIELD_CONT; + } + + if ((ret = client->dumps(ss)) != ERROR_SUCCESS) { + return ret; + } + } + ss << SRS_JARRAY_END; + + + return ret; +} + SrsStatisticVhost* SrsStatistic::create_vhost(SrsRequest* req) { SrsStatisticVhost* vhost = NULL; // create vhost if not exists. - if (vhosts.find(req->vhost) == vhosts.end()) { + if (rvhosts.find(req->vhost) == rvhosts.end()) { vhost = new SrsStatisticVhost(); vhost->vhost = req->vhost; - vhosts[req->vhost] = vhost; + rvhosts[req->vhost] = vhost; + vhosts[vhost->id] = vhost; return vhost; } - vhost = vhosts[req->vhost]; + vhost = rvhosts[req->vhost]; return vhost; } @@ -428,17 +496,18 @@ SrsStatisticStream* SrsStatistic::create_stream(SrsStatisticVhost* vhost, SrsReq SrsStatisticStream* stream = NULL; // create stream if not exists. - if (streams.find(url) == streams.end()) { + if (rstreams.find(url) == rstreams.end()) { stream = new SrsStatisticStream(); stream->vhost = vhost; stream->stream = req->stream; stream->app = req->app; stream->url = url; - streams[url] = stream; + rstreams[url] = stream; + streams[stream->id] = stream; return stream; } - stream = streams[url]; + stream = rstreams[url]; return stream; } diff --git a/trunk/src/app/srs_app_statistic.hpp b/trunk/src/app/srs_app_statistic.hpp index bb1ed29ae..9a8483245 100755 --- a/trunk/src/app/srs_app_statistic.hpp +++ b/trunk/src/app/srs_app_statistic.hpp @@ -115,6 +115,11 @@ struct SrsStatisticClient public: SrsStatisticStream* stream; int id; +public: + SrsStatisticClient(); + virtual ~SrsStatisticClient(); +public: + virtual int dumps(std::stringstream& ss); }; class SrsStatistic @@ -123,10 +128,19 @@ private: static SrsStatistic *_instance; // the id to identify the sever. int64_t _server_id; - // key: vhost name, value: vhost object. - std::map vhosts; - // key: stream url, value: stream object. - std::map streams; +private: + // key: vhost id, value: vhost object. + std::map vhosts; + // key: vhost url, value: vhost Object. + // @remark a fast index for vhosts. + std::map rvhosts; +private: + // key: stream id, value: stream Object. + std::map streams; + // key: stream url, value: stream Object. + // @remark a fast index for streams. + std::map rstreams; +private: // key: client id, value: stream object. std::map clients; // server total kbps. @@ -137,7 +151,10 @@ private: public: static SrsStatistic* instance(); public: - virtual SrsStatisticStream* find_stream(int stream_id); + virtual SrsStatisticVhost* find_vhost(int vid); + virtual SrsStatisticStream* find_stream(int sid); + virtual SrsStatisticClient* find_client(int cid); +public: /** * when got video info for stream. */ @@ -198,6 +215,12 @@ public: * dumps the streams to sstream in json. */ virtual int dumps_streams(std::stringstream& ss); + /** + * dumps the clients to sstream in json. + * @param start the start index, from 0. + * @param count the max count of clients to dump. + */ + virtual int dumps_clients(std::stringstream& ss, int start, int count); private: virtual SrsStatisticVhost* create_vhost(SrsRequest* req); virtual SrsStatisticStream* create_stream(SrsStatisticVhost* vhost, SrsRequest* req);