statistics counters: callsmax/avg, cpsmax/avg

max/avg calls and calls/s values, can be accessed via
get_callsmax/get_callsavg/get_cpsmax/get_cpsavg from
- stats server
- XMLRPC through xmlrpc2di

based on a patch by Robert Szokovacs rsokovacs gammatelecom hu
sayer/1.4-spce2.6
Stefan Sayer 16 years ago
parent 7774944f12
commit 21642b8c9a

@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 iptego GmbH
* Copyright (C) 2010-2011 Stefan Sayer
*
* This file is part of SEMS, a free SIP media server.
*
@ -336,7 +337,12 @@ XMLRPC2DIServer::XMLRPC2DIServer(unsigned int port,
// register method 'set_shutdownmode'
setshutdownmode_method(s),
// register method 'get_shutdownmode'
getshutdownmode_method(s)
getshutdownmode_method(s),
getcallsavg_method(s),
getcallsmax_method(s),
getcpsavg_method(s),
getcpsmax_method(s)
{
DBG("XMLRPC Server: enabled builtin method 'calls'\n");
@ -344,6 +350,10 @@ XMLRPC2DIServer::XMLRPC2DIServer(unsigned int port,
DBG("XMLRPC Server: enabled builtin method 'set_loglevel'\n");
DBG("XMLRPC Server: enabled builtin method 'get_shutdownmode'\n");
DBG("XMLRPC Server: enabled builtin method 'set_shutdownmode'\n");
DBG("XMLRPC Server: enabled builtin method 'get_callsavg'\n");
DBG("XMLRPC Server: enabled builtin method 'get_callsmax'\n");
DBG("XMLRPC Server: enabled builtin method 'get_cpsavg'\n");
DBG("XMLRPC Server: enabled builtin method 'get_cpsmax'\n");
// export all methods via 'di' function?
if (di_export) {
@ -460,6 +470,19 @@ void XMLRPC2DIServerSetShutdownmodeMethod::execute(XmlRpcValue& params, XmlRpcVa
result = "200 OK";
}
#define XMLMETH_EXEC(_meth, _sess_func, _descr) \
void _meth::execute(XmlRpcValue& params, XmlRpcValue& result) { \
unsigned int res = AmSession::_sess_func(); \
result = (int)res; \
DBG("XMLRPC2DI: " _descr "(): %u\n", res); \
}
XMLMETH_EXEC(XMLRPC2DIServerGetCallsavgMethod, getAvgSessionNum, "get_callsavg");
XMLMETH_EXEC(XMLRPC2DIServerGetCallsmaxMethod, getMaxSessionNum, "get_callsmax");
XMLMETH_EXEC(XMLRPC2DIServerGetCpsavgMethod, getAvgCPS, "get_cpsavg");
XMLMETH_EXEC(XMLRPC2DIServerGetCpsmaxMethod, getMaxCPS, "get_cpsmax");
#undef XMLMETH_EXEC
void XMLRPC2DIServerDIMethod::execute(XmlRpcValue& params, XmlRpcValue& result) {
try {
if (params.size() < 2) {

@ -60,6 +60,12 @@ DEF_XMLRPCSERVERMETHOD(XMLRPC2DIServerGetLoglevelMethod, "get_loglevel");
DEF_XMLRPCSERVERMETHOD(XMLRPC2DIServerSetShutdownmodeMethod, "set_shutdownmode");
DEF_XMLRPCSERVERMETHOD(XMLRPC2DIServerGetShutdownmodeMethod, "get_shutdownmode");
DEF_XMLRPCSERVERMETHOD(XMLRPC2DIServerGetCallsavgMethod, "get_callsavg");
DEF_XMLRPCSERVERMETHOD(XMLRPC2DIServerGetCallsmaxMethod, "get_callsmax");
DEF_XMLRPCSERVERMETHOD(XMLRPC2DIServerGetCpsavgMethod, "get_cpsavg");
DEF_XMLRPCSERVERMETHOD(XMLRPC2DIServerGetCpsmaxMethod, "get_cpsmax");
class XMLRPC2DIServerDIMethod
: public XmlRpcServerMethod {
@ -95,6 +101,12 @@ class XMLRPC2DIServer : public AmThread {
XMLRPC2DIServerGetLoglevelMethod getloglevel_method;
XMLRPC2DIServerSetShutdownmodeMethod setshutdownmode_method;
XMLRPC2DIServerGetShutdownmodeMethod getshutdownmode_method;
XMLRPC2DIServerGetCallsavgMethod getcallsavg_method;
XMLRPC2DIServerGetCallsmaxMethod getcallsmax_method;
XMLRPC2DIServerGetCpsavgMethod getcpsavg_method;
XMLRPC2DIServerGetCpsmaxMethod getcpsmax_method;
XMLRPC2DIServerDIMethod* di_method;
void registerMethods(const std::string& iface);

@ -52,7 +52,21 @@
volatile unsigned int AmSession::session_num = 0;
AmMutex AmSession::session_num_mut;
volatile unsigned int AmSession::max_session_num = 0;
volatile unsigned long long AmSession::avg_session_num = 0;
volatile unsigned long AmSession::max_cps = 0;
volatile unsigned long AmSession::max_cps_counter = 0;
volatile unsigned long AmSession::avg_cps = 0;
struct timeval get_now() {
struct timeval res;
gettimeofday(&res, NULL);
return res;
}
struct timeval avg_last_timestamp = get_now();
struct timeval avg_first_timestamp = avg_last_timestamp;
struct timeval cps_first_timestamp = avg_last_timestamp;
struct timeval cps_max_timestamp = avg_last_timestamp;
// AmSession methods
@ -370,9 +384,7 @@ bool AmSession::startup() {
}
#endif
session_num_mut.lock();
session_num++;
session_num_mut.unlock();
session_started();
try {
try {
@ -394,9 +406,7 @@ bool AmSession::startup() {
onBeforeDestroy();
destroy();
session_num_mut.lock();
session_num--;
session_num_mut.unlock();
session_stopped();
return false;
}
@ -514,9 +524,7 @@ void AmSession::finalize() {
onBeforeDestroy();
destroy();
session_num_mut.lock();
session_num--;
session_num_mut.unlock();
session_stopped();
DBG("session is stopped.\n");
}
@ -541,14 +549,12 @@ void AmSession::setStopped(bool wakeup) {
new AmEvent(0));
}
void AmSession::destroy()
{
void AmSession::destroy() {
DBG("AmSession::destroy()\n");
AmSessionContainer::instance()->destroySession(this);
}
string AmSession::getNewId()
{
string AmSession::getNewId() {
struct timeval t;
gettimeofday(&t,NULL);
@ -560,9 +566,57 @@ string AmSession::getNewId()
return id;
}
/* bookkeeping functions - TODO: move to monitoring */
void AmSession::session_started() {
struct timeval now, delta;
unsigned int AmSession::getSessionNum()
{
session_num_mut.lock();
//avg session number
gettimeofday(&now, NULL);
timersub(&now, &avg_last_timestamp, &delta);
avg_session_num += session_num * (delta.tv_sec * 1000000ULL + delta.tv_usec);
avg_last_timestamp = now;
//current session number
session_num++;
//maximum session number
if(session_num > max_session_num) max_session_num = session_num;
//cps average
++avg_cps;
//cps maximum
++max_cps_counter;
timersub(&now, &cps_max_timestamp, &delta);
unsigned long long d_usec = delta.tv_sec * 1000000ULL + delta.tv_usec;
if (delta.tv_sec > 0) {
//more than 1 sec has passed
unsigned long long secavg = ((max_cps_counter * 1000000ULL) + d_usec - 1) / d_usec;
if (max_cps < secavg) {
max_cps = secavg;
}
cps_max_timestamp = now;
max_cps_counter = 0;
}
session_num_mut.unlock();
}
void AmSession::session_stopped() {
struct timeval now, delta;
session_num_mut.lock();
//avg session number
gettimeofday(&now, NULL);
timersub(&now, &avg_last_timestamp, &delta);
avg_session_num += session_num * (delta.tv_sec * 1000000ULL + delta.tv_usec);
avg_last_timestamp = now;
//current session number
session_num--;
session_num_mut.unlock();
}
unsigned int AmSession::getSessionNum() {
unsigned int res = 0;
session_num_mut.lock();
res = session_num;
@ -570,6 +624,88 @@ unsigned int AmSession::getSessionNum()
return res;
}
unsigned int AmSession::getMaxSessionNum() {
unsigned int res = 0;
session_num_mut.lock();
res = max_session_num;
max_session_num = session_num;
session_num_mut.unlock();
return res;
}
unsigned int AmSession::getAvgSessionNum() {
unsigned int res = 0;
struct timeval now, delta;
session_num_mut.lock();
gettimeofday(&now, NULL);
timersub(&now, &avg_last_timestamp, &delta);
avg_session_num += session_num * (delta.tv_sec * 1000000ULL + delta.tv_usec);
timersub(&now, &avg_first_timestamp, &delta);
unsigned long long d_usec = delta.tv_sec * 1000000ULL + delta.tv_usec;
if (!d_usec) {
res = 0;
WARN("zero delta!\n");
} else {
//Round up
res = (unsigned int)((avg_session_num + d_usec - 1) / d_usec);
}
avg_session_num = 0;
avg_last_timestamp = now;
avg_first_timestamp = now;
session_num_mut.unlock();
return res;
}
unsigned int AmSession::getMaxCPS()
{
unsigned int res = 0;
struct timeval now, delta;
session_num_mut.lock();
gettimeofday(&now, NULL);
timersub(&now, &cps_max_timestamp, &delta);
unsigned long long d_usec = delta.tv_sec * 1000000ULL + delta.tv_usec;
if(delta.tv_sec > 0) {
//more than 1 sec has passed
//Round up
unsigned long long secavg = ((max_cps_counter * 1000000ULL) + d_usec - 1) / d_usec;
if (max_cps < secavg) {
max_cps = secavg;
}
cps_max_timestamp = now;
max_cps_counter = 0;
}
res = max_cps;
max_cps = 0;
session_num_mut.unlock();
return res;
}
unsigned int AmSession::getAvgCPS()
{
unsigned int res = 0;
struct timeval now, delta;
unsigned long n_avg_cps;
session_num_mut.lock();
gettimeofday(&now, NULL);
timersub(&now, &cps_first_timestamp, &delta);
cps_first_timestamp = now;
n_avg_cps = avg_cps;
avg_cps = 0;
session_num_mut.unlock();
unsigned long long d_usec = delta.tv_sec * 1000000ULL + delta.tv_usec;
if(!d_usec) {
res = 0;
WARN("zero delta!\n");
} else {
//Round up
res = (unsigned int)(((n_avg_cps * 1000000ULL) + d_usec - 1) / d_usec);
}
return res;
}
void AmSession::setInbandDetector(Dtmf::InbandDetectorType t)
{

@ -138,7 +138,15 @@ private:
AmCondition<bool> sess_stopped;
AmCondition<bool> detached;
static void session_started();
static void session_stopped();
static volatile unsigned int session_num;
static volatile unsigned int max_session_num;
static volatile unsigned long long avg_session_num;
static volatile unsigned long max_cps;
static volatile unsigned long max_cps_counter;
static volatile unsigned long avg_cps;
static AmMutex session_num_mut;
friend class AmMediaProcessor;
@ -402,6 +410,22 @@ public:
* Gets the number of running sessions
*/
static unsigned int getSessionNum();
/**
* Gets the maximum of running sessions since last query
*/
static unsigned int getMaxSessionNum();
/**
* Gets the average of running sessions since last query
*/
static unsigned int getAvgSessionNum();
/**
* Gets the maximum of calls per second since last query
*/
static unsigned int getMaxCPS();
/**
* Gets the timeaverage of calls per second since last query
*/
static unsigned int getAvgCPS();
/**
* Entry point for DTMF events

@ -294,6 +294,10 @@ int StatsUDPServer::execute(char* msg_buf, string& reply,
"get_loglevel - get log level\n"
"set_shutdownmode <1 or 0> - turns on and off shutdown mode\n"
"get_shutdownmode - returns the shutdown mode's current state\n"
"get_callsavg - get number of active calls (average since the last query)\n"
"get_callsmax - get maximum of active calls since the last query\n"
"get_cpsavg - get calls per second (average since the last query)\n"
"get_cpsmax - get maximum of CPS since the last query\n"
"DI <factory> <function> (<args>)* - invoke DI command\n"
"\n"
@ -337,6 +341,15 @@ int StatsUDPServer::execute(char* msg_buf, string& reply,
reply= "loglevel is "+int2str(log_level)+".\n";
}
else if(cmd_str.substr(4, 8) == "callsavg")
reply = "Average active calls: " + int2str(AmSession::getAvgSessionNum()) + "\n";
else if(cmd_str.substr(4, 8) == "callsmax")
reply = "Maximum active calls: " + int2str(AmSession::getMaxSessionNum()) + "\n";
else if(cmd_str.substr(4, 8) == "cpsavg")
reply = "Average calls per second: " + int2str(AmSession::getAvgCPS()) + "\n";
else if(cmd_str.substr(4, 8) == "cpsmax")
reply = "Maximum calls per second: " + int2str(AmSession::getMaxCPS()) + "\n";
else if (cmd_str.substr(4, 12) == "shutdownmode") {
if(AmConfig::ShutdownMode)
{

@ -2,8 +2,9 @@ xmlrpc2di: DI call via XMLRPC
This module makes the Dynamic Invocation (DI) Interfaces exported
by component modules accessible from XMLRPC. Additionaly the builtin
methods "calls", "get_loglevel"/"set_loglevel" and
"get_shutdownmode"/"set_shutdownmode" are implemented.
methods "calls", "get_loglevel"/"set_loglevel",
"get_shutdownmode"/"set_shutdownmode", and access to the statistics counters
(get_callsavg/get_callsmax/get_cpsmax/get_cpsavg) are implemented.
Additionally, it can be used as client to access XMLRPC servers. Applications
can use the DI function newConnection to add a new server entry, and sendRequest

Loading…
Cancel
Save