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
|
#ifndef MULTILOG_H
#define MULTILOG_H
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include "ringlist.h"
#include "linkedlist.h"
#include "singleton.h"
/**
* Calls the DetailLog function but includes pre-processor macros to fill in
* most of the fields for you. This makes your life a lot easier, and makes the
* log useful for system debugging as well as just letting people know what's
* going on.
*@param LEVEL The log level, comes from an enum in the MultiLog class.
*@param FORMAT The text to store in the log, using printf style formatting.
*@param ... Parameters to help format the text in the FROMAT param.
*/
#define LineLog( LEVEL, FORMAT, ...) DetailLog( LEVEL, __FILE__, __LINE__, __PRETTY_FUNCTION__, FORMAT, ##__VA_ARGS__ )
#define MultiLineLog( LEVEL, FORMAT, ...) MultiLog::getInstance().DetailLog( LEVEL, __FILE__, __LINE__, __PRETTY_FUNCTION__, FORMAT, ##__VA_ARGS__ )
/** MultiLog keeps track of logfile info in a myriad of varieties, and is
* easily configurable between them all. It allows output to the standard
* output, error output, files, networks, and streams, which includes memory
* buffers.
* MultiLog uses the singleton pattern to keep only a single instance of
* the log. Instead of instantiating a new copy, call the getLog method.
*@author Mike Buland
*/
class MultiLog : public Singleton<MultiLog>
{
friend class Singleton<MultiLog>;
public:
/**
* Keeps track of a single log entry, in a standard format, that can be
* processed by any MultiLogChannel derrived class.
*@author Mike Buland
*/
typedef struct LogEntry
{
/** Safely delete a log entry. */
virtual ~LogEntry();
time_t xTime; /**< The time the log entry was made. */
int nLevel; /**< The log-level of the entry. */
char *lpFile; /**< The name of the file this entry came from. */
int nLine; /**< The line number that this log came from. */
char *lpText; /**< The text content of this log entry. */
} LogEntry;
protected:
/**
* Private constructor, this ensures that this is a singleton.
*/
MultiLog();
/**
* Destroy the multilog.
*/
virtual ~MultiLog();
/**
* Append a new logentry to the log list, possibly pushing an old entry off.
*@param pEntry The new entry to append.
*/
void append( LogEntry *pEntry );
/**
* The actual log entry storage mechanism.
*/
RingList *rEntry;
/**
* The number of entries that have rolled off the end of the RingList.
*/
unsigned long nEntriesLost;
/**
* A list of all channels that are registered with the MultiLog.
*/
LinkedList *lChannel;
public:
/** Sends info to the logfile.
*@param nLevel The type of data being logged (error, info, etc.)
*@param lpFormat The data to send to the log.
*@author Mike Buland
*/
//void Log( int nLevel, const char *lpFormat, ...);
/** Sends info to the logfile with extra information, including the files
* that it was called from and the line in the code. Besides that, it's
* exactly the same as Log. Please use the LineLog macro to make DetailLog
* really easy to use. It operates exacly like Log, but inserts the
* builtin macros as the lpFile and nLine parameters.
*@param nLevel The type of data being logged (error, info, etc.)
*@param lpFile The name of the file that called the log function.
*@param nLine The line in the file that this log function was called from.
*@param lpFunction The name of the function that called the log function.
*@param lpFormat The data to send to the log.
*@author Mike Buland
*/
void DetailLog( int nLevel, const char *lpFile, int nLine, const char *lpFunction, const char *lpFormat, ...);
/**
* Adds a logging channel to the MultiLog channel chain. Every added
* channel will automatically receive a complete log of everything that
* happened before the channel was added as well as all future messages.
*@param pChannel A pointer to the pre-contructed channel object to add.
*/
void addChannel( class MultiLogChannel *pChannel );
/** The various pre-defined levels available to use when logging.
* The person logging can make up their own, just make sure to remember
* which value is which (all levels are integers).
*@author Mike Buland
*/
enum Levels
{
LError,
LWarning,
LInfo,
LStatus
};
};
#endif
|