winlin

refine the stat api, support query specified stream.

@@ -470,40 +470,37 @@ int SrsGoApiStreams::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) @@ -470,40 +470,37 @@ int SrsGoApiStreams::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
470 int ret = ERROR_SUCCESS; 470 int ret = ERROR_SUCCESS;
471 SrsStatistic* stat = SrsStatistic::instance(); 471 SrsStatistic* stat = SrsStatistic::instance();
472 std::stringstream ss; 472 std::stringstream ss;
473 -  
474 - if (r->is_http_delete()) {  
475 - // path: {pattern}{stream_id}  
476 - // e.g. /api/v1/streams/100 pattern= /api/v1/streams/, stream_id=100  
477 - string sid = r->path().substr((int)entry->pattern.length());  
478 - if (sid.empty()) {  
479 - ret = ERROR_REQUEST_DATA;  
480 - srs_error("invalid param, stream_id=%s. ret=%d", sid.c_str(), ret);  
481 -  
482 - ss << SRS_JOBJECT_START  
483 - << SRS_JFIELD_ERROR(ret)  
484 - << SRS_JOBJECT_END;  
485 -  
486 - return srs_http_response_json(w, ss.str());  
487 - }  
488 -  
489 - int stream_id = ::atoi(sid.c_str());  
490 - SrsStatisticStream* stream = stat->find_stream(stream_id);  
491 - if (stream == NULL) {  
492 - ret = ERROR_RTMP_STREAM_NOT_FOUND;  
493 - srs_error("stream stream_id=%s not found. ret=%d", sid.c_str(), ret);  
494 -  
495 - ss << SRS_JOBJECT_START  
496 - << SRS_JFIELD_ERROR(ret)  
497 - << SRS_JOBJECT_END;  
498 -  
499 - return srs_http_response_json(w, ss.str()); 473 +
  474 + // path: {pattern}{stream_id}
  475 + // e.g. /api/v1/streams/100 pattern= /api/v1/streams/, stream_id=100
  476 + int sid = -1;
  477 + if (true) {
  478 + string stream_id = r->path().substr((int)entry->pattern.length());
  479 + if (!stream_id.empty()) {
  480 + sid = ::atoi(stream_id.c_str());
500 } 481 }
  482 + }
  483 +
  484 + SrsStatisticStream* stream = NULL;
  485 + if (sid >= 0 && (stream = stat->find_stream(sid)) == NULL) {
  486 + ret = ERROR_RTMP_STREAM_NOT_FOUND;
  487 + srs_error("stream stream_id=%d not found. ret=%d", sid, ret);
  488 +
  489 + ss << SRS_JOBJECT_START
  490 + << SRS_JFIELD_ERROR(ret)
  491 + << SRS_JOBJECT_END;
  492 +
  493 + return srs_http_response_json(w, ss.str());
  494 + }
501 495
  496 + if (r->is_http_delete()) {
  497 + srs_assert(stream);
  498 +
502 SrsSource* source = SrsSource::fetch(stream->vhost->vhost, stream->app, stream->stream); 499 SrsSource* source = SrsSource::fetch(stream->vhost->vhost, stream->app, stream->stream);
503 if (source) { 500 if (source) {
504 source->set_expired(); 501 source->set_expired();
505 srs_warn("disconnent stream=%d successfully. vhost=%s, app=%s, stream=%s.", 502 srs_warn("disconnent stream=%d successfully. vhost=%s, app=%s, stream=%s.",
506 - stream_id, stream->vhost->vhost.c_str(), stream->app.c_str(), stream->stream.c_str()); 503 + sid, stream->vhost->vhost.c_str(), stream->app.c_str(), stream->stream.c_str());
507 } else { 504 } else {
508 ret = ERROR_SOURCE_NOT_FOUND; 505 ret = ERROR_SOURCE_NOT_FOUND;
509 } 506 }
@@ -513,18 +510,31 @@ int SrsGoApiStreams::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) @@ -513,18 +510,31 @@ int SrsGoApiStreams::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
513 << SRS_JOBJECT_END; 510 << SRS_JOBJECT_END;
514 511
515 return srs_http_response_json(w, ss.str()); 512 return srs_http_response_json(w, ss.str());
516 - } else { 513 + } else if (r->is_http_get()) {
517 std::stringstream data; 514 std::stringstream data;
518 - int ret = stat->dumps_streams(data);  
519 515
520 - ss << SRS_JOBJECT_START  
521 - << SRS_JFIELD_ERROR(ret) << SRS_JFIELD_CONT  
522 - << SRS_JFIELD_ORG("server", stat->server_id()) << SRS_JFIELD_CONT  
523 - << SRS_JFIELD_ORG("streams", data.str())  
524 - << SRS_JOBJECT_END; 516 + if (!stream) {
  517 + ret = stat->dumps_streams(data);
  518 +
  519 + ss << SRS_JOBJECT_START
  520 + << SRS_JFIELD_ERROR(ret) << SRS_JFIELD_CONT
  521 + << SRS_JFIELD_ORG("server", stat->server_id()) << SRS_JFIELD_CONT
  522 + << SRS_JFIELD_ORG("streams", data.str())
  523 + << SRS_JOBJECT_END;
  524 + } else {
  525 + ret = stream->dumps(data);
  526 +
  527 + ss << SRS_JOBJECT_START
  528 + << SRS_JFIELD_ERROR(ret) << SRS_JFIELD_CONT
  529 + << SRS_JFIELD_ORG("server", stat->server_id()) << SRS_JFIELD_CONT
  530 + << SRS_JFIELD_ORG("stream", data.str())
  531 + << SRS_JOBJECT_END;
  532 + }
525 533
526 return srs_http_response_json(w, ss.str()); 534 return srs_http_response_json(w, ss.str());
527 } 535 }
  536 +
  537 + return ret;
528 } 538 }
529 539
530 SrsGoApiError::SrsGoApiError() 540 SrsGoApiError::SrsGoApiError()
@@ -47,6 +47,8 @@ SrsStatisticVhost::SrsStatisticVhost() @@ -47,6 +47,8 @@ SrsStatisticVhost::SrsStatisticVhost()
47 47
48 kbps = new SrsKbps(); 48 kbps = new SrsKbps();
49 kbps->set_io(NULL, NULL); 49 kbps->set_io(NULL, NULL);
  50 +
  51 + nb_clients = 0;
50 } 52 }
51 53
52 SrsStatisticVhost::~SrsStatisticVhost() 54 SrsStatisticVhost::~SrsStatisticVhost()
@@ -54,6 +56,31 @@ SrsStatisticVhost::~SrsStatisticVhost() @@ -54,6 +56,31 @@ SrsStatisticVhost::~SrsStatisticVhost()
54 srs_freep(kbps); 56 srs_freep(kbps);
55 } 57 }
56 58
  59 +int SrsStatisticVhost::dumps(stringstream& ss)
  60 +{
  61 + int ret = ERROR_SUCCESS;
  62 +
  63 + // dumps the config of vhost.
  64 + bool hls_enabled = _srs_config->get_hls_enabled(vhost);
  65 +
  66 + ss << SRS_JOBJECT_START
  67 + << SRS_JFIELD_ORG("id", id) << SRS_JFIELD_CONT
  68 + << SRS_JFIELD_STR("name", vhost) << SRS_JFIELD_CONT
  69 + << SRS_JFIELD_ORG("cleints", nb_clients) << SRS_JFIELD_CONT
  70 + << SRS_JFIELD_ORG("send_bytes", kbps->get_send_bytes()) << SRS_JFIELD_CONT
  71 + << SRS_JFIELD_ORG("recv_bytes", kbps->get_recv_bytes()) << SRS_JFIELD_CONT
  72 + << SRS_JFIELD_NAME("hls") << SRS_JOBJECT_START
  73 + << SRS_JFIELD_BOOL("enabled", hls_enabled);
  74 + if (hls_enabled) {
  75 + ss << SRS_JFIELD_CONT;
  76 + ss << SRS_JFIELD_ORG("fragment", _srs_config->get_hls_fragment(vhost));
  77 + }
  78 + ss << SRS_JOBJECT_END
  79 + << SRS_JOBJECT_END;
  80 +
  81 + return ret;
  82 +}
  83 +
57 SrsStatisticStream::SrsStatisticStream() 84 SrsStatisticStream::SrsStatisticStream()
58 { 85 {
59 id = srs_generate_id(); 86 id = srs_generate_id();
@@ -73,6 +100,8 @@ SrsStatisticStream::SrsStatisticStream() @@ -73,6 +100,8 @@ SrsStatisticStream::SrsStatisticStream()
73 100
74 kbps = new SrsKbps(); 101 kbps = new SrsKbps();
75 kbps->set_io(NULL, NULL); 102 kbps->set_io(NULL, NULL);
  103 +
  104 + nb_clients = 0;
76 } 105 }
77 106
78 SrsStatisticStream::~SrsStatisticStream() 107 SrsStatisticStream::~SrsStatisticStream()
@@ -80,6 +109,48 @@ SrsStatisticStream::~SrsStatisticStream() @@ -80,6 +109,48 @@ SrsStatisticStream::~SrsStatisticStream()
80 srs_freep(kbps); 109 srs_freep(kbps);
81 } 110 }
82 111
  112 +int SrsStatisticStream::dumps(stringstream& ss)
  113 +{
  114 + int ret = ERROR_SUCCESS;
  115 +
  116 + ss << SRS_JOBJECT_START
  117 + << SRS_JFIELD_ORG("id", id) << SRS_JFIELD_CONT
  118 + << SRS_JFIELD_STR("name", stream) << SRS_JFIELD_CONT
  119 + << SRS_JFIELD_ORG("vhost", vhost->id) << SRS_JFIELD_CONT
  120 + << SRS_JFIELD_STR("app", app) << SRS_JFIELD_CONT
  121 + << SRS_JFIELD_ORG("clients", nb_clients) << SRS_JFIELD_CONT
  122 + << SRS_JFIELD_ORG("send_bytes", kbps->get_send_bytes()) << SRS_JFIELD_CONT
  123 + << SRS_JFIELD_ORG("recv_bytes", kbps->get_recv_bytes()) << SRS_JFIELD_CONT
  124 + << SRS_JFIELD_ORG("live_ms", srs_get_system_time_ms()) << SRS_JFIELD_CONT
  125 + << SRS_JFIELD_STR("status", status) << SRS_JFIELD_CONT;
  126 +
  127 + if (!has_video) {
  128 + ss << SRS_JFIELD_NULL("video") << SRS_JFIELD_CONT;
  129 + } else {
  130 + ss << SRS_JFIELD_NAME("video") << SRS_JOBJECT_START
  131 + << SRS_JFIELD_STR("codec", srs_codec_video2str(vcodec)) << SRS_JFIELD_CONT
  132 + << SRS_JFIELD_STR("profile", srs_codec_avc_profile2str(avc_profile)) << SRS_JFIELD_CONT
  133 + << SRS_JFIELD_ORG("level", srs_codec_avc_level2str(avc_level))
  134 + << SRS_JOBJECT_END
  135 + << SRS_JFIELD_CONT;
  136 + }
  137 +
  138 + if (!has_audio) {
  139 + ss << SRS_JFIELD_NULL("audio");
  140 + } else {
  141 + ss << SRS_JFIELD_NAME("audio") << SRS_JOBJECT_START
  142 + << SRS_JFIELD_STR("codec", srs_codec_audio2str(acodec)) << SRS_JFIELD_CONT
  143 + << SRS_JFIELD_ORG("sample_rate", (int)flv_sample_rates[asample_rate]) << SRS_JFIELD_CONT
  144 + << SRS_JFIELD_ORG("channel", (int)asound_type + 1) << SRS_JFIELD_CONT
  145 + << SRS_JFIELD_STR("profile", srs_codec_aac_object2str(aac_object))
  146 + << SRS_JOBJECT_END;
  147 + }
  148 +
  149 + ss << SRS_JOBJECT_END;
  150 +
  151 + return ret;
  152 +}
  153 +
83 void SrsStatisticStream::publish() 154 void SrsStatisticStream::publish()
84 { 155 {
85 status = STATISTIC_STREAM_STATUS_PUBLISHING; 156 status = STATISTIC_STREAM_STATUS_PUBLISHING;
@@ -215,6 +286,10 @@ int SrsStatistic::on_client(int id, SrsRequest* req) @@ -215,6 +286,10 @@ int SrsStatistic::on_client(int id, SrsRequest* req)
215 } else { 286 } else {
216 client = clients[id]; 287 client = clients[id];
217 } 288 }
  289 +
  290 + // got client.
  291 + stream->nb_clients++;
  292 + vhost->nb_clients++;
218 293
219 return ret; 294 return ret;
220 } 295 }
@@ -222,12 +297,19 @@ int SrsStatistic::on_client(int id, SrsRequest* req) @@ -222,12 +297,19 @@ int SrsStatistic::on_client(int id, SrsRequest* req)
222 void SrsStatistic::on_disconnect(int id) 297 void SrsStatistic::on_disconnect(int id)
223 { 298 {
224 std::map<int, SrsStatisticClient*>::iterator it; 299 std::map<int, SrsStatisticClient*>::iterator it;
225 - it = clients.find(id);  
226 - if (it != clients.end()) {  
227 - SrsStatisticClient* client = it->second;  
228 - srs_freep(client);  
229 - clients.erase(it); 300 + if ((it = clients.find(id)) == clients.end()) {
  301 + return;
230 } 302 }
  303 +
  304 + SrsStatisticClient* client = it->second;
  305 + SrsStatisticStream* stream = client->stream;
  306 + SrsStatisticVhost* vhost = stream->vhost;
  307 +
  308 + srs_freep(client);
  309 + clients.erase(it);
  310 +
  311 + stream->nb_clients--;
  312 + vhost->nb_clients--;
231 } 313 }
232 314
233 void SrsStatistic::kbps_add_delta(SrsConnection* conn) 315 void SrsStatistic::kbps_add_delta(SrsConnection* conn)
@@ -286,26 +368,14 @@ int SrsStatistic::dumps_vhosts(stringstream& ss) @@ -286,26 +368,14 @@ int SrsStatistic::dumps_vhosts(stringstream& ss)
286 std::map<std::string, SrsStatisticVhost*>::iterator it; 368 std::map<std::string, SrsStatisticVhost*>::iterator it;
287 for (it = vhosts.begin(); it != vhosts.end(); it++) { 369 for (it = vhosts.begin(); it != vhosts.end(); it++) {
288 SrsStatisticVhost* vhost = it->second; 370 SrsStatisticVhost* vhost = it->second;
  371 +
289 if (it != vhosts.begin()) { 372 if (it != vhosts.begin()) {
290 ss << SRS_JFIELD_CONT; 373 ss << SRS_JFIELD_CONT;
291 } 374 }
292 375
293 - // dumps the config of vhost.  
294 - bool hls_enabled = _srs_config->get_hls_enabled(vhost->vhost);  
295 -  
296 - ss << SRS_JOBJECT_START  
297 - << SRS_JFIELD_ORG("id", vhost->id) << SRS_JFIELD_CONT  
298 - << SRS_JFIELD_STR("name", vhost->vhost) << SRS_JFIELD_CONT  
299 - << SRS_JFIELD_ORG("send_bytes", vhost->kbps->get_send_bytes()) << SRS_JFIELD_CONT  
300 - << SRS_JFIELD_ORG("recv_bytes", vhost->kbps->get_recv_bytes()) << SRS_JFIELD_CONT  
301 - << SRS_JFIELD_NAME("hls") << SRS_JOBJECT_START  
302 - << SRS_JFIELD_BOOL("enabled", hls_enabled);  
303 - if (hls_enabled) {  
304 - ss << SRS_JFIELD_CONT;  
305 - ss << SRS_JFIELD_ORG("fragment", _srs_config->get_hls_fragment(vhost->vhost)); 376 + if ((ret = vhost->dumps(ss)) != ERROR_SUCCESS) {
  377 + return ret;
306 } 378 }
307 - ss << SRS_JOBJECT_END  
308 - << SRS_JOBJECT_END;  
309 } 379 }
310 ss << SRS_JARRAY_END; 380 ss << SRS_JARRAY_END;
311 381
@@ -320,55 +390,14 @@ int SrsStatistic::dumps_streams(stringstream& ss) @@ -320,55 +390,14 @@ int SrsStatistic::dumps_streams(stringstream& ss)
320 std::map<std::string, SrsStatisticStream*>::iterator it; 390 std::map<std::string, SrsStatisticStream*>::iterator it;
321 for (it = streams.begin(); it != streams.end(); it++) { 391 for (it = streams.begin(); it != streams.end(); it++) {
322 SrsStatisticStream* stream = it->second; 392 SrsStatisticStream* stream = it->second;
  393 +
323 if (it != streams.begin()) { 394 if (it != streams.begin()) {
324 ss << SRS_JFIELD_CONT; 395 ss << SRS_JFIELD_CONT;
325 } 396 }
326 397
327 - int client_num = 0;  
328 - std::map<int, SrsStatisticClient*>::iterator it_client;  
329 - for (it_client = clients.begin(); it_client != clients.end(); it_client++) {  
330 - SrsStatisticClient* client = it_client->second;  
331 - if (client->stream == stream) {  
332 - client_num++;  
333 - } 398 + if ((ret = stream->dumps(ss)) != ERROR_SUCCESS) {
  399 + return ret;
334 } 400 }
335 -  
336 - ss << SRS_JOBJECT_START  
337 - << SRS_JFIELD_ORG("id", stream->id) << SRS_JFIELD_CONT  
338 - << SRS_JFIELD_STR("name", stream->stream) << SRS_JFIELD_CONT  
339 - << SRS_JFIELD_ORG("vhost", stream->vhost->id) << SRS_JFIELD_CONT  
340 - << SRS_JFIELD_STR("app", stream->app) << SRS_JFIELD_CONT  
341 - << SRS_JFIELD_ORG("clients", client_num) << SRS_JFIELD_CONT  
342 - << SRS_JFIELD_ORG("send_bytes", stream->kbps->get_send_bytes()) << SRS_JFIELD_CONT  
343 - << SRS_JFIELD_ORG("recv_bytes", stream->kbps->get_recv_bytes()) << SRS_JFIELD_CONT  
344 - << SRS_JFIELD_ORG("live_ms", srs_get_system_time_ms()) << SRS_JFIELD_CONT  
345 - << SRS_JFIELD_STR("status", stream->status) << SRS_JFIELD_CONT;  
346 -  
347 - if (!stream->has_video) {  
348 - ss << SRS_JFIELD_NULL("video") << SRS_JFIELD_CONT;  
349 - } else {  
350 - ss << SRS_JFIELD_NAME("video")  
351 - << SRS_JOBJECT_START  
352 - << SRS_JFIELD_STR("codec", srs_codec_video2str(stream->vcodec)) << SRS_JFIELD_CONT  
353 - << SRS_JFIELD_STR("profile", srs_codec_avc_profile2str(stream->avc_profile)) << SRS_JFIELD_CONT  
354 - << SRS_JFIELD_ORG("level", srs_codec_avc_level2str(stream->avc_level))  
355 - << SRS_JOBJECT_END  
356 - << SRS_JFIELD_CONT;  
357 - }  
358 -  
359 - if (!stream->has_audio) {  
360 - ss << SRS_JFIELD_NULL("audio");  
361 - } else {  
362 - ss << SRS_JFIELD_NAME("audio")  
363 - << SRS_JOBJECT_START  
364 - << SRS_JFIELD_STR("codec", srs_codec_audio2str(stream->acodec)) << SRS_JFIELD_CONT  
365 - << SRS_JFIELD_ORG("sample_rate", (int)flv_sample_rates[stream->asample_rate]) << SRS_JFIELD_CONT  
366 - << SRS_JFIELD_ORG("channel", (int)stream->asound_type + 1) << SRS_JFIELD_CONT  
367 - << SRS_JFIELD_STR("profile", srs_codec_aac_object2str(stream->aac_object))  
368 - << SRS_JOBJECT_END;  
369 - }  
370 -  
371 - ss << SRS_JOBJECT_END;  
372 } 401 }
373 ss << SRS_JARRAY_END; 402 ss << SRS_JARRAY_END;
374 403
@@ -47,6 +47,7 @@ struct SrsStatisticVhost @@ -47,6 +47,7 @@ struct SrsStatisticVhost
47 public: 47 public:
48 int64_t id; 48 int64_t id;
49 std::string vhost; 49 std::string vhost;
  50 + int nb_clients;
50 public: 51 public:
51 /** 52 /**
52 * vhost total kbps. 53 * vhost total kbps.
@@ -55,6 +56,8 @@ public: @@ -55,6 +56,8 @@ public:
55 public: 56 public:
56 SrsStatisticVhost(); 57 SrsStatisticVhost();
57 virtual ~SrsStatisticVhost(); 58 virtual ~SrsStatisticVhost();
  59 +public:
  60 + virtual int dumps(std::stringstream& ss);
58 }; 61 };
59 62
60 struct SrsStatisticStream 63 struct SrsStatisticStream
@@ -66,6 +69,7 @@ public: @@ -66,6 +69,7 @@ public:
66 std::string stream; 69 std::string stream;
67 std::string url; 70 std::string url;
68 std::string status; 71 std::string status;
  72 + int nb_clients;
69 public: 73 public:
70 /** 74 /**
71 * stream total kbps. 75 * stream total kbps.
@@ -94,6 +98,8 @@ public: @@ -94,6 +98,8 @@ public:
94 SrsStatisticStream(); 98 SrsStatisticStream();
95 virtual ~SrsStatisticStream(); 99 virtual ~SrsStatisticStream();
96 public: 100 public:
  101 + virtual int dumps(std::stringstream& ss);
  102 +public:
97 /** 103 /**
98 * publish the stream. 104 * publish the stream.
99 */ 105 */