khanat-opennel-code/code/nelns/admin_executor_service/log_report.h
2013-06-06 02:56:48 -07:00

291 lines
7.2 KiB
C++

// NeLNS - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_LOG_REPORT_H
#define NL_LOG_REPORT_H
#include "nel/misc/types_nl.h"
#include "nel/misc/log.h"
#include "nel/misc/thread.h"
#include <string>
#include <vector>
#include <map>
class CLogReport;
/*
*
*/
class CMakeLogTask : public NLMISC::IRunnable
{
public:
/// Constructor
CMakeLogTask() : _Stopping(false), _Complete(false), _Thread(NULL), _OutputLogReport(NULL) {}
/// Destructor
~CMakeLogTask();
/// Start (called in main thread)
void start();
/// Ask for stop and wait until terminated (called in main thread)
void terminateTask();
///
bool isRunning() const { return (_Thread != NULL) && (!_Complete); }
///
bool isStopping() const { return _Stopping; }
///
bool isComplete() const { return _Complete; }
virtual void run();
/// Set the path of logfile directory.
void setLogPath(const std::string & logPath);
/// Set one or more paths of logfile directory. They will be processed when running the background thread.
void setLogPaths(const std::vector<std::string>& logPaths);
/// Set the path of logfile directory to default value
void setLogPathToDefault();
/// Return the log paths
const std::vector<std::string> getLogPaths() const { return _LogPaths; }
/** Set which files are to be browsed:
* v --> log*.log (default if setLogTarget() not called or called with an empty string)
* v* --> log*.log + v*_log*.log
* v<n> --> v<n>_log*.log
* v<n>+ --> v<n>_log*.log + all matching greater <n> + log*.log
* v<n>- --> v<n>_log*.log + all matching lower <n>
* * --> *.log
*/
void setLogTarget(const std::string & logTarget) { _LogTarget = logTarget; }
/// Return the log report (NULL if task not started yet)
CLogReport* getLogReport() { return _OutputLogReport; }
private:
void pleaseStop() { _Stopping = true; }
void clear();
volatile bool _Stopping;
volatile bool _Complete;
std::string _LogTarget;
std::vector<std::string> _LogPaths;
NLMISC::IThread *_Thread;
CLogReport *_OutputLogReport;
};
const uint NB_LINES_PER_PAGE = 100;
/**
*
*/
class CLogLineInfo
{
public:
CLogLineInfo() : NbOccurences(0) {}
void addAnOccurence( const std::vector<std::string>& lineTokens );
uint NbOccurences;
std::string SampleLogText;
};
/**
*
*/
class ILogReport
{
public:
virtual void storeLine( const std::vector<std::string>& lineTokens, bool mainCountOnly ) = 0;
virtual void report( NLMISC::CLog *targetLog, bool detailed ) = 0;
virtual uint getNbDistinctLines() const = 0;
virtual uint getNbTotalLines( NLMISC::CLog::TLogType logType ) = 0;
virtual ~ILogReport() {}
};
/**
* For one service (service name, not service instance), store info about log lines
*/
class CLogReportLeaf : public ILogReport
{
public:
/// Constructor
CLogReportLeaf( const std::string& service ) : _Service(service), _TotalLines(0) {}
std::string service() { return _Service; }
virtual uint getNbDistinctLines() const { return (uint)_LogLineInfo.size(); }
virtual uint getNbTotalLines( NLMISC::CLog::TLogType logType );
virtual void storeLine( const std::vector<std::string>& lineTokens, bool mainCountOnly );
virtual void report( NLMISC::CLog *targetLog, bool detailed );
uint reportPart( uint beginIndex, uint maxNbLines, NLMISC::CLog *targetLog );
protected:
typedef std::map< std::string, CLogLineInfo > CLogLineInfoMap;
std::string _Service;
CLogLineInfoMap _LogLineInfo;
std::map< std::string, uint > _Counts; // indexed by log type string
uint _TotalLines;
};
/**
* Store info about log lines for several services
*/
class CLogReportNode : public ILogReport
{
public:
/// Constructor
CLogReportNode() {}
/// Destructor
~CLogReportNode() { reset(); }
/// Clear all
void reset()
{
for ( std::vector<CLogReportLeaf*>::iterator it=_Children.begin(); it!=_Children.end(); ++it )
delete (*it);
_Children.clear();
}
protected:
virtual void storeLine( const std::vector<std::string>& lineTokens, bool mainCountOnly=false );
CLogReportLeaf* getChild( const std::string& service )
{
for ( std::vector<CLogReportLeaf*>::iterator it=_Children.begin(); it!=_Children.end(); ++it )
{
if ( (*it)->service() == service )
return (*it);
}
return NULL;
}
CLogReportLeaf* addChild( const std::string& service )
{
CLogReportLeaf *child = new CLogReportLeaf( service );
_Children.push_back( child );
return child;
}
virtual void report( NLMISC::CLog *targetLog, bool displayDetailsPerService );
virtual uint getNbDistinctLines() const
{
uint n = 0;
for ( std::vector<CLogReportLeaf*>::const_iterator it=_Children.begin(); it!=_Children.end(); ++it )
n += (*it)->getNbDistinctLines();
return n;
}
virtual uint getNbTotalLines( NLMISC::CLog::TLogType logType=NLMISC::CLog::LOG_UNKNOWN )
{
uint n = 0;
for ( std::vector<CLogReportLeaf*>::const_iterator it=_Children.begin(); it!=_Children.end(); ++it )
n += (*it)->getNbTotalLines( logType );
return n;
}
void reportPage( uint pageNum, NLMISC::CLog *targetLog );
private:
std::vector<CLogReportLeaf*> _Children;
};
/*
* <Class description>
* \author Olivier Cado
* \author Nevrax France
* \date 2004
*/
class CLogReport : public CLogReportNode
{
public:
/// Constructor
CLogReport() : _CurrentFile(~0), _TotalFiles(~0) {}
/// Clear all
void reset() { CLogReportNode::reset(); }
/**
* Add a log line to the report tree.
* \param onlyType Type of log to study. If LOG_UNKNOWN, study all.
* \param countOtherTypes If true and onlyType not LOG_UNKNOWN, count the number of lines of each other type found.
*/
void pushLine( const std::string& line, NLMISC::CLog::TLogType onlyType=NLMISC::CLog::LOG_WARNING, bool countOtherTypes=true );
/// Set the current progress
void setProgress( uint currentFile, uint totalFiles ) { _CurrentFile = currentFile; _TotalFiles = totalFiles; }
/// Get the current progress
void getProgress( uint& currentFile, uint& totalFiles ) { currentFile = _CurrentFile; totalFiles = _TotalFiles; }
/// Get results for a service
void reportByService( const std::string& service, NLMISC::CLog *targetLog );
/// Get partial results (pageNum>=1)
void reportPage( uint pageNum, NLMISC::CLog *targetLog ) { CLogReportNode::reportPage( pageNum, targetLog ); }
/// Get summary of results
virtual void report( NLMISC::CLog *targetLog, bool displayDetailsPerService=false ) { CLogReportNode::report( targetLog, displayDetailsPerService ); }
private:
uint _CurrentFile;
uint _TotalFiles;
};
#endif // NL_LOG_REPORT_H
/* End of log_report.h */