summaryrefslogtreecommitdiffstats
path: root/src/util/consoleLogger.h
blob: e4cb291bad2b5d2139b43220b3b797efbd1d3c34 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273

#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