-
Notifications
You must be signed in to change notification settings - Fork 0
/
Log.h
250 lines (179 loc) · 6.49 KB
/
Log.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
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
#pragma once
#include <memory>
#include <string>
#include <mutex>
#include <sstream>
#include <vector>
#include <list>
#include <fstream>
#include <map>
#include <stdarg.h>
#include "CurrentThread.h"
#define LOG_LEVEL(logger, level) \
if(logger->getLevel() <= level) \
LogEventWrap(LogEvent::ptr(new LogEvent(logger, level, \
__FILE__, __LINE__, 0, CurrentThread::tid(), time(0), "thread"))).getSS();
#define LOG_DEBUG(logger) LOG_LEVEL(logger, LogLevel::DEBUG)
#define LOG_INFO(logger) LOG_LEVEL(logger, LogLevel::INFO);
#define LOG_ERROR(logger) LOG_ERROR(logger, LogLevel::ERROR);
#define LOG_FATAL(logger) LOG_LEVEL(logger, LogLevel::FATAL);
#define LOG_FMT_LEVEL(logger, level, fmt, ...) \
if(logger->getLevel() <= level) \
LogEventWrap(LogEvent::ptr(new LogEvent(logger, level, \
__FILE__, __LINE__, 0, CurrentThread::tid(), time(0), "thread"))).getEvent()->format(fmt, __VA_ARGS__)
#define LOG_FMT_DEBUG(logger, fmt, ...) LOG_FMT_LEVEL(logger, LogLevel::DEBUG, fmt, __VA_ARGS__)
#define LOG_FMT_INFO(logger, fmt, ...) LOG_FMT_LEVEL(logger, LogLevel::INFO, fmt, __VA_ARGS__)
#define LOG_FMT_ERROR(logger, fmt, ...) LOG_FMT_LEVEL(logger, LogLevel::ERROR, fmt, __VA_ARGS__)
#define LOG_FMT_FATAL(logger, fmt, ...) LOG_FMT_LEVEL(logger, LogLevel::FATAL, fmt, __VA_ARGS__)
#define LOG_ROOT() LoggerManager::instance()->getRoot()
#define LOG_NAME(name) LoggerManager::instance()->getLogger(name)
class Logger;
class LoggerManager;
class LogLevel {
public:
enum Level{
UNKNOW = 0,
DEBUG = 1,
INFO = 2,
ERROR = 3,
FATAL = 4
};
static const char* ToString(LogLevel::Level level);
static LogLevel::Level FromString(const std::string& str);
};
class LogEvent{
public:
typedef std::shared_ptr<LogEvent> ptr;
LogEvent(std::shared_ptr<Logger> logger
, LogLevel::Level level
, const char* file, int32_t line, uint32_t elapse
, uint32_t thread_id
, uint64_t time
, const std::string& thread_name);
const char* getFile() const { return file_; }
int32_t getLine() const { return line_; }
uint32_t getElapse() const { return elapse_; }
uint32_t getThreadId() const { return threadId_; }
uint64_t getTime() const { return time_; }
const std::string& getThreadName() const { return threadName_; }
std::string getContent() const { return ss_.str(); }
std::shared_ptr<Logger> getLogger() const { return logger_; }
LogLevel::Level getLevel() const { return level_; }
std::stringstream& getSS() { return ss_; }
void format(const char* fmt, ...);
void format(const char* fmt, va_list al);
private:
const char* file_ = nullptr;
int32_t line_ = 0;
uint32_t elapse_ = 0;
uint32_t threadId_ = 0;
uint64_t time_ = 0;
std::string threadName_;
std::stringstream ss_;
std::shared_ptr<Logger> logger_;
LogLevel::Level level_;
};
class LogEventWrap {
public:
LogEventWrap(LogEvent::ptr e);
~LogEventWrap();
LogEvent::ptr getEvent() const { return event_; }
std::stringstream& getSS();
private:
LogEvent::ptr event_;
};
class LogFormatter {
public:
typedef std::shared_ptr<LogFormatter> ptr;
LogFormatter(const std::string& pattern);
std::string format(std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::ptr event);
std::ostream& format(std::ostream& ofs, std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::ptr event);
public:
class FormatItem {
public:
typedef std::shared_ptr<FormatItem> ptr;
virtual ~FormatItem() {}
virtual void format(std::ostream& os, std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::ptr event);
};
void init();
bool isError() const { return error_; }
const std::string getPattern() const { return pattern_; }
private:
std::string pattern_;
std::vector<FormatItem::ptr> items_;
bool error_ = false;
};
class LogAppender {
friend class Logger;
public:
typedef std::shared_ptr<LogAppender> ptr;
typedef pthread_spinlock_t MutexType;
virtual ~LogAppender() {}
virtual void log(std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::ptr event) = 0;
void setFormatter(LogFormatter::ptr val);
LogFormatter::ptr getFormatter();
LogLevel::Level getLevel() const { return level_; }
void setLevel(LogLevel::Level val) { level_ = val; }
protected:
LogLevel::Level level_ = LogLevel::DEBUG;
bool hasFormatter_ = false;
MutexType mutex_;
LogFormatter::ptr formatter_;
};
class Logger : public std::enable_shared_from_this<Logger> {
friend class LoggerManager;
public:
typedef std::shared_ptr<Logger> ptr;
typedef pthread_spinlock_t MutexType;
Logger(const std::string& name = "root");
void log(LogLevel::Level level, LogEvent::ptr event);
void debug(LogEvent::ptr event);
void info(LogEvent::ptr event);
void error(LogEvent::ptr event);
void fatal(LogEvent::ptr event);
void addAppender(LogAppender::ptr appender);
void delAppender(LogAppender::ptr appender);
void clearAppenders();
LogLevel::Level getLevel() const { return level_; }
void setLevel(LogLevel::Level val) { level_ = val; }
const std::string& getName() const { return name_; }
void setFormatter(LogFormatter::ptr val);
void setFormatter(const std::string& val);
LogFormatter::ptr getFormatter();
private:
std::string name_;
LogLevel::Level level_;
MutexType mutex_;
std::list<LogAppender::ptr> appenders_;
LogFormatter::ptr formatter_;
Logger::ptr root_;
};
class StdoutLogAppender : public LogAppender {
public:
typedef std::shared_ptr<StdoutLogAppender> ptr;
void log(Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event) override;
};
class FileLogAppender : public LogAppender {
public:
typedef std::shared_ptr<FileLogAppender> ptr;
FileLogAppender(const std::string& filename);
void log(Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event) override;
bool reopen();
private:
std::string filename_;
std::ofstream filestream_;
uint64_t lastTime_ = 0;
};
class LoggerManager {
public:
typedef pthread_spinlock_t MutexType;
static LoggerManager* instance();
Logger::ptr getLogger(const std::string& name);
void init();
Logger::ptr getRoot() const { return root_; }
private:
LoggerManager();
MutexType mutex_;
std::map<std::string, Logger::ptr> loggers_;
Logger::ptr root_;
};