summaryrefslogblamecommitdiffstats
path: root/src/util/consoleLogger.h
blob: e4cb291bad2b5d2139b43220b3b797efbd1d3c34 (plain) (tree)





















































































































                                                                                                                                                                              
                                                

























































































































































                                                                                  

#include "util.h"
#include "dispatcher.h"
#include <vector>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <list>


//#define as_daemon
#ifndef _CONSOLELOGGER_H_
#define _CONSOLELOGGER_H_

/**********************************************************************************************************************/
//  Console-, and Message Dispatching / Logging  (With timestamping!)
/**********************************************************************************************************************/
//
//  :: Usage ::
//
#define ConsoleLog ConsoleLogger::getLogger()-> //ease of acces!
//
//
//  *Logging:
//
//  ConsoleLog writeLine(<string/char*>);            // sends out a message with "normal" loglevel
//  ConsoleLog writeLine(<string/char*>, <loglevel>);   // sends out a message with the chosen loglevel --> enum LOG_LEVEL
//  ConsoleLog writeError(<string/char*>);          // sends out a message with "Error" loglevel
//  ConsoleLog writeTerminal(<string/char*>);       // sends out a message with "Terminal" loglevel, which means it is
//                                                                                           // also printed on stdout
//  ConsoleLog writeNetwork(<string/char*>);         // sends out a message with "network" loglevel
//  ConsoleLog writeChat(<string/char*>);         // sends out a message with "Chat" loglevel
//
//  *un/subscribing to the LogDispatcher
//
//  ConsoleLog addListener(<pointer-to-object-of-Type-myClass>, &myClass::myMethod);
//      callback signature --> typedef void (T::*callback)(ConsoleEntry); // with <U, T> as template  // for more on ConsoleEntry, see later
//  ConsoleLog removeListener(<pointer-to-object-of-Type-myClass>, &myClass::myMethod);
//
//  *Misc
//
//  ConsoleLog setLogPath(<string-path-to-log-directory>);    // set the log directory (with a final /, the logfilename is appended.)
//  ConsoleLog setLogName(<string-name>);         // like the above, but for the filename.
//  ConsoleLog dumpLog(DUMP_MODE);
//
//  DUMP_FILE               ::>>        Dumps the whole log since the logger was started into the specified logfile. the file content gets overwritten
//  DUMP_FILE_CONCAT        ::>>        The Same as above, but it will just append itself to the previously (if implemented) log which got \**
//                                              ***\ read from the logfile which was present at logger start. if no log is found or logfile was not read, behaves as DUMP_FILE
//  DUMP_TERMINAL           ::>>        Dumps the whole log into the terminal
//  DUMP_ALL_LISTENERS      ::>>        Dumps the whole log to all listeners
//
//  Alternatively, you can request a dump to a certain listener:
//  ConsoleLog dump2Listener(<pointer-to-object-of-Type-myClass>, &myClass::myMethod); // it expects the same information as when subscribing
//              // the PVS-Server console makes heavy use of this feature to implement its filters
//
//
//  :: using the ConsoleEntry class ::
//
//  *methods and members
//
//
//        LOG_LEVEL getLevel()      // returns the loglevel as LOG_LEVEL Enum-type
//        QString getLine()     // returns the complete line as shown in the logfile, with timestamp, loglevel prefix etc
//        QString getMessage()  // returns the message body, no gimmicks attached
//        QString getPrefix()   // returns the loglevel as string-represenation
//        QString getTimeStamp() // returns the timestamp which was set at the creation of the object
//
//
//
//
//
//
/**********************************************************************************************************************/






// Typdef at bottom of file :
// typedef ConsoleLogger::ConsoleEntry LogEntry;


class ConsoleLogger
{
public:

    enum LOG_LEVEL { LOG_NORMAL,
                     LOG_ERROR,
                     LOG_CHAT,
                     LOG_TERMINAL,
                     LOG_NETWORK
                   };
    enum DUMP_MODE { DUMP_FILE,
                     DUMP_FILE_CONCAT,
                     DUMP_TERMINAL,
                     DUMP_ALL_LISTENERS,
                   };
    class ConsoleEntry
    {
    public:
        ConsoleEntry(QString timeStamp, QString message, LOG_LEVEL level)
        {
            setLine(timeStamp, message, level);
        };
        void setLine(QString timeStamp, QString message, LOG_LEVEL level)
        {
            _message = message;
            _prefix = _prefixLine(level);
            _timeStamp = timeStamp;
            _line.append(QString("[ ").append(timeStamp));
            _line.append(QString(" ] ").append(_prefix));
            _line.append(QString(": ").append(message));
            _level = level;
           if ('\n' != _line[_line.size()-1] && '\n' != _line[_line.size()])
                _line.push_back('\n');    // add an explicit newline char, so it looks better in the logfile
            //#ifndef as_daemon
            if (_level == LOG_TERMINAL) // may look strange here, but its quite central :-)
                qDebug("%s", qPrintable(_line));
            //#endif
        };
        LOG_LEVEL getLevel()
        {
            return _level;
        };
        QString getLine()
        {
            return _line;
        };
        QString getMessage()
        {
            return _message;
        };
        QString getPrefix()
        {
            return _prefix;
        };
        QString getTimeStamp()
        {
            return _timeStamp;
        };

    private:
        QString _prefixLine(LOG_LEVEL level)
        {
            // switch anyone?
            if (level == LOG_NORMAL)
                return QString("PVS");
            if (level == LOG_ERROR)
                return QString("PVS ERROR");
            if (level == LOG_TERMINAL)
                return QString("PVS Terminal");
            if (level == LOG_CHAT)
                return QString("PVS Chat");
            if (level == LOG_NETWORK)
                return QString("PVS Network");
            return QString("UNDEFINED");
        };
        QString _line; // the complete line with timestamp and everything
        QString _message; // the message itself
        QString _prefix; // just the prefix
        QString _timeStamp; // just the timestamp
        LOG_LEVEL _level;
    };

    class LogNotifyEntry
    {
    public:
        virtual void fire(ConsoleEntry consoleEntry) {};
        LogNotifyEntry() {};
    };

#ifdef never
private:
    template<class T>
    class LogNotify : public LogNotifyEntry
    {
    public:
        typedef void (T::*callback)(ConsoleEntry);
        LogNotify(T* who, callback func )//void (T :: *func)(QString))
        {
            callee = who;
            //callback = func;
            myCB = func;
        };
        virtual void fire(ConsoleEntry consoleEntry)
        {
            if (callee)
                (callee->*myCB)(consoleEntry);
        };
        T* getCallee()
        {
            return callee;
        };
        callback getCB()
        {
            return myCB;
        };

    private:
        T *callee;
        callback myCB;
    };

public:
#endif
    // interfaces for the dispatcher for easy of access ( --> ConsoleLog Makro)
    template<class T> void addListener(T* who, void (T :: *func)(ConsoleEntry))
    {
        entryDispatcher.addListener(who, func);
    };
    template<class T> void removeListener(T* who, void (T :: *func)(ConsoleEntry))
    {
        entryDispatcher.removeListener(who, func);
    };
    template<class T> void dump2Listener(T* who, void (T :: *func)(ConsoleEntry))
    {
        for (int i = 0; i < int(_log.size()) ; i++)
            (who->*func)(_log[i]);
    };

    int writeLine(QString message, LOG_LEVEL = LOG_NORMAL);
    int writeline(const char* message, LOG_LEVEL = LOG_NORMAL);
    int writeError(QString error);
    int writeError(const char* error);
    int writeTerminal(QString terminal);
    int writeTerminal(const char* terminal);
    int writeNetwork(QString network);
    int writeNetwork(const char* network);
    int writeChat(QString chat);
    int writeChat(const char* chat);
    void getLine(int lineNum, char* line);
    void getLine(int lineNum, QString* line);
    void setLogPath(QString logPath);
    void setLogName(QString logName);
    void dumpLog(DUMP_MODE mode = DUMP_FILE);
    static ConsoleLogger* getLogger();
    static int count;
private:


    std::vector<ConsoleEntry>* _getLog()
    {
        return &_log;
    };
    static ConsoleLogger* _logger;
    void _prepareLog();
    void _writeLine2File(QString line);
    void _writeLog(bool concat = false);
    void _announceWrite(ConsoleEntry consoleEntry);
    void _readLog(QString path = QString(""));
    QString _getTimeStamp();
    void _prefixLine(QString* line, LOG_LEVEL level = LOG_NORMAL);



    ConsoleLogger();
    ~ConsoleLogger();

    QString _logName;
    QString _logPath;

    bool _logFileGood, _fileRead;
//    std::list<LogNotifyEntry*> _CBLog;
    EventDispatcher<ConsoleEntry> entryDispatcher;
    std::vector<ConsoleEntry> _log;
    std::vector<ConsoleEntry> _prev_log;
    std::ofstream _logFile;
};

typedef ConsoleLogger::ConsoleEntry LogEntry;

#endif