Browse Source

RTPENGINE-1_total_statistics_rectl.patch:

Neues rectl kommando list totals, mit dem man sich die totalen
statistiken ausgeben kann

Author:    Frederic-Philippe Metz <Frederic.Metz@1und1.de>
pull/60/head
Frederic-Philippe Metz 11 years ago
committed by Richard Fuchs
parent
commit
4882d917ba
5 changed files with 169 additions and 14 deletions
  1. +100
    -14
      daemon/call.c
  2. +15
    -0
      daemon/call.h
  3. +50
    -0
      daemon/cli.c
  4. +3
    -0
      daemon/main.c
  5. +1
    -0
      utils/rtpengine-ctl

+ 100
- 14
daemon/call.c View File

@ -438,7 +438,7 @@ void kernelize(struct packet_stream *stream) {
PS_SET(stream, KERNELIZED);
return;
no_kernel_warn:
ilog(LOG_WARNING, "No support for kernel packet forwarding available");
no_kernel:
@ -1036,6 +1036,8 @@ static void call_timer_iterator(void *key, void *val, void *ptr) {
rwlock_lock_r(&c->master_lock);
log_info_call(c);
cm = c->callmaster;
if (c->deleted && poller_now >= c->deleted
&& c->last_signal <= c->deleted)
goto delete;
@ -1048,8 +1050,6 @@ static void call_timer_iterator(void *key, void *val, void *ptr) {
if (!c->streams)
goto drop;
cm = c->callmaster;
for (it = c->streams; it; it = it->next) {
ps = it->data;
mutex_lock(&ps->in_lock);
@ -2338,16 +2338,36 @@ static void unkernelize(struct packet_stream *p) {
void timeval_subtract (struct timeval *result, const struct timeval *a, const struct timeval *b) {
long microseconds=0;
microseconds = ((long)a->tv_sec - (long)b->tv_sec) * 1000000 + ((long)a->tv_usec - (long)b->tv_usec);
result->tv_sec = microseconds/(long)1000000;
result->tv_usec = microseconds%(long)1000000;
}
microseconds = (a->tv_sec - b->tv_sec) * 1000000 + ((long)a->tv_usec - (long)b->tv_usec);
result->tv_sec = microseconds/1000000;
result->tv_usec = microseconds%1000000;
void timeval_multiply(struct timeval *result, const struct timeval *a, const long multiplier) {
long microseconds=0;
microseconds = (((long)a->tv_sec * 1000000) + (long)a->tv_usec) * multiplier;
result->tv_sec = microseconds/(long)1000000;
result->tv_usec = microseconds%(long)1000000;
}
void timeval_devide(struct timeval *result, const struct timeval *a, const long devisor) {
long microseconds=0;
microseconds = (((long)a->tv_sec * 1000000) + (long)a->tv_usec) / devisor;
result->tv_sec = microseconds/(long)1000000;
result->tv_usec = microseconds%(long)1000000;
}
void timeval_add(struct timeval *result, const struct timeval *a, const struct timeval *b) {
long microseconds=0;
microseconds = ((long)a->tv_sec + (long)b->tv_sec) * (long)1000000 + ((long)a->tv_usec + (long)b->tv_usec);
result->tv_sec = microseconds/(long)1000000;
result->tv_usec = microseconds%(long)1000000;
}
/* called lock-free, but must hold a reference to the call */
void call_destroy(struct call *c) {
struct callmaster *m = c->callmaster;
struct packet_stream *ps;
struct packet_stream *ps=0, *ps2=0;
struct stream_fd *sfd;
struct poller *p = m->poller;
GSList *l;
@ -2356,13 +2376,15 @@ void call_destroy(struct call *c) {
struct call_media *md;
GList *k, *o;
char buf[64];
struct timeval tim_result;
struct timeval tim_result_duration;
static const int CDRBUFLENGTH = 4096*2;
char reasonbuf[16]; memset(&reasonbuf,0,16);
char tagtypebuf[16]; memset(&tagtypebuf,0,16);
char cdrbuffer[CDRBUFLENGTH]; memset(&cdrbuffer,0,CDRBUFLENGTH);
char* cdrbufcur = cdrbuffer;
int cdrlinecnt = 0;
char cdrbuffer[CDRBUFLENGTH]; memset(&cdrbuffer,0,CDRBUFLENGTH);
char* cdrbufcur = cdrbuffer;
int cdrlinecnt = 0;
int found = 0;
//char tmpstreampairstatus[2]; memset(&tmpstreampairstatus,0,2);
rwlock_lock_w(&m->hashlock);
ret = g_hash_table_remove(m->callhash, &c->callid);
@ -2386,8 +2408,8 @@ void call_destroy(struct call *c) {
for (l = c->monologues; l; l = l->next) {
ml = l->data;
if (_log_facility_cdr) {
memset(&tim_result,0,sizeof(struct timeval));
timeval_subtract(&tim_result,&ml->terminated,&ml->started);
memset(&tim_result_duration,0,sizeof(struct timeval));
timeval_subtract(&tim_result_duration,&ml->terminated,&ml->started);
cdrbufcur += sprintf(cdrbufcur, "ml%i_start_time=%ld.%06lu, "
"ml%i_end_time=%ld.%06ld, "
"ml%i_duration=%ld.%06ld, "
@ -2397,7 +2419,7 @@ void call_destroy(struct call *c) {
"ml%i_remote_tag=%s, ",
cdrlinecnt, ml->started.tv_sec, ml->started.tv_usec,
cdrlinecnt, ml->terminated.tv_sec, ml->terminated.tv_usec,
cdrlinecnt, tim_result.tv_sec, tim_result.tv_usec,
cdrlinecnt, tim_result_duration.tv_sec, tim_result_duration.tv_usec,
cdrlinecnt, get_term_reason_text(reasonbuf,ml->term_reason),
cdrlinecnt, ml->tag.s,
cdrlinecnt, get_tag_type_text(tagtypebuf,ml->tagtype),
@ -2449,12 +2471,76 @@ void call_destroy(struct call *c) {
(unsigned long long) ps->stats.packets,
(unsigned long long) ps->stats.bytes,
(unsigned long long) ps->stats.errors);
m->totalstats.total_relayed_packets += (unsigned long long) ps->stats.packets;
m->totalstats.total_relayed_errors += (unsigned long long) ps->stats.errors;
}
}
if (_log_facility_cdr)
++cdrlinecnt;
}
// --- for statistics getting one way stream or no relay at all
m->totalstats.total_nopacket_relayed_sess *= 2;
for (l = c->monologues; l; l = l->next) {
ml = l->data;
// --- go through partner ml and search the RTP
for (k = ml->medias.head; k; k = k->next) {
md = k->data;
for (o = md->streams.head; o; o = o->next) {
ps = o->data;
if ((PS_ISSET(ps, RTP) && !PS_ISSET(ps, RTCP))) {
// --- only RTP is interesting
found = 1;
break;
}
}
if (found) { break; }
}
found = 0;
// --- go through partner ml and search the RTP
for (k = ml->active_dialogue->medias.head; k; k = k->next) {
md = k->data;
for (o = md->streams.head; o; o = o->next) {
ps2 = o->data;
if ((PS_ISSET(ps2, RTP) && !PS_ISSET(ps2, RTCP))) {
// --- only RTP is interesting
found = 1;
break;
}
}
if (found) { break; }
}
if (ps && ps2 && ps->stats.packets!=0 && ps2->stats.packets==0)
m->totalstats.total_oneway_stream_sess++;
if (ps && ps2 && ps->stats.packets==0 && ps2->stats.packets==0)
m->totalstats.total_nopacket_relayed_sess++;
}
m->totalstats.total_nopacket_relayed_sess /= 2;
m->totalstats.total_managed_sess += 1;
ml = c->monologues->data;
if (ml->term_reason==TIMEOUT) {
m->totalstats.total_timeout_sess++;
} else if (ml->term_reason==SILENT_TIMEOUT) {
m->totalstats.total_silent_timeout_sess++;
} else if (ml->term_reason==REGULAR) {
m->totalstats.total_regular_term_sess++;
} else if (ml->term_reason==FORCED) {
m->totalstats.total_forced_term_sess++;
}
timeval_multiply(&m->totalstats.total_average_call_dur,&m->totalstats.total_average_call_dur,m->totalstats.total_managed_sess-1);
timeval_add(&m->totalstats.total_average_call_dur,&m->totalstats.total_average_call_dur,&tim_result_duration);
timeval_devide(&m->totalstats.total_average_call_dur,&m->totalstats.total_average_call_dur,m->totalstats.total_managed_sess);
if (_log_facility_cdr)
/* log it */
cdrlog(cdrbuffer);


+ 15
- 0
daemon/call.h View File

@ -192,6 +192,20 @@ struct stats {
u_int64_t errors;
};
struct totalstats {
time_t started;
u_int64_t total_managed_sess;
u_int64_t total_timeout_sess;
u_int64_t total_silent_timeout_sess;
u_int64_t total_regular_term_sess;
u_int64_t total_forced_term_sess;
u_int64_t total_relayed_packets;
u_int64_t total_relayed_errors;
u_int64_t total_nopacket_relayed_sess;
u_int64_t total_oneway_stream_sess;
struct timeval total_average_call_dur;
};
struct udp_fd {
int fd;
u_int16_t localport;
@ -395,6 +409,7 @@ struct callmaster {
struct stats statsps; /* per second stats, running timer */
mutex_t statslock;
struct stats stats; /* copied from statsps once a second */
struct totalstats totalstats;
struct poller *poller;
pcre *info_re;


+ 50
- 0
daemon/cli.c View File

@ -23,6 +23,34 @@ static const char* TRUNCATED = " ... Output truncated. Increase Output Buffer
truncate_output(replybuffer); \
replybuffer += (printlen>=outbufend-replybuffer)?outbufend-replybuffer:printlen; } while (0);
static void cli_incoming_list_totals(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) {
int printlen=0;
printlen = snprintf(replybuffer,(outbufend-replybuffer), "\nTotal statistics (does not include current running sessions):\n\n");
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Uptime of rtpengine :%llu seconds\n", (unsigned long long)time(NULL)-m->totalstats.started);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total managed sessions :%llu\n", (unsigned long long)m->totalstats.total_managed_sess);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total timed-out sessions via TIMEOUT :%llu\n",(unsigned long long)m->totalstats.total_timeout_sess);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total timed-out sessions via SILENT_TIMEOUT :%llu\n",(unsigned long long)m->totalstats.total_silent_timeout_sess);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total regular terminated sessions :%llu\n",(unsigned long long)m->totalstats.total_regular_term_sess);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total forced terminated sessions :%llu\n",(unsigned long long)m->totalstats.total_forced_term_sess);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total relayed packets :%llu\n",(unsigned long long)m->totalstats.total_relayed_packets);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total relayed packet errors :%llu\n",(unsigned long long)m->totalstats.total_relayed_errors);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total number of streams with no relayed packets :%llu\n", (unsigned long long)m->totalstats.total_nopacket_relayed_sess);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total number of 1-way streams :%llu\n",(unsigned long long)m->totalstats.total_oneway_stream_sess);
ADJUSTLEN(printlen,outbufend,replybuffer);
printlen = snprintf(replybuffer,(outbufend-replybuffer), " Average call duration :%ld.%06ld\n\n",m->totalstats.total_average_call_dur.tv_sec,m->totalstats.total_average_call_dur.tv_usec);
ADJUSTLEN(printlen,outbufend,replybuffer);
}
static void cli_incoming_list_callid(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) {
str callid;
struct call* c=0;
@ -106,6 +134,7 @@ static void cli_incoming_list(char* buffer, int len, struct callmaster* m, char*
static const char* LIST_NUMSESSIONS = "numsessions";
static const char* LIST_SESSIONS = "sessions";
static const char* LIST_SESSION = "session";
static const char* LIST_TOTALS = "totals";
if (len<=1) {
printlen = snprintf(replybuffer, outbufend-replybuffer, "%s\n", "More parameters required.");
@ -137,6 +166,8 @@ static void cli_incoming_list(char* buffer, int len, struct callmaster* m, char*
rwlock_unlock_r(&m->hashlock);
} else if (len>=strlen(LIST_SESSION) && strncmp(buffer,LIST_SESSION,strlen(LIST_SESSION)) == 0) {
cli_incoming_list_callid(buffer+strlen(LIST_SESSION), len-strlen(LIST_SESSION), m, replybuffer, outbufend);
} else if (len>=strlen(LIST_TOTALS) && strncmp(buffer,LIST_TOTALS,strlen(LIST_TOTALS)) == 0) {
cli_incoming_list_totals(buffer+strlen(LIST_TOTALS), len-strlen(LIST_TOTALS), m, replybuffer, outbufend);
} else {
printlen = snprintf(replybuffer, outbufend-replybuffer, "%s:%s\n", "Unknown 'list' command", buffer);
ADJUSTLEN(printlen,outbufend,replybuffer);
@ -149,6 +180,8 @@ static void cli_incoming_terminate(char* buffer, int len, struct callmaster* m,
int printlen=0;
GHashTableIter iter;
gpointer key, value;
struct call_monologue *ml;
GSList *i;
if (len<=1) {
printlen = snprintf(replybuffer, outbufend-replybuffer, "%s\n", "More parameters required.");
@ -165,6 +198,14 @@ static void cli_incoming_terminate(char* buffer, int len, struct callmaster* m,
g_hash_table_iter_next (&iter, &key, &value);
c = (struct call*)value;
if (!c) continue;
if (!c->ml_deleted) {
for (i = c->monologues; i; i = i->next) {
ml = i->data;
memset(&ml->terminated,0,sizeof(struct timeval));
gettimeofday(&(ml->terminated), NULL);
ml->term_reason = FORCED;
}
}
call_destroy(c);
}
ilog(LOG_INFO,"All calls terminated by operator.");
@ -181,6 +222,15 @@ static void cli_incoming_terminate(char* buffer, int len, struct callmaster* m,
ADJUSTLEN(printlen,outbufend,replybuffer);
return;
}
if (!c->ml_deleted) {
for (i = c->monologues; i; i = i->next) {
ml = i->data;
memset(&ml->terminated,0,sizeof(struct timeval));
gettimeofday(&(ml->terminated), NULL);
ml->term_reason = FORCED;
}
}
call_destroy(c);
printlen = snprintf(replybuffer, outbufend-replybuffer, "\nCall Id (%s) successfully terminated by operator.\n\n",termparam.s);


+ 3
- 0
daemon/main.c View File

@ -665,6 +665,9 @@ no_kernel:
ctx->m->conf = mc;
callmaster_config_init(ctx->m);
ZERO(ctx->m->totalstats);
ctx->m->totalstats.started = time(NULL);
if (!foreground)
daemonize();
wpidfile();


+ 1
- 0
utils/rtpengine-ctl View File

@ -18,6 +18,7 @@ showusage() {
echo " numsessions : prints the number of sessions"
echo " sessions : print one-liner session information"
echo " session <callid> : print detail about one session"
echo " totals : print total statistics (does not include current sessions)"
echo ""
echo " terminate [ all | <callid> ]"
echo " all : terminates all current sessions"


Loading…
Cancel
Save