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
|
#include <logger.h>
#include <stdarg.h>
#include <exception.h>
#include <cerrno>
namespace newsbeuter {
mutex logger::instanceMutex;
logger::logger() : curlevel(LOG_NONE) { }
void logger::set_logfile(const char * logfile) {
/*
* This sets the filename of the debug logfile
*/
scope_mutex lock(&logMutex);
if (f.is_open())
f.close();
f.open(logfile, std::fstream::out);
if (!f.is_open()) {
throw exception(errno); // the question is whether f.open() sets errno...
}
}
void logger::set_errorlogfile(const char * logfile) {
/*
* This sets the filename of the error logfile, i.e. the one that can be configured to be generated.
*/
scope_mutex lock(&logMutex);
if (ef.is_open())
ef.close();
ef.open(logfile, std::fstream::out);
if (!ef.is_open()) {
throw exception(errno);
}
if (LOG_NONE == curlevel) {
curlevel = LOG_USERERROR;
}
}
void logger::set_loglevel(loglevel level) {
scope_mutex lock(&logMutex);
curlevel = level;
if (curlevel == LOG_NONE)
f.close();
}
const char * loglevel_str[] = { "NONE", "USERERROR", "CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG" };
void logger::log(loglevel level, const char * format, ...) {
/*
* This function checks the loglevel, creates the error message, and then
* writes it to the debug logfile and to the error logfile (if applicable).
*/
scope_mutex lock(&logMutex);
if (level <= curlevel && curlevel > LOG_NONE && (f.is_open() || ef.is_open())) {
char * buf, * logmsgbuf;
char date[128];
time_t t = time(NULL);
struct tm * stm = localtime(&t);
strftime(date,sizeof(date),"%Y-%m-%d %H:%M:%S",stm);
if (curlevel > LOG_DEBUG)
curlevel = LOG_DEBUG;
va_list ap;
va_start(ap, format);
unsigned int len = vsnprintf(NULL,0,format,ap);
va_end(ap);
va_start(ap, format);
logmsgbuf = new char[len + 1];
vsnprintf(logmsgbuf, len + 1, format, ap);
va_end(ap);
len = snprintf(NULL, 0, "[%s] %s: %s",date, loglevel_str[level], logmsgbuf);
buf = new char[len + 1];
snprintf(buf,len + 1,"[%s] %s: %s",date, loglevel_str[level], logmsgbuf);
if (f.is_open()) {
f << buf << std::endl;
}
if (LOG_USERERROR == level && ef.is_open()) {
snprintf(buf, len + 1, "[%s] %s", date, logmsgbuf);
ef << buf << std::endl;
ef.flush();
}
delete[] buf;
delete[] logmsgbuf;
}
}
logger &logger::getInstance() {
/*
* This is the global logger that everyone uses
*/
scope_mutex lock(&instanceMutex);
static logger theLogger;
return theLogger;
}
}
|