mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
refine the stat api, support query specified stream.
This commit is contained in:
parent
c75f05c88b
commit
ab4620870d
3 changed files with 144 additions and 99 deletions
|
@ -471,39 +471,36 @@ int SrsGoApiStreams::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
|
||||||
SrsStatistic* stat = SrsStatistic::instance();
|
SrsStatistic* stat = SrsStatistic::instance();
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
|
// 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()) {
|
if (r->is_http_delete()) {
|
||||||
// path: {pattern}{stream_id}
|
srs_assert(stream);
|
||||||
// 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());
|
|
||||||
}
|
|
||||||
|
|
||||||
SrsSource* source = SrsSource::fetch(stream->vhost->vhost, stream->app, stream->stream);
|
SrsSource* source = SrsSource::fetch(stream->vhost->vhost, stream->app, stream->stream);
|
||||||
if (source) {
|
if (source) {
|
||||||
source->set_expired();
|
source->set_expired();
|
||||||
srs_warn("disconnent stream=%d successfully. vhost=%s, app=%s, stream=%s.",
|
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 {
|
} else {
|
||||||
ret = ERROR_SOURCE_NOT_FOUND;
|
ret = ERROR_SOURCE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
@ -513,18 +510,31 @@ int SrsGoApiStreams::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
|
||||||
<< SRS_JOBJECT_END;
|
<< SRS_JOBJECT_END;
|
||||||
|
|
||||||
return srs_http_response_json(w, ss.str());
|
return srs_http_response_json(w, ss.str());
|
||||||
} else {
|
} else if (r->is_http_get()) {
|
||||||
std::stringstream data;
|
std::stringstream data;
|
||||||
int ret = stat->dumps_streams(data);
|
|
||||||
|
|
||||||
ss << SRS_JOBJECT_START
|
if (!stream) {
|
||||||
<< SRS_JFIELD_ERROR(ret) << SRS_JFIELD_CONT
|
ret = stat->dumps_streams(data);
|
||||||
<< SRS_JFIELD_ORG("server", stat->server_id()) << SRS_JFIELD_CONT
|
|
||||||
<< SRS_JFIELD_ORG("streams", data.str())
|
ss << SRS_JOBJECT_START
|
||||||
<< SRS_JOBJECT_END;
|
<< 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 srs_http_response_json(w, ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsGoApiError::SrsGoApiError()
|
SrsGoApiError::SrsGoApiError()
|
||||||
|
|
|
@ -47,6 +47,8 @@ SrsStatisticVhost::SrsStatisticVhost()
|
||||||
|
|
||||||
kbps = new SrsKbps();
|
kbps = new SrsKbps();
|
||||||
kbps->set_io(NULL, NULL);
|
kbps->set_io(NULL, NULL);
|
||||||
|
|
||||||
|
nb_clients = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsStatisticVhost::~SrsStatisticVhost()
|
SrsStatisticVhost::~SrsStatisticVhost()
|
||||||
|
@ -54,6 +56,31 @@ SrsStatisticVhost::~SrsStatisticVhost()
|
||||||
srs_freep(kbps);
|
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()
|
SrsStatisticStream::SrsStatisticStream()
|
||||||
{
|
{
|
||||||
id = srs_generate_id();
|
id = srs_generate_id();
|
||||||
|
@ -73,6 +100,8 @@ SrsStatisticStream::SrsStatisticStream()
|
||||||
|
|
||||||
kbps = new SrsKbps();
|
kbps = new SrsKbps();
|
||||||
kbps->set_io(NULL, NULL);
|
kbps->set_io(NULL, NULL);
|
||||||
|
|
||||||
|
nb_clients = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsStatisticStream::~SrsStatisticStream()
|
SrsStatisticStream::~SrsStatisticStream()
|
||||||
|
@ -80,6 +109,48 @@ SrsStatisticStream::~SrsStatisticStream()
|
||||||
srs_freep(kbps);
|
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()
|
void SrsStatisticStream::publish()
|
||||||
{
|
{
|
||||||
status = STATISTIC_STREAM_STATUS_PUBLISHING;
|
status = STATISTIC_STREAM_STATUS_PUBLISHING;
|
||||||
|
@ -216,18 +287,29 @@ int SrsStatistic::on_client(int id, SrsRequest* req)
|
||||||
client = clients[id];
|
client = clients[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// got client.
|
||||||
|
stream->nb_clients++;
|
||||||
|
vhost->nb_clients++;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsStatistic::on_disconnect(int id)
|
void SrsStatistic::on_disconnect(int id)
|
||||||
{
|
{
|
||||||
std::map<int, SrsStatisticClient*>::iterator it;
|
std::map<int, SrsStatisticClient*>::iterator it;
|
||||||
it = clients.find(id);
|
if ((it = clients.find(id)) == clients.end()) {
|
||||||
if (it != clients.end()) {
|
return;
|
||||||
SrsStatisticClient* client = it->second;
|
|
||||||
srs_freep(client);
|
|
||||||
clients.erase(it);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
void SrsStatistic::kbps_add_delta(SrsConnection* conn)
|
||||||
|
@ -286,26 +368,14 @@ int SrsStatistic::dumps_vhosts(stringstream& ss)
|
||||||
std::map<std::string, SrsStatisticVhost*>::iterator it;
|
std::map<std::string, SrsStatisticVhost*>::iterator it;
|
||||||
for (it = vhosts.begin(); it != vhosts.end(); it++) {
|
for (it = vhosts.begin(); it != vhosts.end(); it++) {
|
||||||
SrsStatisticVhost* vhost = it->second;
|
SrsStatisticVhost* vhost = it->second;
|
||||||
|
|
||||||
if (it != vhosts.begin()) {
|
if (it != vhosts.begin()) {
|
||||||
ss << SRS_JFIELD_CONT;
|
ss << SRS_JFIELD_CONT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// dumps the config of vhost.
|
if ((ret = vhost->dumps(ss)) != ERROR_SUCCESS) {
|
||||||
bool hls_enabled = _srs_config->get_hls_enabled(vhost->vhost);
|
return ret;
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
ss << SRS_JOBJECT_END
|
|
||||||
<< SRS_JOBJECT_END;
|
|
||||||
}
|
}
|
||||||
ss << SRS_JARRAY_END;
|
ss << SRS_JARRAY_END;
|
||||||
|
|
||||||
|
@ -320,55 +390,14 @@ int SrsStatistic::dumps_streams(stringstream& ss)
|
||||||
std::map<std::string, SrsStatisticStream*>::iterator it;
|
std::map<std::string, SrsStatisticStream*>::iterator it;
|
||||||
for (it = streams.begin(); it != streams.end(); it++) {
|
for (it = streams.begin(); it != streams.end(); it++) {
|
||||||
SrsStatisticStream* stream = it->second;
|
SrsStatisticStream* stream = it->second;
|
||||||
|
|
||||||
if (it != streams.begin()) {
|
if (it != streams.begin()) {
|
||||||
ss << SRS_JFIELD_CONT;
|
ss << SRS_JFIELD_CONT;
|
||||||
}
|
}
|
||||||
|
|
||||||
int client_num = 0;
|
if ((ret = stream->dumps(ss)) != ERROR_SUCCESS) {
|
||||||
std::map<int, SrsStatisticClient*>::iterator it_client;
|
return ret;
|
||||||
for (it_client = clients.begin(); it_client != clients.end(); it_client++) {
|
|
||||||
SrsStatisticClient* client = it_client->second;
|
|
||||||
if (client->stream == stream) {
|
|
||||||
client_num++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
ss << SRS_JARRAY_END;
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ struct SrsStatisticVhost
|
||||||
public:
|
public:
|
||||||
int64_t id;
|
int64_t id;
|
||||||
std::string vhost;
|
std::string vhost;
|
||||||
|
int nb_clients;
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* vhost total kbps.
|
* vhost total kbps.
|
||||||
|
@ -55,6 +56,8 @@ public:
|
||||||
public:
|
public:
|
||||||
SrsStatisticVhost();
|
SrsStatisticVhost();
|
||||||
virtual ~SrsStatisticVhost();
|
virtual ~SrsStatisticVhost();
|
||||||
|
public:
|
||||||
|
virtual int dumps(std::stringstream& ss);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SrsStatisticStream
|
struct SrsStatisticStream
|
||||||
|
@ -66,6 +69,7 @@ public:
|
||||||
std::string stream;
|
std::string stream;
|
||||||
std::string url;
|
std::string url;
|
||||||
std::string status;
|
std::string status;
|
||||||
|
int nb_clients;
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* stream total kbps.
|
* stream total kbps.
|
||||||
|
@ -93,6 +97,8 @@ public:
|
||||||
public:
|
public:
|
||||||
SrsStatisticStream();
|
SrsStatisticStream();
|
||||||
virtual ~SrsStatisticStream();
|
virtual ~SrsStatisticStream();
|
||||||
|
public:
|
||||||
|
virtual int dumps(std::stringstream& ss);
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* publish the stream.
|
* publish the stream.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue