Commit de16881f authored by Pavel Vainerman's avatar Pavel Vainerman

(LogAgregator): первая часть переделок, для внедрения возможности

следить за отдельными.. указанными логами. - изменён внутренний формат хранения информации об управляемых логах - изменён формат вывода списка (на экран) - добавлен вывод информации о текущих включённых уровнях каждого лога (thank`s hd@nio14)
parent 458d94ba
......@@ -92,7 +92,6 @@ int main( int argc, char** argv )
}
auto la = make_shared<LogAgregator>("la");
cerr << "create LogAgregator: " << la->getLogName() << endl;
auto dlog = make_shared<DebugStream>();
dlog->setLogName("dlog");
......@@ -116,13 +115,10 @@ int main( int argc, char** argv )
auto la2 = make_shared<LogAgregator>("la2");
cerr << "create LogAgregator: " << la2->getLogName() << endl;
auto dlog3 = la2->create("dlog3");
auto dlog4 = la2->create("dlog4");
la->add(la2);
if( la->getLog("la2/dlog3") == nullptr )
{
cerr << "Not found 'la2/dlog3'" << endl;
......@@ -130,6 +126,21 @@ int main( int argc, char** argv )
}
auto la3 = make_shared<LogAgregator>("la3");
auto dlog5 = la3->create("dlog5");
auto dlog6 = la3->create("dlog6");
la->add(la3);
#if 0
cout << la << endl;
cout << "************ " << endl;
auto lst = la->getLogList();
for( const auto& l: lst )
cout << l.name << endl;
return 0;
#endif
LogServer ls(la);
ls.setMaxSessionCount(msess);
......
......@@ -96,6 +96,8 @@ struct Debug
static void showTags(std::ostream& o);
friend std::ostream& operator<<(std::ostream& os, Debug::type level );
static std::string str( Debug::type level );
};
......
......@@ -136,6 +136,18 @@ class DebugStream : public std::ostream
return fname;
}
// имя лог файла можно установить отдельно, но не вклчать запись..
inline void setLogFile( const std::string& n ){ fname = n; }
// включена ли запись лог-файла
inline bool isOnLogFile(){ return isWriteLogFile; }
// включить запись лог файла
inline void onLogFile( bool truncate=false ){ logFile(fname,truncate); }
// отключить запись логфайла
inline void offLogFile(){ logFile(""); }
/// Returns true if t is part of the current debug level.
inline bool debugging(Debug::type t = Debug::ANY) const
{
......@@ -258,6 +270,8 @@ class DebugStream : public std::ostream
StreamEvent_Signal s_stream;
std::string logname;
bool isWriteLogFile = { false };
};
#endif
......@@ -4,6 +4,7 @@
#include <string>
#include <memory>
#include <list>
#include <vector>
#include <unordered_map>
#include "DebugStream.h"
#include "LogServerTypes.h"
......@@ -110,7 +111,7 @@ class LogAgregator:
{
public:
const std::string sep={"/"}; /*< раздедитель для имён подчинённых агрегаторов */
const std::string sep= {"/"}; /*< раздедитель для имён подчинённых агрегаторов */
explicit LogAgregator( const std::string& name, Debug::type t );
explicit LogAgregator( const std::string& name="" );
......@@ -128,38 +129,48 @@ class LogAgregator:
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 );
void offLogFile( const std::string& logname );
void onLogFile( const std::string& logname );
struct LogInfo
{
LogInfo(): log(0), logfile(""),logname("") {}
LogInfo( std::shared_ptr<DebugStream>& l, const std::string& lname="" ):
log(l), logfile(l->getLogFile()),logname(lname.empty()?l->getLogName():lname) {}
std::shared_ptr<DebugStream> getLog( const std::string& logname );
friend std::ostream& operator<<(std::ostream& os, LogAgregator& la );
friend std::ostream& operator<<(std::ostream& os, std::shared_ptr<LogAgregator> la );
static std::vector<std::string> split_first( const std::string& lname, const std::string s = "/" );
struct iLog
{
iLog( std::shared_ptr<DebugStream>& l, const std::string& nm ):log(l),name(nm){}
std::shared_ptr<DebugStream> log;
std::string logfile;
std::string logname;
std::string name;
// для сортировки "по алфавиту"
inline bool operator < ( const LogInfo& r ) const
inline bool operator < ( const iLog& r ) const
{
return logname < r.logname;
return name < r.name;
}
};
std::shared_ptr<DebugStream> getLog( const std::string& logname );
LogInfo getLogInfo( const std::string& logname );
std::list<LogInfo> getLogList();
std::list<LogInfo> getLogList( const std::string& regexp_str );
std::list<iLog> getLogList();
std::list<iLog> getLogList( const std::string& regexp_str );
protected:
void logOnEvent( const std::string& s );
void addLog( std::shared_ptr<DebugStream> l, const std::string& lname );
void addLogAgregator( std::shared_ptr<LogAgregator> la, const std::string& lname );
// поиск лога по составному логу.."agregator/agregator2/.../logname"
std::shared_ptr<DebugStream> findLog( const std::string& lname );
// вывод в виде "дерева"
std::ostream& print_tree(std::ostream& os, const std::string& g_tab="");
// получить список с именами (длинными) и с указателями на логи
std::list<iLog> makeLogNameList( const std::string& prefix );
private:
typedef std::unordered_map<std::string, LogInfo> LogMap;
typedef std::unordered_map<std::string,std::shared_ptr<DebugStream>> LogMap;
LogMap lmap;
};
// -------------------------------------------------------------------------
......
......@@ -13,6 +13,7 @@
#endif
#include <iomanip>
#include <sstream>
#include "Debug.h"
//#include "gettext.h"
......@@ -109,7 +110,6 @@ void Debug::showLevel(ostream& o, Debug::type level)
<< "' (" << errorTags[i].desc << ')' << endl;
}
void Debug::showTags(ostream& os)
{
for (int i = 0 ; i < numErrorTags ; ++i)
......@@ -132,5 +132,35 @@ std::ostream& operator<<(std::ostream& os, Debug::type level )
return os << "???Debuglevel"; // << "(" << int(level) << ")";
}
std::string Debug::str( Debug::type level )
{
if( level == Debug::NONE )
return "NONE";
if( level == Debug::ANY )
return "ANY";
std::ostringstream s;
bool first = true;
for (int i = 0 ; i < numErrorTags ; ++i)
{
if (errorTags[i].level != Debug::ANY
&& errorTags[i].level != Debug::NONE
&& errorTags[i].level & level)
{
if( first )
{
first = false;
s << errorTags[i].name;
}
else
s << "," << errorTags[i].name;
}
}
return s.str();
}
//DebugStream ulog;
......@@ -105,8 +105,11 @@ const DebugStream& DebugStream::operator=( const DebugStream& r )
/// Sets the debugstreams' logfile to f.
void DebugStream::logFile( const std::string& f, bool truncate )
{
if( !f.empty() && f != fname )
fname = f;
isWriteLogFile = !f.empty();
if( internal )
{
internal->fbuf.close();
......
#include <memory>
#include <iomanip>
#include <regex>
#include <sstream>
#include "DebugExtBuf.h"
#include "LogAgregator.h"
// -------------------------------------------------------------------------
using namespace std;
// -------------------------------------------------------------------------
LogAgregator::LogAgregator( const std::string& name ):
LogAgregator(name,Debug::NONE)
LogAgregator(name,Debug::ANY)
{
}
// ------------------------------------------------------------------------
......@@ -77,6 +80,8 @@ void LogAgregator::addLogAgregator( std::shared_ptr<LogAgregator> la, const std:
if( i != lmap.end() )
return;
addLog(la,lname);
#if 0
auto lst = la->getLogList();
for( auto&& l: lst )
{
......@@ -94,6 +99,7 @@ void LogAgregator::addLogAgregator( std::shared_ptr<LogAgregator> la, const std:
addLog(l.log,s.str());
}
}
#endif
}
// ------------------------------------------------------------------------
void LogAgregator::addLog( std::shared_ptr<DebugStream> l, const std::string& lname )
......@@ -110,7 +116,7 @@ void LogAgregator::addLog( std::shared_ptr<DebugStream> l, const std::string& ln
// иначе будет дублироваие при выводе потом (на экран)
for( const auto& i : lmap )
{
if( i.second.log == l )
if( i.second == l )
{
have = true;
break;
......@@ -120,8 +126,7 @@ void LogAgregator::addLog( std::shared_ptr<DebugStream> l, const std::string& ln
if( !have )
l->signal_stream_event().connect( sigc::mem_fun(this, &LogAgregator::logOnEvent) );
LogInfo li(l,lname);
lmap[lname] = li;
lmap[lname] = l;
}
// ------------------------------------------------------------------------
void LogAgregator::addLevel( const std::string& logname, Debug::type t )
......@@ -129,7 +134,7 @@ void LogAgregator::addLevel( const std::string& logname, Debug::type t )
auto i = lmap.find(logname);
if( i != lmap.end() )
i->second.log->addLevel(t);
i->second->addLevel(t);
}
// -------------------------------------------------------------------------
void LogAgregator::delLevel( const std::string& logname, Debug::type t )
......@@ -137,7 +142,7 @@ void LogAgregator::delLevel( const std::string& logname, Debug::type t )
auto i = lmap.find(logname);
if( i != lmap.end() )
i->second.log->delLevel(t);
i->second->delLevel(t);
}
// -------------------------------------------------------------------------
void LogAgregator::level( const std::string& logname, Debug::type t )
......@@ -145,7 +150,7 @@ void LogAgregator::level( const std::string& logname, Debug::type t )
auto i = lmap.find(logname);
if( i != lmap.end() )
i->second.log->level(t);
i->second->level(t);
}
// -------------------------------------------------------------------------
std::shared_ptr<DebugStream> LogAgregator::getLog( const std::string& logname )
......@@ -153,50 +158,100 @@ std::shared_ptr<DebugStream> LogAgregator::getLog( const std::string& logname )
if( logname.empty() )
return nullptr;
auto i = lmap.find(logname);
if( i != lmap.end() )
return i->second.log;
return nullptr;
return findLog(logname);
}
// -------------------------------------------------------------------------
LogAgregator::LogInfo LogAgregator::getLogInfo( const std::string& logname )
std::ostream& LogAgregator::print_tree( std::ostream& os, const std::string& g_tab )
{
if( logname.empty() )
return LogInfo();
ostringstream s;
s << " ." << g_tab;
auto i = lmap.find(logname);
string s_tab(s.str());
if( i != lmap.end() )
return i->second;
os << g_tab << getLogName() << sep << endl; // << setw(6) << " " << "[ " << Debug::str(DebugStream::level()) << " ]" << endl;
std::list<std::shared_ptr<DebugStream>> lst;
for( const auto& l: lmap )
lst.push_back(l.second);
lst.sort([](const std::shared_ptr<DebugStream>& a, const std::shared_ptr<DebugStream>& b) { return a->getLogName() < b->getLogName(); });
for( auto&& l: lst )
{
auto ag = dynamic_pointer_cast<LogAgregator>(l);
if( ag )
{
ag->print_tree(os,s_tab);
}
else
os << s_tab << l->getLogName() << " [ " << Debug::str(l->level()) << " ]" << endl;
}
return LogInfo();
return os;
}
// -------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, LogAgregator& la )
{
la.print_tree(os);
return os;
}
// -------------------------------------------------------------------------
std::ostream& operator<<(std::ostream& os, std::shared_ptr<LogAgregator> la )
{
return os << *(la.get());
}
// -------------------------------------------------------------------------
std::list<LogAgregator::LogInfo> LogAgregator::getLogList()
std::vector<std::string> LogAgregator::split_first( const std::string& lname, const std::string s )
{
std::list<LogAgregator::LogInfo> l;
string::size_type pos = lname.find(s);
if( pos == string::npos )
{
vector<string> v{lname,""};
return std::move(v);
}
for( auto && i : lmap )
l.push_back(i.second);
vector<string> v={lname.substr(0, pos), lname.substr(pos+1, lname.length()) };
return std::move(v);
}
// -------------------------------------------------------------------------
std::shared_ptr<DebugStream> LogAgregator::findLog( const std::string& lname )
{
auto v = split_first(lname,sep);
return std::move(l);
if( v[1].empty() )
{
auto l = lmap.find(lname);
if( l == lmap.end() )
return nullptr;
return l->second;
}
auto l = lmap.find(v[0]);
if( l == lmap.end() )
return nullptr;
auto ag = dynamic_pointer_cast<LogAgregator>(l->second);
if( !ag )
return l->second;
return ag->findLog(v[1]); // рекурсия
}
// -------------------------------------------------------------------------
std::list<LogAgregator::LogInfo> LogAgregator::getLogList( const std::string& regex_str )
std::list<LogAgregator::iLog> LogAgregator::getLogList( const std::string& regex_str )
{
std::list<LogAgregator::LogInfo> l;
std::list<LogAgregator::iLog> l;
try
{
std::regex rule(regex_str);
for( auto && i : lmap )
auto lst = getLogList();
for( const auto& i: lst )
{
if( std::regex_match(i.name, rule) )
{
//if( std::regex_match(i.second.log->getLogName(), rule) )
if( std::regex_match(i.first, rule) )
l.push_back(i.second);
l.push_back(i);
}
}
}
catch( const std::exception& ex )
......@@ -207,3 +262,51 @@ std::list<LogAgregator::LogInfo> LogAgregator::getLogList( const std::string& re
return std::move(l);
}
// -------------------------------------------------------------------------
std::list<LogAgregator::iLog> LogAgregator::getLogList()
{
std::list<LogAgregator::iLog> lst = makeLogNameList("");
lst.sort([](const LogAgregator::iLog& a, const LogAgregator::iLog& b) { return a.name < b.name; });
return std::move(lst);
}
// -------------------------------------------------------------------------
std::list<LogAgregator::iLog> LogAgregator::makeLogNameList( const std::string& prefix )
{
std::list<LogAgregator::iLog> lst;
ostringstream s;
s << prefix << getLogName();
string p(s.str());
string p2(p+sep);
for( auto&& l : lmap )
{
auto ag = dynamic_pointer_cast<LogAgregator>(l.second);
if( ag )
lst.splice(lst.end(), ag->makeLogNameList(p2));
else
{
std::string nm(p2+l.second->getLogName());
LogAgregator::iLog il(l.second,std::move(nm) );
lst.push_back( std::move(il) );
}
}
return std::move(lst);
}
// -------------------------------------------------------------------------
void LogAgregator::offLogFile( const std::string& logname )
{
auto l = findLog(logname);
if( l )
l->offLogFile();
}
// -------------------------------------------------------------------------
void LogAgregator::onLogFile( const std::string& logname )
{
auto l = findLog(logname);
if( l )
l->onLogFile();
}
// -------------------------------------------------------------------------
......@@ -205,8 +205,8 @@ void LogReader::readlogs( const std::string& _addr, ost::tpport_t _port, LogServ
log << buf;
if( msg.cmd == LogServerTypes::cmdList )
break;
// if( msg.cmd == LogServerTypes::cmdList )
// break;
}
else
break;
......
......@@ -109,7 +109,7 @@ void LogSession::run()
slog.info() << peername << "(run): receive command: '" << msg.cmd << "'" << endl;
string cmdLogName(msg.logname);
std::list<LogAgregator::LogInfo> loglist;
std::list<LogAgregator::iLog> loglist;
if( !cmdLogName.empty () )
{
......@@ -124,8 +124,8 @@ void LogSession::run()
{
if( cmdLogName == "ALL" || log->getLogFile() == cmdLogName )
{
LogAgregator::LogInfo log0(log);
loglist.push_back(log0);
LogAgregator::iLog llog(log,log->getLogName());
loglist.push_back(llog);
}
}
}
......@@ -142,66 +142,54 @@ void LogSession::run()
}
else
{
std::list<LogAgregator::LogInfo> lst;
if( cmdLogName.empty() || cmdLogName == "ALL" )
lst = alog->getLogList();
else
lst = alog->getLogList(cmdLogName);
// красиво отсортируем сперва..
lst.sort([](const LogAgregator::LogInfo & a, const LogAgregator::LogInfo & b) { return a.logname < b.logname; });
for( const auto& i : lst )
s << i.logname << endl;
s << alog << endl;
}
s << "=====================" << endl << endl;
if( isPending(Socket::pendingOutput, cmdTimeout) )
{
*tcp() << s.str();
tcp()->sync();
}
// по идее вывели список и завершили работу..
cancelled = true;
disconnect();
return;
}
// обрабатываем команды только если нашли подходящие логи
for( auto && li : loglist )
for( auto&& l : loglist )
{
// Обработка команд..
// \warning Работа с логом ведётся без mutex-а, хотя он разделяется отдельными потоками
switch( msg.cmd )
{
case LogServerTypes::cmdSetLevel:
li.log->level( (Debug::type)msg.data );
l.log->level( (Debug::type)msg.data );
break;
case LogServerTypes::cmdAddLevel:
li.log->addLevel( (Debug::type)msg.data );
l.log->addLevel( (Debug::type)msg.data );
break;
case LogServerTypes::cmdDelLevel:
li.log->delLevel( (Debug::type)msg.data );
l.log->delLevel( (Debug::type)msg.data );
break;
case LogServerTypes::cmdRotate:
{
if( !li.logfile.empty() )
li.log->logFile(li.logfile, true);
}
l.log->onLogFile(true);
break;
case LogServerTypes::cmdList: // обработали выше (в начале)
break;
case LogServerTypes::cmdOffLogFile:
li.log->logFile("");
l.log->offLogFile();
break;
case LogServerTypes::cmdOnLogFile:
{
if( !li.logfile.empty() )
li.log->logFile(li.logfile);
}
l.log->onLogFile();
break;
default:
......
......@@ -94,7 +94,7 @@ TEST_CASE("LogAgregator", "[LogServer][LogAgregator]" )
log2->any() << test_msg2;
REQUIRE( la_msg.str() == test_msg2 );
#if 0
auto lst = la->getLogList();
REQUIRE( lst.size() == 2 );
......@@ -104,6 +104,7 @@ TEST_CASE("LogAgregator", "[LogServer][LogAgregator]" )
auto lst3 = la->getLogList("log\\d{1}");
REQUIRE( lst3.size() == 2 );
#endif
}
// --------------------------------------------------------------------------
......@@ -245,7 +246,7 @@ TEST_CASE("MaxSessions", "[LogServer]" )
// --------------------------------------------------------------------------
TEST_CASE("Logagregator regexp", "[LogAgregator]" )
{
auto la = make_shared<LogAgregator>();
auto la = make_shared<LogAgregator>("ROOT");
auto log1 = la->create("log1");
auto log2 = la->create("log2");
auto log3 = la->create("a3/log1");
......@@ -257,7 +258,7 @@ TEST_CASE("Logagregator regexp", "[LogAgregator]" )
auto lst = la->getLogList(".*/a4/.*");
REQUIRE( lst.size() == 2 );
lst = la->getLogList("a3/.*");
lst = la->getLogList(".*a3/.*");
REQUIRE( lst.size() == 5 );
lst = la->getLogList(".*log1.*");
......
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