引言
日志对于程序来说是非常重要的,特别是对一些大型程序而言。一旦程序被发布,在现场日志几乎是程序员唯一可以获取程序信息的手段。
使用步骤
- 1 生成消息
- 2 写入logger
- 3 导入channel
- 4 写文件
生成消息
POCO使用Poco::Message 对象存储和传递日志信息。
#include “Poco/Message.h”
日志消息(Message)包括:
- 优先级(priority):定义八个消息优先级
- 消息源(source):描述一个日志的消息源
- 文本(text):实际的消息将被记录。
- 时间戳(timestamp):创建的日期和时间信息,微秒精度。
- 进程和线程标识符
- 可选参数<名称-值>对
此处只列出一个,具体查看文档
优先级(priority)
POCO的定义八个消息优先级:
- PRIO_FATAL (最高优先级)
- PRIO_CRITICAL
- PRIO_ERROR
- PRIO_WARNING
- PRIO_NOTICE
- PRIO_INFORMATION
- PRIO_DEBUG
- PRIO_TRACE (最低优先级)
**API接口:**
//可以通过函数设置和获取消息优先级:
void setPriority(Priority prio)
Priority getPriority() const
日志类(Logger)
POCO::Logger 是日志框架的主入口点。
#include “Poco/Logger.h”
- 应用程序使用POCO::Logger类的实例生成日志消息。
- 每一个日志附属通道(channel),通道用于传递消息。
- 每一个日志都拥有一个名称,名称用于表示消息源。日志名称设置有不能改变。
层次结构(Logger Hierarchy) - 日志名称可由一个或多个日志组件组成,各个日志组件有自己独立的名称范围。
- 每个日志组件的名称都会包含上级日志组件的名称。树型结构的根是名称为空的日志组件。
- 树型结构没有最大深度的限制。
|---- "" (the root logger)
|
|-----"HTTPServer"
|
|-----"HTTPServer.RequestHandler"
|
|-----"HTTPServer.RequestHandler.File"
|
|-----"HTTPServer.RequestHandler.CGI"
|
|------"HTTPServer.Listener"
//!."HTTPServer.RequestHandler.CGI" 继承"HTTPServer.RequestHandler"的级别和通道
访问日志对象
- POCO库在内部全局管理日志。用户不用创建日志对象,只要从POCO库获取日志引用。
- POCO根据需要创建新的日志。
- static Logger& get(const std::string&
name),获取POCO提供的名为name的日志引用,这个日志由POCO内部创建。保存获得的日志引用是安全的。
#include "Poco/Logger.h"
using Poco::Logger;
int main(int argc, char** argv)
{
Logger& logger = Logger::get("MyLogger");
logger.information("This is an informational message");
logger.warning("This is a warning message");
return 0;
}
通道类(Channels)
- Poco::Channel的子类负责传递消息到目的地(如控制台、日志文件)。
- Poco::Logger也是Poco::Channel的子类,Poco::Logger与Poco::Channel连接。
- POCO提供有多个Poco::Channel子类,使用不同的子类可以把消息发送到控制台、日志文件或系统日志服务。
- 用户可以定义自己的Channel类。
- Channel使用应用计数进行内存管理(智能指针)
通道属性
- 通道提供任意数量的可配置属性(“名称-值”对)。
void setProperty(const std::string& name, const std::string& value)
std::string getProperty(const sdt::string& name)
例如文件通道(FileChannel),使用智能指针管理内存
//name属性 说明
//path 主文件路径
//secondaryPath 备用文件路径。默认为<path>.1
void setProperty(const std::string& name, const std::string& value);
- 在文件中追加一行消息文本。
- 文件轮换支持基于文件大小或时间间隔方式进行。
- 支持文件自动归档、压缩和清除
#include "Poco/FileChannel.h"
//实例化
AutoPtr模板类,类型为PatternFormatter
AutoPtr<PatternFormatter> formatter(new PatternFormatter);
formatter->setProperty("times","local");
formatter->setProperty("pattern","%Y-%m-%d-%m-%d %H:%M:%s-%Y:%t");
file_channel>setProperty("path",switchFileName(logFilename));
控制台通道(ConsoleChannel)
- Poco::ConsoleChannel是最基本的通道实现。
- 将消息文本输出到标准输出(std::clog)不具备配置属性根日志的默认通道
AutoPtr<ConsoleChannel> console_channel(new ConsoleChannel);
分发通道(SplitterChannel)
- Poco::SplitterChannel将消息分发到一个或多个通道。
void addChannel(Channel* pChannel)//添加一个新通道到Poco::SplitterChannel
#include "Poco/SplitterChannel.h"
AutoPtr<SplitterChannel> splitter_Channel(new SplitterChannel);
splitter_Channel->addChannel(file_channel);
splitter_Channel->addChannel(console_channel);
日志流类(LogStream)
- Poco::LogStream给Logger提供一个流(ostream)接口。
- 所有流(ostream)的特性都能用于格式化日志消息。
- 日志流的消息必须以std::endl(或CR、LF字符)结尾。
#include "Poco/LogStream.h"
日志消息格式化(Message Formatting)
- Poco::FormattingChannel与Poco::Formatter用于格式化日志消息。
- Poco::FormattingChannel收到消息后,将消息先通过Poco::Formatter处理,然后输出到下一个通道。
- Poco::Formatter i是所有格式化类的基类。channels,formatters都是可配置的。
#include "Poco/FormattingChannel.h"
#include "Poco/Formatter.h"
AutoPtr<PatternFormatter> pattern_formatter (new PatternFormatter("%L%H:%M:%S-code line :%u-%U : %t"));
AutoPtr<FormattingChannel> formatter_channle(new FormattingChannel(pattern_formatter , file_channel));
模式格式化类(PatternFormatter)
- Poco::PatternFormatter使用打印模式格式化消息。
性能注意事项
- 创建消息会消耗一些时间(需要判断当前时间、进程ID和线程ID。
- 创建有意义的消息可能消耗更多的时间,因为需要文本拼接、格式化等必须的操作。
- 消息文本通过通道链传输。
- FormattingChannel和AsyncChannel会创建消息copy。
- 记录日志经常会为每个日志启用或禁用日志(或者,更正确来说,设置日志级别),如果你拥有一个日志引用,那么使用日志引用来判断日志级别,是一个常数时间操作。
- 通常,只需要在应用程序中做一次获取日志引用(Logger::get())操作。例如在类的构造函数中获取日志引用,然后使用日志对象的引用。
- 用户应当避免频繁调用Logger::get()。最好是调用一次、保存下来,然后使用。
- 日志的性能依赖于通道。
- 构造日志消息需要一定的时间消耗。
- 因此,建议在构造消息前,首先使用 is(), fatal(), critical()等接口核实是否需要构建。
- POCO提供用于核实构造消息的宏:poco_fatal(msg), poco_critical(msg),poco_error(msg)等等。