- simplified logging interface (now works with more than one logger)

- 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-fb5ebe64c474
sayer/1.4-spce2.6
Stefan Sayer 19 years ago
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>

@ -202,7 +202,7 @@ class AmLoggingFacility : public AmPluginFactory
/** will be called on logging messages
*/
virtual void log(int level, const char* fmt, va_list ap) = 0;
virtual void log(int level, const char* msg) = 0;
};
#if __GNUC__ < 3

@ -83,15 +83,19 @@ void log_fac_print(int level, const char* fct, char* file, int line, char* fmt,
{
va_list ap;
char logline[512];
int len;
if(log_hooks.empty()) return;
snprintf(logline, sizeof(logline), "(%i) %s: %s (%s:%i): ",(int)getpid(), level2txt(level), fct, file, line);
strncat(logline, fmt, sizeof(logline));
// file, line etc
len = snprintf(logline, sizeof(logline), "(%i) %s: %s (%s:%i): ",
(int)getpid(), level2txt(level), fct, file, line);
// dbg msg
va_start(ap, fmt);
for(unsigned i=0; i<log_hooks.size(); i++) log_hooks[i]->log(level, logline, ap);
vsnprintf(logline+len, sizeof(logline)-len, fmt, ap);
va_end(ap);
for(unsigned i=0; i<log_hooks.size(); i++) log_hooks[i]->log(level, logline);
}
void register_logging_fac(void* vp)

Loading…
Cancel
Save