mirror of https://github.com/sipwise/sems.git
- added di_log: ring buffer log in memory, dump triggered via DI git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@323 8eb893ce-cfd4-0310-b710-fb5ebe64c474sayer/1.4-spce2.6
parent
f1193e0900
commit
8346c43eed
@ -0,0 +1,77 @@
|
||||
#include "AmPlugIn.h"
|
||||
#include "log.h"
|
||||
#include "DILog.h"
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define MOD_NAME "di_log"
|
||||
|
||||
EXPORT_LOG_FACILITY_FACTORY(DILog, MOD_NAME);
|
||||
EXPORT_PLUGIN_CLASS_FACTORY(DILog, MOD_NAME);
|
||||
|
||||
char DILog::ring_buf[MAX_LINES][MAX_LINE_LEN] = {{0}};
|
||||
int DILog::pos = 0;
|
||||
|
||||
DILog::DILog(const string& name) : AmLoggingFacility(name), AmDynInvokeFactory(name) {
|
||||
}
|
||||
|
||||
DILog* DILog::_instance=0;
|
||||
|
||||
DILog* DILog::instance() {
|
||||
if(_instance == NULL){
|
||||
_instance = new DILog(MOD_NAME);
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
|
||||
int DILog::onLoad() {
|
||||
DBG("DILog logging ring-buffer loaded.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
DILog::~DILog() { }
|
||||
|
||||
void DILog::invoke(const string& method, const AmArgArray& args, AmArgArray& ret) {
|
||||
if(method == "dumplog") {
|
||||
ret.push(dumpLog().c_str());
|
||||
} else if(method == "dumplogtodisk") {
|
||||
dumpLog(args.get(0).asCStr());
|
||||
ret.push("dumped to disk.\n");
|
||||
} else if(method == "help") {
|
||||
ret.push("dumplog\n"
|
||||
"dumplogtodisk <path>\n"
|
||||
);
|
||||
} else throw AmDynInvoke::NotImplemented(method);
|
||||
}
|
||||
|
||||
void DILog::dumpLog(const char* path) {
|
||||
fstream fs(path, ios::out);
|
||||
int start = (pos + 1) % MAX_LINES;
|
||||
for(int i=0; i<MAX_LINES; i++) {
|
||||
fs << ring_buf[(i+start)%MAX_LINES];
|
||||
}
|
||||
}
|
||||
|
||||
string DILog::dumpLog() {
|
||||
stringstream log;
|
||||
|
||||
int start = (pos + 1) % MAX_LINES;
|
||||
for(int i=0; i<MAX_LINES; i++) {
|
||||
log << ring_buf[(i+start)%MAX_LINES];
|
||||
}
|
||||
log << endl;
|
||||
return log.str();
|
||||
}
|
||||
|
||||
void DILog::log(int level, const char* fmt) {
|
||||
strncpy(ring_buf[pos], fmt, sizeof(ring_buf[0]));
|
||||
pos = (pos + 1) % MAX_LINES;
|
||||
}
|
||||
// todo: new() array on load, provide DI for resizing
|
||||
@ -0,0 +1,31 @@
|
||||
#include "AmApi.h"
|
||||
|
||||
#include <string>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define MAX_LINES 1000
|
||||
#define MAX_LINE_LEN 256
|
||||
|
||||
class DILog : public AmLoggingFacility, public AmDynInvoke, public AmDynInvokeFactory
|
||||
{
|
||||
private:
|
||||
void dumpLog(const char* path);
|
||||
string dumpLog();
|
||||
static DILog* _instance;
|
||||
static char ring_buf[MAX_LINES][MAX_LINE_LEN];
|
||||
static int pos;
|
||||
|
||||
public:
|
||||
DILog(const string& name);
|
||||
~DILog();
|
||||
// DI factory
|
||||
AmDynInvoke* getInstance() { return instance(); }
|
||||
// DI API
|
||||
static DILog* instance();
|
||||
void invoke(const string& method, const AmArgArray& args, AmArgArray& ret);
|
||||
|
||||
int onLoad();
|
||||
|
||||
// LF API
|
||||
void log(int level, const char* fmt);
|
||||
};
|
||||
@ -0,0 +1,7 @@
|
||||
plug_in_name = di_log
|
||||
|
||||
module_ldflags =
|
||||
module_cflags =
|
||||
|
||||
COREPATH ?=../../core
|
||||
include $(COREPATH)/plug-in/Makefile.app_module
|
||||
@ -0,0 +1,186 @@
|
||||
di_log Readme
|
||||
-------------
|
||||
The di_log module provides a ring buffer logging facility
|
||||
which on request dumps the ring buffer contents either as
|
||||
result of the DI call or in a file on HD. dumping the ring
|
||||
buffer can be invoked via DI interface (for example remotely
|
||||
from the stats module).
|
||||
|
||||
ring buffer size and string length can be customized at compile
|
||||
time, see DILog.h
|
||||
|
||||
exported functions
|
||||
------------------
|
||||
|
||||
help : return help string
|
||||
|
||||
dumplog : return contents of buffer
|
||||
|
||||
dumplogtodisk(string filename) : dump buffer contents into file
|
||||
|
||||
examples of invocation through query_stats
|
||||
------------------------------------------
|
||||
|
||||
./query_stats -c "DI di_log help"
|
||||
./query_stats -c "DI di_log dumplog"
|
||||
the dump will most probably be truncated due to string length
|
||||
constraint
|
||||
|
||||
./query_stats -c "DI di_log dumplogtodisk log_file.log"
|
||||
|
||||
|
||||
about performance
|
||||
-----------------
|
||||
|
||||
snprintf'ing and vsnprintf'ing all debug messages does consume
|
||||
quite some CPU power, especially on call setup and tear down as
|
||||
there are a lot of debug messages print out.
|
||||
|
||||
for G711 announcement (from file) over loopback interface, the
|
||||
following was measured over 2000 calls using sipp and valgrind:
|
||||
|
||||
call length CPU consumed by logging (log_fac_print, incl)
|
||||
5s 34%
|
||||
1s 58%
|
||||
|
||||
for 50 participants G711 conference, 30s/ call, logging
|
||||
used 16%.
|
||||
|
||||
valgrind command:
|
||||
valgrind --tool=callgrind --instr-atstart=no ./sems -f sems.conf -D 1 -E
|
||||
|
||||
sipp command:
|
||||
conference:
|
||||
sipp -sf sippuac.xml -i 127.0.0.1 \
|
||||
-rtp_echo -m 2000 -l 50 -d 30000 -s 8 127.0.0.1:5060
|
||||
announcement 1s:
|
||||
sipp -sf sippuac.xml -i 127.0.0.1 \
|
||||
-rtp_echo -m 2000 -l 50 -d 1000 -s 7 127.0.0.1:5060
|
||||
announcement 5s:
|
||||
sipp -sf sippuac.xml -i 127.0.0.1 \
|
||||
-rtp_echo -m 2000 -l 50 -d 5000 -s 7 127.0.0.1:5060
|
||||
|
||||
|
||||
sippuac.xml is -sn uac scenario, with 5070 as contact
|
||||
(no target updating from contact implemented in sipp)
|
||||
|
||||
sippuac.xml:
|
||||
---------------------------------------------------------------------------
|
||||
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||
|
||||
<!-- This program is free software; you can redistribute it and/or -->
|
||||
<!-- modify it under the terms of the GNU General Public License as -->
|
||||
<!-- published by the Free Software Foundation; either version 2 of the -->
|
||||
<!-- License, or (at your option) any later version. -->
|
||||
<!-- -->
|
||||
<!-- This program is distributed in the hope that it will be useful, -->
|
||||
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
|
||||
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
|
||||
<!-- GNU General Public License for more details. -->
|
||||
<!-- -->
|
||||
<!-- You should have received a copy of the GNU General Public License -->
|
||||
<!-- along with this program; if not, write to the -->
|
||||
<!-- Free Software Foundation, Inc., -->
|
||||
<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
|
||||
<!-- -->
|
||||
<!-- Sipp default 'uac' scenario. -->
|
||||
<!-- -->
|
||||
|
||||
<scenario name="Basic Sipstone UAC">
|
||||
<!-- In client mode (sipp placing calls), the Call-ID MUST be -->
|
||||
<!-- generated by sipp. To do so, use [call_id] keyword. -->
|
||||
<send retrans="500">
|
||||
<![CDATA[
|
||||
|
||||
INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
|
||||
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
|
||||
To: sut <sip:[service]@[remote_ip]:[remote_port]>
|
||||
Call-ID: [call_id]
|
||||
CSeq: 1 INVITE
|
||||
Contact: sip:sipp@[local_ip]:[local_port]
|
||||
Max-Forwards: 70
|
||||
Subject: Performance Test
|
||||
Content-Type: application/sdp
|
||||
Content-Length: [len]
|
||||
|
||||
v=0
|
||||
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
|
||||
s=-
|
||||
c=IN IP[media_ip_type] [media_ip]
|
||||
t=0 0
|
||||
m=audio [media_port] RTP/AVP 0
|
||||
a=rtpmap:0 PCMU/8000
|
||||
|
||||
]]>
|
||||
</send>
|
||||
|
||||
<recv response="100"
|
||||
optional="true">
|
||||
</recv>
|
||||
|
||||
<recv response="180" optional="true">
|
||||
</recv>
|
||||
|
||||
<recv response="183" optional="true">
|
||||
</recv>
|
||||
|
||||
<!-- By adding rrs="true" (Record Route Sets), the route sets -->
|
||||
<!-- are saved and used for following messages sent. Useful to test -->
|
||||
<!-- against stateful SIP proxies/B2BUAs. -->
|
||||
<recv response="200" rtd="true">
|
||||
</recv>
|
||||
|
||||
<!-- Packet lost can be simulated in any send/recv message by -->
|
||||
<!-- by adding the 'lost = "10"'. Value can be [1-100] percent. -->
|
||||
<send>
|
||||
<![CDATA[
|
||||
|
||||
ACK sip:[service]@[remote_ip]:5070 SIP/2.0
|
||||
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
|
||||
To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
|
||||
Call-ID: [call_id]
|
||||
CSeq: 1 ACK
|
||||
Contact: sip:sipp@[local_ip]:[local_port]
|
||||
Max-Forwards: 70
|
||||
Subject: Performance Test
|
||||
Content-Length: 0
|
||||
|
||||
]]>
|
||||
</send>
|
||||
|
||||
<!-- This delay can be customized by the -d command-line option -->
|
||||
<!-- or by adding a 'milliseconds = "value"' option here. -->
|
||||
<pause/>
|
||||
|
||||
<!-- The 'crlf' option inserts a blank line in the statistics report. -->
|
||||
<send retrans="500">
|
||||
<![CDATA[
|
||||
|
||||
BYE sip:[service]@[remote_ip]:5070 SIP/2.0
|
||||
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
|
||||
To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
|
||||
Call-ID: [call_id]
|
||||
CSeq: 2 BYE
|
||||
Contact: sip:sipp@[local_ip]:[local_port]
|
||||
Max-Forwards: 70
|
||||
Subject: Performance Test
|
||||
Content-Length: 0
|
||||
|
||||
]]>
|
||||
</send>
|
||||
|
||||
<recv response="200" crlf="true">
|
||||
</recv>
|
||||
|
||||
<!-- definition of the response time repartition table (unit is ms) -->
|
||||
<ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
|
||||
|
||||
<!-- definition of the call length repartition table (unit is ms) -->
|
||||
<CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
|
||||
|
||||
</scenario>
|
||||
|
||||
Loading…
Reference in new issue