forked from c42f/displaz
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlogger.h
141 lines (116 loc) · 6.16 KB
/
logger.h
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
// Copyright 2015, Christopher J. Foster and the other displaz contributors.
// Use of this code is governed by the BSD-style license found in LICENSE.txt
#ifndef LOGGER_H_INCLUDED
#define LOGGER_H_INCLUDED
#include <map>
#include "tinyformat.h"
//------------------------------------------------------------------------------
/// Logger class for log message formatting using printf-style strings
class Logger
{
public:
enum LogLevel
{
Error,
Warning,
Info,
Debug,
Progress
};
Logger(LogLevel logLevel = Info, bool logProgress = true,
int logMessageLimit = 1000)
: m_logLevel(logLevel),
m_logProgress(logProgress),
m_logMessageLimit(logMessageLimit)
{ }
/// Parse logging level to the given string level. Must be one of
/// "error", "warning", "info" or "debug". For badly formatted
/// strings, `defaultLevel` is returned.
static Logger::LogLevel parseLogLevel(const std::string& logLevel, LogLevel defaultLevel = Info);
void setLogLevel(LogLevel logLevel) { m_logLevel = logLevel; }
void setLogProgress(bool logProgress) { m_logProgress = logProgress; }
/// Printf-style logging functions (typesafe via tinyformat)
# define DISPLAZ_MAKE_LOG_FUNCS(n) \
\
template<TINYFORMAT_ARGTYPES(n)> \
void progress(const char* fmt, TINYFORMAT_VARARGS(n)) \
{ \
log(Progress, fmt, tfm::makeFormatList(TINYFORMAT_PASSARGS(n)));\
} \
\
template<TINYFORMAT_ARGTYPES(n)> \
void debug(const char* fmt, TINYFORMAT_VARARGS(n)) \
{ \
log(Debug, fmt, tfm::makeFormatList(TINYFORMAT_PASSARGS(n))); \
} \
\
template<TINYFORMAT_ARGTYPES(n)> \
void info(const char* fmt, TINYFORMAT_VARARGS(n)) \
{ \
log(Info, fmt, tfm::makeFormatList(TINYFORMAT_PASSARGS(n))); \
} \
\
template<TINYFORMAT_ARGTYPES(n)> \
void warning(const char* fmt, TINYFORMAT_VARARGS(n)) \
{ \
log(Warning, fmt, tfm::makeFormatList(TINYFORMAT_PASSARGS(n)));\
} \
\
template<TINYFORMAT_ARGTYPES(n)> \
void error(const char* fmt, TINYFORMAT_VARARGS(n)) \
{ \
log(Error, fmt, tfm::makeFormatList(TINYFORMAT_PASSARGS(n))); \
} \
\
/* Versions of above which limit total number of messages to m_logMessageLimit */ \
template<TINYFORMAT_ARGTYPES(n)> \
void warning_limited(const char* fmt, TINYFORMAT_VARARGS(n)) \
{ \
log(Warning, fmt, tfm::makeFormatList(TINYFORMAT_PASSARGS(n)), m_logMessageLimit); \
}
TINYFORMAT_FOREACH_ARGNUM(DISPLAZ_MAKE_LOG_FUNCS)
# undef DISPLAZ_MAKE_LOG_FUNCS
// 0-arg versions
void progress (const char* fmt) { log(Progress, fmt, tfm::makeFormatList()); }
void debug (const char* fmt) { log(Debug, fmt, tfm::makeFormatList()); }
void info (const char* fmt) { log(Info, fmt, tfm::makeFormatList()); }
void warning (const char* fmt) { log(Warning, fmt, tfm::makeFormatList()); }
void error (const char* fmt) { log(Error, fmt, tfm::makeFormatList()); }
void warning_limited (const char* fmt) { log(Warning, fmt, tfm::makeFormatList(), m_logMessageLimit); }
/// Log result of `tfm::vformat(fmt,flist)` at the given log level.
///
/// If `maxMsgs` is positive, messages with the same `(level,fmt)` key
/// will be logged at most `maxMsgs` times.
virtual void log(LogLevel level, const char* fmt, tfm::FormatListRef flist, int maxMsgs = 0);
/// Report progress of some processing step
void progress(double progressFraction)
{
if (m_logProgress)
progressImpl(progressFraction);
}
protected:
virtual void logImpl(LogLevel level, const std::string& msg) = 0;
virtual void progressImpl(double progressFraction) = 0;
private:
typedef std::pair<const char*,LogLevel> LogCountKey;
LogLevel m_logLevel;
bool m_logProgress;
int m_logMessageLimit;
std::map<LogCountKey,int> m_logCountLimit;
};
/// Logger class which logs to the console
class StreamLogger : public Logger
{
public:
StreamLogger(std::ostream& outStream);
~StreamLogger();
protected:
virtual void logImpl(LogLevel level, const std::string& msg);
virtual void progressImpl(double progressFraction);
private:
bool m_prevPrintWasProgress;
double m_prevProgressFraction;
std::string m_progressPrefix;
std::ostream& m_out;
};
#endif // LOGGER_H_INCLUDED