add cpu stat

pull/133/head
winlin 11 years ago
parent 4c5aae7804
commit 117fd67950

@ -1079,6 +1079,18 @@ int SrsConfig::parse_options(int argc, char** argv)
{
int ret = ERROR_SUCCESS;
for (int i = 0; i < argc; i++) {
_argv.append(argv[i]);
if (i < argc - 1) {
_argv.append(" ");
}
}
char cwd[256];
getcwd(cwd, sizeof(cwd));
_cwd = cwd;
show_help = true;
for (int i = 1; i < argc; i++) {
if ((ret = parse_argv(i, argv)) != ERROR_SUCCESS) {
@ -1239,6 +1251,16 @@ void SrsConfig::print_help(char** argv)
argv[0], argv[0], argv[0], argv[0]);
}
string SrsConfig::get_cwd()
{
return _cwd;
}
string SrsConfig::get_argv()
{
return _argv;
}
bool SrsConfig::get_deamon()
{
srs_assert(root);

@ -120,6 +120,8 @@ private:
bool test_conf;
bool show_version;
std::string config_file;
std::string _argv;
std::string _cwd;
SrsConfDirective* root;
std::vector<ISrsReloadHandler*> subscribes;
public:
@ -143,6 +145,9 @@ private:
virtual int parse_file(const char* filename);
virtual int parse_argv(int& i, char** argv);
virtual void print_help(char** argv);
public:
virtual std::string get_cwd();
virtual std::string get_argv();
// global section
public:
virtual SrsConfDirective* get_root();

@ -34,6 +34,8 @@ using namespace std;
#include <srs_app_socket.hpp>
#include <srs_core_autofree.hpp>
#include <srs_app_json.hpp>
#include <srs_app_config.hpp>
#include <srs_kernel_utility.hpp>
SrsApiRoot::SrsApiRoot()
{
@ -114,6 +116,8 @@ int SrsApiApi::do_process_request(SrsSocket* skt, SrsHttpMessage* req)
SrsApiV1::SrsApiV1()
{
handlers.push_back(new SrsApiVersion());
handlers.push_back(new SrsApiSummaries());
handlers.push_back(new SrsApiRusages());
handlers.push_back(new SrsApiAuthors());
}
@ -134,6 +138,9 @@ int SrsApiV1::do_process_request(SrsSocket* skt, SrsHttpMessage* req)
<< JFIELD_ERROR(ERROR_SUCCESS) << JFIELD_CONT
<< JFIELD_ORG("urls", JOBJECT_START)
<< JFIELD_STR("versions", "the version of SRS") << JFIELD_CONT
<< JFIELD_STR("summaries", "the summary(pid, argv, pwd, cpu, mem) of SRS") << JFIELD_CONT
<< JFIELD_STR("rusages", "the rusage of SRS") << JFIELD_CONT
<< JFIELD_STR("proc_stats", "the /proc/self/stat of SRS") << JFIELD_CONT
<< JFIELD_STR("authors", "the primary authors and contributors")
<< JOBJECT_END
<< JOBJECT_END;
@ -171,6 +178,89 @@ int SrsApiVersion::do_process_request(SrsSocket* skt, SrsHttpMessage* req)
return res_json(skt, req, ss.str());
}
SrsApiSummaries::SrsApiSummaries()
{
}
SrsApiSummaries::~SrsApiSummaries()
{
}
bool SrsApiSummaries::can_handle(const char* path, int length, const char** /*pchild*/)
{
return srs_path_equals("/summaries", path, length);
}
int SrsApiSummaries::do_process_request(SrsSocket* skt, SrsHttpMessage* req)
{
std::stringstream ss;
SrsRusage* r = srs_get_system_rusage();
SrsCpuSelfStat* u = srs_get_self_cpu_stat();
SrsCpuSystemStat* s = srs_get_system_cpu_stat();
ss << JOBJECT_START
<< JFIELD_ERROR(ERROR_SUCCESS) << JFIELD_CONT
<< JFIELD_ORG("data", JOBJECT_START)
<< JFIELD_ORG("pid", getpid()) << JFIELD_CONT
<< JFIELD_STR("argv", _srs_config->get_argv()) << JFIELD_CONT
<< JFIELD_STR("cwd", _srs_config->get_cwd()) << JFIELD_CONT
<< JFIELD_ORG("rusage_ok", (r->ok? "true":"false")) << JFIELD_CONT
<< JFIELD_ORG("self_cpu_stat_ok", (u->ok? "true":"false")) << JFIELD_CONT
<< JFIELD_ORG("system_cpu_stat_ok", (s->ok? "true":"false")) << JFIELD_CONT
<< JFIELD_ORG("mem_kbyte", r->r.ru_maxrss) << JFIELD_CONT
<< JFIELD_ORG("ppid", u->ppid)
<< JOBJECT_END
<< JOBJECT_END;
return res_json(skt, req, ss.str());
}
SrsApiRusages::SrsApiRusages()
{
}
SrsApiRusages::~SrsApiRusages()
{
}
bool SrsApiRusages::can_handle(const char* path, int length, const char** /*pchild*/)
{
return srs_path_equals("/rusages", path, length);
}
int SrsApiRusages::do_process_request(SrsSocket* skt, SrsHttpMessage* req)
{
std::stringstream ss;
SrsRusage* r = srs_get_system_rusage();
ss << JOBJECT_START
<< JFIELD_ERROR(ERROR_SUCCESS) << JFIELD_CONT
<< JFIELD_ORG("data", JOBJECT_START)
<< JFIELD_ORG("rusage_ok", (r->ok? "true":"false")) << JFIELD_CONT
<< JFIELD_ORG("ru_utime", r->r.ru_utime.tv_sec) << JFIELD_CONT
<< JFIELD_ORG("ru_stime", r->r.ru_stime.tv_sec) << JFIELD_CONT
<< JFIELD_ORG("ru_maxrss", r->r.ru_maxrss) << JFIELD_CONT
<< JFIELD_ORG("ru_ixrss", r->r.ru_ixrss) << JFIELD_CONT
<< JFIELD_ORG("ru_idrss", r->r.ru_idrss) << JFIELD_CONT
<< JFIELD_ORG("ru_isrss", r->r.ru_isrss) << JFIELD_CONT
<< JFIELD_ORG("ru_minflt", r->r.ru_minflt) << JFIELD_CONT
<< JFIELD_ORG("ru_majflt", r->r.ru_majflt) << JFIELD_CONT
<< JFIELD_ORG("ru_nswap", r->r.ru_nswap) << JFIELD_CONT
<< JFIELD_ORG("ru_inblock", r->r.ru_inblock) << JFIELD_CONT
<< JFIELD_ORG("ru_oublock", r->r.ru_oublock) << JFIELD_CONT
<< JFIELD_ORG("ru_msgsnd", r->r.ru_msgsnd) << JFIELD_CONT
<< JFIELD_ORG("ru_msgrcv", r->r.ru_msgrcv) << JFIELD_CONT
<< JFIELD_ORG("ru_nsignals", r->r.ru_nsignals) << JFIELD_CONT
<< JFIELD_ORG("ru_nvcsw", r->r.ru_nvcsw) << JFIELD_CONT
<< JFIELD_ORG("ru_nivcsw", r->r.ru_nivcsw)
<< JOBJECT_END
<< JOBJECT_END;
return res_json(skt, req, ss.str());
}
SrsApiAuthors::SrsApiAuthors()
{
}

@ -87,6 +87,28 @@ protected:
virtual int do_process_request(SrsSocket* skt, SrsHttpMessage* req);
};
class SrsApiSummaries : public SrsHttpHandler
{
public:
SrsApiSummaries();
virtual ~SrsApiSummaries();
public:
virtual bool can_handle(const char* path, int length, const char** pchild);
protected:
virtual int do_process_request(SrsSocket* skt, SrsHttpMessage* req);
};
class SrsApiRusages : public SrsHttpHandler
{
public:
SrsApiRusages();
virtual ~SrsApiRusages();
public:
virtual bool can_handle(const char* path, int length, const char** pchild);
protected:
virtual int do_process_request(SrsSocket* skt, SrsHttpMessage* req);
};
class SrsApiAuthors : public SrsHttpHandler
{
public:

@ -46,7 +46,21 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#endif
#define SERVER_LISTEN_BACKLOG 512
#define SRS_SYS_TIME_RESOLUTION_MS 500
// system interval
#define SRS_SYS_CYCLE_INTERVAL 100
// update time interval:
// SRS_SYS_CYCLE_INTERVAL * SRS_SYS_TIME_RESOLUTION_MS_TIMES
#define SRS_SYS_TIME_RESOLUTION_MS_TIMES 3
// update rusage interval:
// SRS_SYS_CYCLE_INTERVAL * SRS_SYS_RUSAGE_RESOLUTION_TIMES
#define SRS_SYS_RUSAGE_RESOLUTION_TIMES 15
// update rusage interval:
// SRS_SYS_CYCLE_INTERVAL * SRS_SYS_CPU_STAT_RESOLUTION_TIMES
#define SRS_SYS_CPU_STAT_RESOLUTION_TIMES 15
SrsListener::SrsListener(SrsServer* server, SrsListenerType type)
{
@ -393,10 +407,15 @@ int SrsServer::cycle()
{
int ret = ERROR_SUCCESS;
// find the max loop
int max = srs_max(0, SRS_SYS_TIME_RESOLUTION_MS_TIMES);
max = srs_max(max, SRS_SYS_RUSAGE_RESOLUTION_TIMES);
max = srs_max(max, SRS_SYS_CPU_STAT_RESOLUTION_TIMES);
// the deamon thread, update the time cache
while (true) {
st_usleep(SRS_SYS_TIME_RESOLUTION_MS * 1000);
srs_update_system_time_ms();
for (int i = 1; i < max + 1; i++) {
st_usleep(SRS_SYS_CYCLE_INTERVAL * 1000);
// for gperf heap checker,
// @see: research/gperftools/heap-checker/heap_checker.cc
@ -404,20 +423,32 @@ int SrsServer::cycle()
// but, if gperf, use reload to ensure main return normally,
// because directly exit will cause core-dump.
#ifdef SRS_AUTO_GPERF_MC
if (signal_gmc_stop) {
break;
}
if (signal_gmc_stop) {
break;
}
#endif
if (signal_reload) {
signal_reload = false;
srs_info("get signal reload, to reload the config.");
if (signal_reload) {
signal_reload = false;
srs_info("get signal reload, to reload the config.");
if ((ret = _srs_config->reload()) != ERROR_SUCCESS) {
srs_error("reload config failed. ret=%d", ret);
return ret;
}
srs_trace("reload config success.");
}
if ((ret = _srs_config->reload()) != ERROR_SUCCESS) {
srs_error("reload config failed. ret=%d", ret);
return ret;
// update the cache time or rusage.
if (i == SRS_SYS_TIME_RESOLUTION_MS_TIMES) {
srs_update_system_time_ms();
}
if (i == SRS_SYS_RUSAGE_RESOLUTION_TIMES) {
srs_update_system_rusage();
}
if (i == SRS_SYS_CPU_STAT_RESOLUTION_TIMES) {
srs_update_system_cpu_stat();
}
srs_trace("reload config success.");
}
}

@ -57,3 +57,116 @@ void srs_update_system_time_ms()
_srs_system_time_us_cache = now_us;
}
static SrsRusage _srs_system_rusage;
SrsRusage::SrsRusage()
{
ok = false;
memset(&r, 0, sizeof(rusage));
}
SrsRusage* srs_get_system_rusage()
{
return &_srs_system_rusage;
}
void srs_update_system_rusage()
{
if (getrusage(RUSAGE_SELF, &_srs_system_rusage.r) < 0) {
srs_warn("getrusage failed, ignore");
return;
}
_srs_system_rusage.ok = true;
}
static SrsCpuSelfStat _srs_system_cpu_self_stat;
static SrsCpuSystemStat _srs_system_cpu_system_stat;
SrsCpuSelfStat::SrsCpuSelfStat()
{
ok = false;
}
SrsCpuSystemStat::SrsCpuSystemStat()
{
ok = false;
}
SrsCpuSelfStat* srs_get_self_cpu_stat()
{
return &_srs_system_cpu_self_stat;
}
SrsCpuSystemStat* srs_get_system_cpu_stat()
{
return &_srs_system_cpu_system_stat;
}
void srs_update_system_cpu_stat()
{
// system cpu stat
if (true) {
FILE* f = fopen("/proc/stat", "r");
if (f == NULL) {
srs_warn("open system cpu stat failed, ignore");
return;
}
SrsCpuSystemStat& r = _srs_system_cpu_system_stat;
for (;;) {
int ret = fscanf(f, "%4s %lu %lu %lu %lu %lu "
"%lu %lu %lu %lu\n",
r.label, &r.user, &r.nice, &r.sys, &r.idle, &r.iowait,
&r.irq, &r.softirq, &r.steal, &r.guest);
r.ok = false;
if (ret == EOF) {
break;
}
if (strcmp("cpu", r.label) == 0) {
r.ok = true;
break;
}
}
fclose(f);
}
// self cpu stat
if (true) {
FILE* f = fopen("/proc/self/stat", "r");
if (f == NULL) {
srs_warn("open self cpu stat failed, ignore");
return;
}
SrsCpuSelfStat& r = _srs_system_cpu_self_stat;
int ret = fscanf(f, "%d %32s %c %d %d %d %d "
"%d %u %lu %lu %lu %lu "
"%lu %lu %ld %ld %ld %ld "
"%ld %ld %llu %lu %ld "
"%lu %lu %lu %lu %lu "
"%lu %lu %lu %lu %lu "
"%lu %lu %lu %d %d "
"%u %u %llu "
"%lu %ld",
&r.pid, r.comm, &r.state, &r.ppid, &r.pgrp, &r.session, &r.tty_nr,
&r.tpgid, &r.flags, &r.minflt, &r.cminflt, &r.majflt, &r.cmajflt,
&r.utime, &r.stime, &r.cutime, &r.cstime, &r.priority, &r.nice,
&r.num_threads, &r.itrealvalue, &r.starttime, &r.vsize, &r.rss,
&r.rsslim, &r.startcode, &r.endcode, &r.startstack, &r.kstkesp,
&r.kstkeip, &r.signal, &r.blocked, &r.sigignore, &r.sigcatch,
&r.wchan, &r.nswap, &r.cnswap, &r.exit_signal, &r.processor,
&r.rt_priority, &r.policy, &r.delayacct_blkio_ticks,
&r.guest_time, &r.cguest_time);
if (ret >= 0) {
r.ok = true;
}
fclose(f);
}
}

@ -30,9 +30,222 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <srs_core.hpp>
#include <sys/resource.h>
// get current system time in ms, use cache to avoid performance problem
extern int64_t srs_get_system_time_ms();
// the deamon st-thread will update it.
extern void srs_update_system_time_ms();
// @see: man getrusage
struct SrsRusage
{
bool ok;
rusage r;
SrsRusage();
};
// get system rusage, use cache to avoid performance problem.
extern SrsRusage* srs_get_system_rusage();
// the deamon st-thread will update it.
extern void srs_update_system_rusage();
// @see: man 5 proc, /proc/[pid]/stat
struct SrsCpuSelfStat
{
// whether the data is ok.
bool ok;
// pid %d The process ID.
int pid;
// comm %s The filename of the executable, in parentheses. This is visible whether or not the executable is
// swapped out.
char comm[32];
// state %c One character from the string "RSDZTW" where R is running, S is sleeping in an interruptible wait, D
// is waiting in uninterruptible disk sleep, Z is zombie, T is traced or stopped (on a signal), and W is
// paging.
char state;
// ppid %d The PID of the parent.
int ppid;
// pgrp %d The process group ID of the process.
int pgrp;
// session %d The session ID of the process.
int session;
// tty_nr %d The controlling terminal of the process. (The minor device number is contained in the combination of
// bits 31 to 20 and 7 to 0; the major device number is in bits 15 t0 8.)
int tty_nr;
// tpgid %d The ID of the foreground process group of the controlling terminal of the process.
int tpgid;
// flags %u (%lu before Linux 2.6.22)
// The kernel flags word of the process. For bit meanings, see the PF_* defines in <linux/sched.h>.
// Details depend on the kernel version.
unsigned int flags;
// minflt %lu The number of minor faults the process has made which have not required loading a memory page from
// disk.
unsigned long minflt;
// cminflt %lu The number of minor faults that the processs waited-for children have made.
unsigned long cminflt;
// majflt %lu The number of major faults the process has made which have required loading a memory page from disk.
unsigned long majflt;
// cmajflt %lu The number of major faults that the processs waited-for children have made.
unsigned long cmajflt;
// utime %lu Amount of time that this process has been scheduled in user mode, measured in clock ticks (divide by
// sysconf(_SC_CLK_TCK). This includes guest time, guest_time (time spent running a virtual CPU, see
// below), so that applications that are not aware of the guest time field do not lose that time from
// their calculations.
unsigned long utime;
// stime %lu Amount of time that this process has been scheduled in kernel mode, measured in clock ticks (divide by
// sysconf(_SC_CLK_TCK).
unsigned long stime;
// cutime %ld Amount of time that this processs waited-for children have been scheduled in user mode, measured in
// clock ticks (divide by sysconf(_SC_CLK_TCK). (See also times(2).) This includes guest time,
// cguest_time (time spent running a virtual CPU, see below).
long cutime;
// cstime %ld Amount of time that this processs waited-for children have been scheduled in kernel mode, measured in
// clock ticks (divide by sysconf(_SC_CLK_TCK).
long cstime;
// priority %ld
// (Explanation for Linux 2.6) For processes running a real-time scheduling policy (policy below; see
// sched_setscheduler(2)), this is the negated scheduling priority, minus one; that is, a number in the
// range -2 to -100, corresponding to real-time priorities 1 to 99. For processes running under a non-
// real-time scheduling policy, this is the raw nice value (setpriority(2)) as represented in the kernel.
// The kernel stores nice values as numbers in the range 0 (high) to 39 (low), corresponding to the user-
// visible nice range of -20 to 19.
//
// Before Linux 2.6, this was a scaled value based on the scheduler weighting given to this process.
long priority;
// nice %ld The nice value (see setpriority(2)), a value in the range 19 (low priority) to -20 (high priority).
long nice;
// num_threads %ld
// Number of threads in this process (since Linux 2.6). Before kernel 2.6, this field was hard coded to
// 0 as a placeholder for an earlier removed field.
long num_threads;
// itrealvalue %ld
// The time in jiffies before the next SIGALRM is sent to the process due to an interval timer. Since
// kernel 2.6.17, this field is no longer maintained, and is hard coded as 0.
long itrealvalue;
// starttime %llu (was %lu before Linux 2.6)
// The time in jiffies the process started after system boot.
long long starttime;
// vsize %lu Virtual memory size in bytes.
unsigned long vsize;
// rss %ld Resident Set Size: number of pages the process has in real memory. This is just the pages which count
// towards text, data, or stack space. This does not include pages which have not been demand-loaded in,
// or which are swapped out.
long rss;
// rsslim %lu Current soft limit in bytes on the rss of the process; see the description of RLIMIT_RSS in getprior-
// ity(2).
unsigned long rsslim;
// startcode %lu
// The address above which program text can run.
unsigned long startcode;
// endcode %lu The address below which program text can run.
unsigned long endcode;
// startstack %lu
// The address of the start (i.e., bottom) of the stack.
unsigned long startstack;
// kstkesp %lu The current value of ESP (stack pointer), as found in the kernel stack page for the process.
unsigned long kstkesp;
// kstkeip %lu The current EIP (instruction pointer).
unsigned long kstkeip;
// signal %lu The bitmap of pending signals, displayed as a decimal number. Obsolete, because it does not provide
// information on real-time signals; use /proc/[pid]/status instead.
unsigned long signal;
// blocked %lu The bitmap of blocked signals, displayed as a decimal number. Obsolete, because it does not provide
// information on real-time signals; use /proc/[pid]/status instead.
unsigned long blocked;
// sigignore %lu
// The bitmap of ignored signals, displayed as a decimal number. Obsolete, because it does not provide
// information on real-time signals; use /proc/[pid]/status instead.
unsigned long sigignore;
// sigcatch %lu
// The bitmap of caught signals, displayed as a decimal number. Obsolete, because it does not provide
// information on real-time signals; use /proc/[pid]/status instead.
unsigned long sigcatch;
// wchan %lu This is the "channel" in which the process is waiting. It is the address of a system call, and can be
// looked up in a namelist if you need a textual name. (If you have an up-to-date /etc/psdatabase, then
// try ps -l to see the WCHAN field in action.)
unsigned long wchan;
// nswap %lu Number of pages swapped (not maintained).
unsigned long nswap;
// cnswap %lu Cumulative nswap for child processes (not maintained).
unsigned long cnswap;
// exit_signal %d (since Linux 2.1.22)
// Signal to be sent to parent when we die.
int exit_signal;
// processor %d (since Linux 2.2.8)
// CPU number last executed on.
int processor;
// rt_priority %u (since Linux 2.5.19; was %lu before Linux 2.6.22)
// Real-time scheduling priority, a number in the range 1 to 99 for processes scheduled under a real-time
// policy, or 0, for non-real-time processes (see sched_setscheduler(2)).
unsigned int rt_priority;
// policy %u (since Linux 2.5.19; was %lu before Linux 2.6.22)
// Scheduling policy (see sched_setscheduler(2)). Decode using the SCHED_* constants in linux/sched.h.
unsigned int policy;
// delayacct_blkio_ticks %llu (since Linux 2.6.18)
// Aggregated block I/O delays, measured in clock ticks (centiseconds).
unsigned long long delayacct_blkio_ticks;
// guest_time %lu (since Linux 2.6.24)
// Guest time of the process (time spent running a virtual CPU for a guest operating system), measured in
// clock ticks (divide by sysconf(_SC_CLK_TCK).
unsigned long guest_time;
// cguest_time %ld (since Linux 2.6.24)
// Guest time of the processs children, measured in clock ticks (divide by sysconf(_SC_CLK_TCK).
long cguest_time;
SrsCpuSelfStat();
};
// @see: man 5 proc, /proc/stat
struct SrsCpuSystemStat
{
// whether the data is ok.
bool ok;
// always be cpu
char label[32];
//The amount of time, measured in units of USER_HZ (1/100ths of a second on most architectures, use
// sysconf(_SC_CLK_TCK) to obtain the right value)
//
// the system spent in user mode,
unsigned long user;
// user mode with low priority (nice),
unsigned long nice;
// system mode,
unsigned long sys;
// and the idle task, respectively.
unsigned long idle;
// In Linux 2.6 this line includes three additional columns:
//
// iowait - time waiting for I/O to complete (since 2.5.41);
unsigned long iowait;
// irq - time servicing interrupts (since 2.6.0-test4);
unsigned long irq;
// softirq - time servicing softirqs (since 2.6.0-test4).
unsigned long softirq;
// Since Linux 2.6.11, there is an eighth column,
// steal - stolen time, which is the time spent in other oper-
// ating systems when running in a virtualized environment
unsigned long steal;
// Since Linux 2.6.24, there is a ninth column,
// guest, which is the time spent running a virtual CPU for guest
// operating systems under the control of the Linux kernel.
unsigned long guest;
SrsCpuSystemStat();
};
// get system cpu stat, use cache to avoid performance problem.
extern SrsCpuSelfStat* srs_get_self_cpu_stat();
// get system cpu stat, use cache to avoid performance problem.
extern SrsCpuSystemStat* srs_get_system_cpu_stat();
// the deamon st-thread will update it.
extern void srs_update_system_cpu_stat();
#endif

Loading…
Cancel
Save