Commit 8a390c1d authored by Pavel Vainerman's avatar Pavel Vainerman

(Log): добавил LogAgregator для возможности "агрегировать" сразу

несколько DebugStream-ов и (например) подключать их к одному LogServer-у. (Log): добавил в DebugStream возможность задать "название" лога. Для возможности дальнейшего использования при управлении логами.. - добавил возможность задавать команду для конкретного лога (logreader) - сделал, чтобы лог в LogAgregator на экран не выводился
parent d1f6eb74
......@@ -55,12 +55,13 @@ int main( int argc, char* argv[], char* envp[] )
case 0:
{
/* Child. */
close(1); /* Close current stdout. */
dup(cp[1]); /* Make stdout go to write end of pipe. */
close(cp[0]);
// close(0); /* Close current stdin. */
// dup( pc[0]); /* Make stdin come from read end of pipe. */
close( cp[0]);
close( fileno(stderr) ); //close stderr
dup2(fileno(stdout),fileno(stderr));
close(fileno(stdout)); /* Close current stdout. */
dup2(cp[1],fileno(stdout)); /* Make stdout go to write end of pipe. */
execvpe(argv[3], argv + 3, envp);
perror("No exec");
......@@ -89,6 +90,7 @@ int main( int argc, char* argv[], char* envp[] )
ssize_t r = read(cp[0], &buf, sizeof(buf)-1 );
if( r > 0 )
{
cout << "***READ**" << endl;
buf[r] = '\0';
zlog << buf;
}
......
......@@ -21,15 +21,20 @@ static struct option longopts[] = {
{ "off", required_argument, 0, 'o' },
{ "on", required_argument, 0, 'n' },
{ "rotate", required_argument, 0, 'r' },
{ "logname", required_argument, 0, 'l' },
{ "command-only", no_argument, 0, 'b' },
{ NULL, 0, 0, 0 }
};
// --------------------------------------------------------------------------
static void print_help()
{
printf("-h, --help - this message\n");
printf("-v, --verbose - Print all messages to stdout\n");
printf("[-i|--iaddr] addr - ULogServer ip or hostname.\n");
printf("[-p|--port] port - ULogServer port.\n");
printf("-h, --help - this message\n");
printf("-v, --verbose - Print all messages to stdout\n");
printf("[-i|--iaddr] addr - LogServer ip or hostname.\n");
printf("[-p|--port] port - LogServer port.\n");
printf("[-l|--logname] name - Send command only for 'logname'.\n");
printf("[-b|--command-only] - Send command and break. (No read logs).\n");
printf("\n");
printf("Commands:\n");
......@@ -52,10 +57,12 @@ int main( int argc, char **argv )
int cmd = LogServerTypes::cmdNOP;
int data = 0;
string sdata("");
int cmdonly = 0;
string logname("");
try
{
while( (opt = getopt_long(argc, argv, "hva:p:i:d:s:onr",longopts,&optindex)) != -1 )
while( (opt = getopt_long(argc, argv, "hva:p:i:d:s:l:onrb",longopts,&optindex)) != -1 )
{
switch (opt)
{
......@@ -95,6 +102,14 @@ int main( int argc, char **argv )
addr = string(optarg);
break;
case 'l':
logname = string(optarg);
break;
case 'b':
cmdonly = 1;
break;
case 'p':
port = uni_atoi(optarg);
break;
......@@ -118,6 +133,7 @@ int main( int argc, char **argv )
}
LogReader lr;
lr.setCommandOnlyMode(cmdonly);
if( !sdata.empty() )
{
......@@ -127,7 +143,7 @@ int main( int argc, char **argv )
cout << "SEND COMMAND: '" << (LogServerTypes::Command)cmd << " data='" << sdata << "'" << endl;
}
lr.readlogs( addr, port, (LogServerTypes::Command)cmd, data, verb );
lr.readlogs( addr, port, (LogServerTypes::Command)cmd, data, logname, verb );
}
catch( SystemError& err )
{
......
......@@ -5,6 +5,7 @@
#include "UniSetTypes.h"
#include "Exceptions.h"
#include "LogServer.h"
#include "LogAgregator.h"
// --------------------------------------------------------------------------
using namespace UniSetTypes;
using namespace std;
......@@ -36,7 +37,6 @@ int main( int argc, char **argv )
string addr("localhost");
int port = 3333;
int tout = 2000;
DebugStream dlog;
timeout_t delay = 5000;
try
......@@ -78,21 +78,37 @@ int main( int argc, char **argv )
// << " timeout=" << tout << " msec "
<< endl;
dlog.addLevel( Debug::type(Debug::CRIT | Debug::WARN | Debug::INFO) );
// dlog.addLevel( Debug::type(Debug::CRIT | Debug::WARN | Debug::INFO) );
}
LogServer ls(dlog);
DebugStream dlog;
dlog.setLogName("dlog");
DebugStream dlog2;
dlog2.setLogName("dlog2");
LogAgregator la;
la.add(dlog);
la.add(dlog2);
LogServer ls(la);
// LogServer ls(cout);
dlog.addLevel(Debug::ANY);
dlog2.addLevel(Debug::ANY);
ls.run( addr, port, true );
unsigned int i=0;
while( true )
{
dlog << "[" << ++i << "] Test message for log" << endl;
dlog.info() << ": INFO message" << endl;
dlog.warn() << ": WARN message" << endl;
dlog.crit() << ": CRIT message" << endl;
dlog.info() << ": dlog : INFO message" << endl;
dlog.warn() << ": dlog : WARN message" << endl;
dlog.crit() << ": dlog : CRIT message" << endl;
dlog2.info() << ": dlog2: INFO message" << endl;
dlog2.warn() << ": dlog2: WARN message" << endl;
dlog2.crit() << ": dlog2: CRIT message" << endl;
msleep(delay);
}
......
......@@ -32,8 +32,7 @@
</Services>
</UniSet>
<dlog name="dlog"/>
<LogServer name="dlog" port="3333" host="localhost" />
<LogServer name="ulog" port="3335" host="localhost" />
<LogServer name="smplus" port="3333" host="localhost" />
<settings>
<TestProc name="TestProc1"
......
......@@ -228,7 +228,7 @@ AC_CONFIG_FILES([Makefile
src/Services/Makefile
src/Timers/Makefile
src/Various/Makefile
src/LogServer/Makefile
src/Log/Makefile
src/Makefile
include/Makefile
include/modbus/Makefile
......
......@@ -16,6 +16,7 @@
#ifdef UNISET_ENABLE_IO
#include "IOControl.h"
#endif
#include "LogAgregator.h"
#include "LogServer.h"
// --------------------------------------------------------------------------
using namespace std;
......@@ -186,15 +187,13 @@ int main( int argc, const char **argv )
(*it)->start();
#endif
if( run_logserver("ulog",ulog) == 0 )
{
ulog.crit() << "(smemory-plus): run logserver for 'ulog' FAILED" << endl;
return 1;
}
if( run_logserver("dlog",dlog) == 0 )
LogAgregator la;
la.add(ulog);
la.add(dlog);
if( run_logserver("smplus",la) == 0 )
{
dlog.crit() << "(smemory-plus): run logserver for 'dlog' FAILED" << endl;
cerr << "(smemory-plus): run logserver for 'smplus' FAILED" << endl;
return 1;
}
......
......@@ -4,7 +4,6 @@ ulimit -Sc 10000000
START=uniset2-start.sh
${START} -f ./uniset2-smemory-plus --smemory-id SharedMemory --confile test.xml \
--dlog-add-levels any \
--io-name IOControl \
--io-polltime 100 \
--io-s-filter-field io \
......@@ -31,7 +30,8 @@ ${START} -f ./uniset2-smemory-plus --smemory-id SharedMemory --confile test.xml
--mbtcp2-gateway-port 2049 \
--mbtcp2-recv-timeout 200 \
--mbtcp2-force-out 1 \
$*
# --dlog-add-levels any \
# $*
# --add-rtu \
# --rs-dev /dev/cbsideA1 \
# --rs-id RTUExchange \
......
......@@ -92,7 +92,7 @@ public:
DebugStream(char const * f, Debug::type t = Debug::NONE);
///
~DebugStream();
virtual ~DebugStream();
typedef sigc::signal<void,const std::string&> StreamEvent_Signal;
StreamEvent_Signal signal_stream_event();
......@@ -118,7 +118,7 @@ public:
}
/// Sets the debugstreams' logfile to f.
void logFile( const std::string& f );
virtual void logFile( const std::string& f );
inline std::string getLogFile(){ return fname; }
......@@ -199,24 +199,27 @@ public:
std::ostream& pos(int x, int y);
const DebugStream &operator=(const DebugStream& r);
inline void setLogName( const std::string& n ){ logname = n; }
inline std::string getLogName(){ return logname; }
protected:
void sbuf_overflow( const std::string& s );
private:
// private:
/// The current debug level
Debug::type dt;
/// The no-op stream.
std::ostream nullstream;
///
struct debugstream_internal;
struct debugstream_sbuf;
///
debugstream_internal * internal;
debugstream_sbuf * internal_sbuf;
bool show_datetime;
std::string fname;
StreamEvent_Signal s_stream;
std::string logname;
};
#endif
#ifndef LogAgregator_H_
#define LogAgregator_H_
// -------------------------------------------------------------------------
#include <string>
#include <list>
#include "DebugStream.h"
#include "LogServerTypes.h"
// -------------------------------------------------------------------------
class LogAgregator:
public DebugStream
{
public:
explicit LogAgregator( Debug::type t = Debug::NONE );
explicit LogAgregator( char const * f, Debug::type t = Debug::NONE );
virtual ~LogAgregator();
virtual void logFile( const std::string& f );
void add( DebugStream& log );
// Управление "подчинёнными" логами
void addLevel( const std::string& logname, Debug::type t );
void delLevel( const std::string& logname, Debug::type t );
void level( const std::string& logname, Debug::type t );
DebugStream* getLog( const std::string& logname );
protected:
void logOnEvent( const std::string& s );
private:
typedef std::list<DebugStream*> LogList;
LogList llst;
};
// -------------------------------------------------------------------------
#endif // LogAgregator_H_
// -------------------------------------------------------------------------
......@@ -15,10 +15,18 @@ class LogReader
LogReader();
~LogReader();
void readlogs( const std::string& addr, ost::tpport_t port, LogServerTypes::Command c, int data, bool verbose = false );
void readlogs( const std::string& addr, ost::tpport_t port,
LogServerTypes::Command c = LogServerTypes::cmdNOP,
int data = 0,
const std::string& logname="",
bool verbose = false );
void readlogs( const std::string& addr, ost::tpport_t port, LogServerTypes::lsMessage& m, bool verbose = false );
bool isConnection();
inline void setCommandOnlyMode( bool s ){ cmdonly = s; }
protected:
void connect( const std::string& addr, ost::tpport_t port, timeout_t tout=TIMEOUT_INF );
......@@ -29,6 +37,7 @@ class LogReader
UTCPStream* tcp;
std::string iaddr;
ost::tpport_t port;
bool cmdonly;
DebugStream rlog;
};
......
......@@ -3,6 +3,7 @@
#define LogServerTypes_H_
// -------------------------------------------------------------------------
#include <ostream>
#include <cstring>
// -------------------------------------------------------------------------
namespace LogServerTypes
{
......@@ -23,16 +24,21 @@ namespace LogServerTypes
struct lsMessage
{
lsMessage():magic(MAGICNUM),cmd(cmdNOP),data(0){}
lsMessage():magic(MAGICNUM),cmd(cmdNOP),data(0){ std::memset(logname,0,sizeof(logname)); }
unsigned int magic;
Command cmd;
unsigned int data;
static const size_t MAXLOGNAME = 20;
char logname[MAXLOGNAME+1]; // +1 reserverd for '\0'
void setLogName( const std::string& name );
// для команды 'cmdSetLogFile'
// static const short MAXLOGFILENAME = 100;
// char logname[MAXLOGFILENAME];
// static const size_t MAXLOGFILENAME = 200;
// char logfile[MAXLOGFILENAME];
}__attribute__((packed));
std::ostream& operator<<(std::ostream& os, lsMessage& m );
}
// -------------------------------------------------------------------------
......
......@@ -22,4 +22,4 @@ libUniSet2_la_LIBADD = -lm \
$(top_builddir)/src/Services/libServices.la \
$(top_builddir)/src/Timers/libTimers.la \
$(top_builddir)/src/Various/libVarious.la \
$(top_builddir)/src/LogServer/libLogServer.la
$(top_builddir)/src/Log/libLog.la
#include "DebugExtBuf.h"
#include "LogAgregator.h"
// -------------------------------------------------------------------------
LogAgregator::LogAgregator( char const * f, Debug::type t ):
DebugStream(f,t)
{
delete rdbuf(new teebuf(&internal->fbuf,&internal->sbuf));
}
// -------------------------------------------------------------------------
LogAgregator::LogAgregator( Debug::type t ):
DebugStream(t)
{
delete rdbuf(new teebuf(&internal->nbuf,&internal->sbuf));
}
// -------------------------------------------------------------------------
void LogAgregator::logFile( const std::string& f )
{
DebugStream::logFile(f);
if( f.empty() )
delete rdbuf(new teebuf(&internal->fbuf,&internal->sbuf));
else
delete rdbuf(new teebuf(&internal->nbuf,&internal->sbuf));
}
// -------------------------------------------------------------------------
LogAgregator::~LogAgregator()
{
}
// -------------------------------------------------------------------------
void LogAgregator::logOnEvent( const std::string& s )
{
(*this) << s;
}
// -------------------------------------------------------------------------
void LogAgregator::add( DebugStream& l )
{
l.signal_stream_event().connect( sigc::mem_fun(this, &LogAgregator::logOnEvent) );
for( LogList::iterator i=llst.begin(); i!=llst.end(); i++ )
{
if( &l == (*i) )
return;
}
llst.push_back(&l);
}
// -------------------------------------------------------------------------
void LogAgregator::addLevel( const std::string& logname, Debug::type t )
{
for( auto& i: llst )
{
if( i->getLogName() == logname )
{
i->addLevel(t);
break;
}
}
}
// -------------------------------------------------------------------------
void LogAgregator::delLevel( const std::string& logname, Debug::type t )
{
for( auto& i: llst )
{
if( i->getLogName() == logname )
{
i->delLevel(t);
break;
}
}
}
// -------------------------------------------------------------------------
void LogAgregator::level( const std::string& logname, Debug::type t )
{
for( auto& i: llst )
{
if( i->getLogName() == logname )
{
i->level(t);
break;
}
}
}
// -------------------------------------------------------------------------
DebugStream* LogAgregator::getLog( const std::string& logname )
{
if( logname.empty() )
return 0;
for( auto& i: llst )
{
if( i->getLogName() == logname )
return i;
}
return 0;
}
// -------------------------------------------------------------------------
\ No newline at end of file
......@@ -11,7 +11,8 @@ using namespace UniSetTypes;
// -------------------------------------------------------------------------
LogReader::LogReader():
tcp(0),
iaddr("")
iaddr(""),
cmdonly(false)
{
}
......@@ -102,7 +103,16 @@ bool LogReader::isConnection()
return tcp && tcp->isConnected();
}
// -------------------------------------------------------------------------
void LogReader::readlogs( const std::string& _addr, ost::tpport_t _port, LogServerTypes::Command cmd, int data, bool verbose )
void LogReader::readlogs( const std::string& _addr, ost::tpport_t _port, LogServerTypes::Command cmd, int data, const std::string& logname, bool verbose )
{
LogServerTypes::lsMessage msg;
msg.cmd = cmd;
msg.data = data;
msg.setLogName(logname);
readlogs(_addr,_port,msg,verbose );
}
// -------------------------------------------------------------------------
void LogReader::readlogs( const std::string& _addr, ost::tpport_t _port, LogServerTypes::lsMessage& msg, bool verbose )
{
timeout_t inTimeout = 10000;
timeout_t outTimeout = 6000;
......@@ -126,15 +136,15 @@ void LogReader::readlogs( const std::string& _addr, ost::tpport_t _port, LogServ
continue;
}
if( !send_ok && cmd != LogServerTypes::cmdNOP )
if( !send_ok && msg.cmd != LogServerTypes::cmdNOP )
{
if( tcp->isPending(ost::Socket::pendingOutput,outTimeout) )
{
rlog.info() << "** send command: '" << cmd << "' data='" << data << "'" << endl;
rlog.info() << "** send command: logname='" << msg.logname << "' cmd='" << msg.cmd << "' data='" << msg.data << "'" << endl;
LogServerTypes::lsMessage msg;
msg.cmd = cmd;
msg.data = data;
// LogServerTypes::lsMessage msg;
// msg.cmd = cmd;
// msg.data = data;
for( size_t i=0; i<sizeof(msg); i++ )
(*tcp) << ((unsigned char*)(&msg))[i];
......@@ -142,10 +152,13 @@ void LogReader::readlogs( const std::string& _addr, ost::tpport_t _port, LogServ
send_ok = true;
}
else
rlog.warn() << "**** SEND COMMAND ('" << cmd << "' FAILED!" << endl;
rlog.warn() << "**** SEND COMMAND ('" << msg.cmd << "' FAILED!" << endl;
if( cmdonly )
return;
}
while( tcp->isPending(ost::Socket::pendingInput,inTimeout) )
while( !cmdonly && tcp->isPending(ost::Socket::pendingInput,inTimeout) )
{
int n = tcp->peek( buf,sizeof(buf)-1 );
if( n > 0 )
......
......@@ -37,3 +37,10 @@ std::ostream& LogServerTypes::operator<<(std::ostream& os, LogServerTypes::lsMes
return os << " magic=" << m.magic << " cmd=" << m.cmd << " data=" << m.data;
}
// -------------------------------------------------------------------------
void LogServerTypes::lsMessage::setLogName( const std::string& name )
{
size_t s = name.size()> MAXLOGNAME ? MAXLOGNAME : name.size();
memcpy( &logname, name.c_str(), s );
logname[s] = '\0';
}
// -------------------------------------------------------------------------
......@@ -8,6 +8,7 @@
#include "LogSession.h"
#include "UniSetTypes.h"
#include "LogServerTypes.h"
#include "LogAgregator.h"
// -------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
......@@ -82,47 +83,60 @@ void LogSession::run()
{
slog.info() << peername << "(run): receive command: '" << msg.cmd << "'" << endl;
// Обработка команд..
// \warning Работа с логом ведётся без mutex-а, хотя он разделяется отдельными потоками
switch( msg.cmd )
string cmdLogName(msg.logname);
DebugStream* cmdlog = 0;
if( !cmdLogName.empty () )
{
LogAgregator* lag = dynamic_cast<LogAgregator*>(log);
cmdlog = lag ? lag->getLog( cmdLogName ) : log;
}
// обрабатываем команды только если нашли log
if( cmdlog )
{
case LogServerTypes::cmdSetLevel:
log->level( (Debug::type)msg.data );
break;
case LogServerTypes::cmdAddLevel:
log->addLevel((Debug::type)msg.data );
break;
case LogServerTypes::cmdDelLevel:
log->delLevel( (Debug::type)msg.data );
break;
case LogServerTypes::cmdRotate:
{
string lfile( log->getLogFile() );
if( !lfile.empty() )
log->logFile(lfile);
}
break;
case LogServerTypes::cmdOffLogFile:
{
string lfile( log->getLogFile() );
if( !lfile.empty() )
log->logFile("");
}
break;
case LogServerTypes::cmdOnLogFile:
{
if( !oldLogFile.empty() && oldLogFile != log->getLogFile() )
log->logFile(oldLogFile);
}
break;
default:
slog.warn() << peername << "(run): Unknown command '" << msg.cmd << "'" << endl;
break;
}
// Обработка команд..
// \warning Работа с логом ведётся без mutex-а, хотя он разделяется отдельными потоками
switch( msg.cmd )
{
case LogServerTypes::cmdSetLevel:
cmdlog->level( (Debug::type)msg.data );
break;
case LogServerTypes::cmdAddLevel:
cmdlog->addLevel((Debug::type)msg.data );
break;
case LogServerTypes::cmdDelLevel:
cmdlog->delLevel( (Debug::type)msg.data );
break;
case LogServerTypes::cmdRotate:
{
string lfile( cmdlog->getLogFile() );
if( !lfile.empty() )
cmdlog->logFile(lfile);
}
break;
case LogServerTypes::cmdOffLogFile:
{
string lfile( cmdlog->getLogFile() );
if( !lfile.empty() )
cmdlog->logFile("");
}
break;
case LogServerTypes::cmdOnLogFile:
{
if( !oldLogFile.empty() && oldLogFile != cmdlog->getLogFile() )
cmdlog->logFile(oldLogFile);
}
break;
default:
slog.warn() << peername << "(run): Unknown command '" << msg.cmd << "'" << endl;
break;
}
}
}
}
}
......
############################################################################
# This file is part of the UniSet library #
############################################################################
noinst_LTLIBRARIES = libLog.la
libLog_la_CPPFLAGS = $(SIGC_CFLAGS) $(COMCPP_CFLAGS)
libLog_la_LIBADD = $(SIGC_LIBS) $(COMCPP_LIBS)
libLog_la_SOURCES = DebugStream.cc Debug.cc LogServerTypes.cc LogServer.cc LogSession.cc LogReader.cc LogAgregator.cc
############################################################################
# This file is part of the UniSet library #
############################################################################
noinst_LTLIBRARIES = libLogServer.la
libLogServer_la_CPPFLAGS = $(SIGC_CFLAGS) $(COMCPP_CFLAGS)
libLogServer_la_LIBADD = $(SIGC_LIBS) $(COMCPP_LIBS)
libLogServer_la_SOURCES = LogServerTypes.cc LogServer.cc LogSession.cc LogReader.cc
......@@ -2,5 +2,5 @@
# This file is part of the UniSet library #
############################################################################
SUBDIRS=ObjectRepository Processes Interfaces Timers Services Various Communications LogServer
SUBDIRS=ObjectRepository Processes Interfaces Timers Services Various Communications Log
......@@ -701,7 +701,10 @@ xmlNode* Configuration::initDebug( DebugStream& deb, const string& _debname )
else
{
if( !getProp(dnode,"name").empty() )
{
debname = getProp(dnode,"name");
deb.setLogName(debname);
}
}
string no_deb("--"+debname+"-no-debug");
......@@ -978,6 +981,7 @@ UniversalIO::IOType Configuration::getIOType( const std::string& name )
void uniset_init( int argc, const char* const* argv, const std::string& xmlfile )
{
string confile = UniSetTypes::getArgParam( "--confile", argc, argv, xmlfile );
ulog.setLogName("ulog");
UniSetTypes::conf = new Configuration(argc, argv, confile);
}
// -------------------------------------------------------------------------
......
......@@ -5,7 +5,7 @@
noinst_LTLIBRARIES = libVarious.la
libVarious_la_CPPFLAGS = $(SIGC_CFLAGS) $(COMCPP_CFLAGS)
libVarious_la_LIBADD = $(SIGC_LIBS) $(COMCPP_LIBS)
libVarious_la_SOURCES = DebugStream.cc Debug.cc UniXML.cc MessageType.cc Configuration.cc \
libVarious_la_SOURCES = UniXML.cc MessageType.cc Configuration.cc \
Restorer_XML.cc RunLock.cc Mutex.cc SViewer.cc SMonitor.cc LT_Object.cc WDTInterface.cc
local-clean:
......
#include <time.h>
#include "Debug.h"
#include "UniSetTypes.h"
#include "LogAgregator.h"
using namespace std;
using namespace UniSetTypes;
std::ostringstream ss;
std::ostringstream ss1;
void check_log_signal( const string& s )
{
ss << s;
}
void check_alog_signal( const string& s )
{
ss1 << s;
}
int main( int argc, const char **argv )
{
DebugStream tlog;
......@@ -30,9 +37,31 @@ int main( int argc, const char **argv )
if( tlog.is_level1() )
tlog.level1() << ": is level1..." << endl;
cout << "==================" << endl;
cout << "===== Test 1 =====" << endl;
cout << ss.str();
cout << "==================" << endl;
DebugStream log1;
log1.setLogName("log1");
DebugStream log2;
log2.setLogName("log2");
LogAgregator la;
la.signal_stream_event().connect(&check_alog_signal);
la.add(log1);
la.add(log2);
log1 << "log1: test message..." << endl;
log2 << "log2: test message..." << endl;
la << "la: test message.." << endl;
cout << "===== Test 2 =====" << endl;
cout << ss1.str();
cout << "==================" << endl;
DebugStream* l = la.getLog("log1");
if( l != &log1 )
cout << "**** TEST FAILED: LogAgregator::getLog() " << endl;
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment