1. LogLevel
日志级别:通过LogLevel
类可以定义日志的重要级别
1 | class LogLevel |
2. LogEvent
日志事件:日志事件LogEvent
类包含当前日志的所有具体信息,包括Logger
日志器、LogLevel
日志级别、行号、线程号等。
1 | class LogEvent |
3. LogFormatter
格式化文本:日志格式器LogFormatter
,返回格式化字符串
- 成员函数
init()
:根据构造函数传入的pattern:%xxx %xxx{xxx} %%
初始化m_items
- 成员函数
format()
:根据传入的Logger
日志器、LogLevel
日志级别、LogEvent
日志事件,遍历调用m_items
将其转换为格式化文本 - 成员对象
string``m_pattern
- 成员对象
vector<FormatItem::ptr> m_items
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
26class 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);
void init();
bool isError() const { return m_error; }
const std::string getPattern() const { return m_pattern; }
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) = 0;
};
private:
std::string m_pattern;
std::vector<FormatItem::ptr> m_items;
bool m_error = false;
};
3.1 FormatItem
格式器项:根据自身要求输出对应的信息,如MessageFormatItem
类负责输出LogEvent
中的字节流,他只获取LogEvent
中的Content
对象,并输出到对应的ostream
1 | class MessageFormatItem : public LogFormatter::FormatItem |
4. LogAppender
输出:日志输出器,用于输出LogFormatter
返回的格式化文本,其中保存了LogFormatter
格式器对象,LogLevel
日志等级
- 成员函数
log()
:通过传入Logger
日志器、LogLevel
日志级别、LogEvent
日志事件,调用LogFormatter
,得到格式化文本并输出到指定位置 - 成员对象
m_formatter
:每个输出器都有自己的格式器 - 成员对象
m_level
:配置LogLevel
,LogAppender
根据自己的LogLevel
判断传入的日志事件是否进行输出操作1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20class LogAppender
{
friend class Logger;
public:
typedef std::shared_ptr<LogAppender> ptr;
typedef Spinlock 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 m_level; }
void setLevel(LogLevel::Level val) { m_level = val; }
protected:
LogLevel::Level m_level = LogLevel::DEBUG;
bool m_hasFormatter = false;
MutexType m_mutex;
LogFormatter::ptr m_formatter;
};
4.1 StdoutLogAppender
控制台输出:日志输出器LogAppender
的具体类,通过调用log
函数实现输出
1 | class StdoutLogAppender : public LogAppender { |
5. Logger
日志器类:保存有字段:LogLevel日志级别,LogAppender日志输出地,LogFormatter日志格式器
- 成员对象
LogLevel
- 成员对象
list<LogAppender::ptr>
- 成员对象
LogFormatter
:默认给LogAppender
内的Logformatter
做配置 - 成员函数
debug/info/warn/error/fatal
:输出该日志等级的日志事件
1 | class Logger : public std::enable_shared_from_this<Logger> |
6. LogEventWrap
日志包装器:可以把LogEventWrap
当作临时的右值,创建时直接传入在构造函数中传入LogEvent
,本行结束后自动析构,调用log
,不会产生额外的指针。
1 | class LogEventWrap { |
7. 调用过程
7.1 Logger::log
Logger::log
函数被调用,根据Logger
日志器的日志等级判断本次log
是否有效- 有效则遍历
Logger
中的所有LogAppender
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19void Logger::log(LogLevel::Level level, LogEvent::ptr event)
{
if (level >= m_level)
{
auto self = shared_from_this();
// 锁 MutexType::Lock lock(m_mutex);
if (!m_appenders.empty())
{
for (auto &i : m_appenders)
{
i->log(self, level, event);
}
}
else if (m_root)
{
m_root->log(level, event);
}
}
}
- 有效则遍历
7.2 LogAppender::log
- 被
Logger::log
调用 - 每个
LogAppender
都保存有自己的LogLevel
日志等级- 如果本次日志有效,则调用
LogFormatter
,并且传入std::cout
作为输出端口1
2
3
4
5
6
7
8void StdoutLogAppender::log(std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::ptr event)
{
if (level >= m_level)
{
// 锁 MutexType::Lock lock(m_mutex);
m_formatter->format(std::cout, logger, level, event);
}
}
- 如果本次日志有效,则调用
7.3 LogFormatter::format
- 被
LogAppender::log
调用 - 遍历内部保存的每个
FormatItem
,有两个重载- 方法一将所有的内容存储到字节流中,并返回字符串
- 方法二传入输出流,并直接通过
format
将流输出到对应位置1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18std::string LogFormatter::format(std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::ptr event)
{
std::stringstream ss;
for (auto &i : m_items)
{
i->format(ss, logger, level, event);
}
return ss.str();
}
std::ostream &LogFormatter::format(std::ostream &ofs, std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::ptr event)
{
for (auto &i : m_items)
{
i->format(ofs, logger, level, event);
}
return ofs;
}
7.4 FormatItem::format
- 以线程格式化器
ThreadIdFormatItem
为例 - 该方法对应了
LogFormatter::format
中的重载方法二- 可以传入
std::cout
,直接将对应的数据输出到std::cout
中1
2
3
4
5
6
7
8
9class ThreadIdFormatItem : public LogFormatter::FormatItem
{
public:
ThreadIdFormatItem(const std::string &str = "") {}
void format(std::ostream &os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event) override
{
os << event->getThreadId();
}
};
- 可以传入
8. Logger使用示例
1 | void testLog() |