码迷,mamicode.com
首页 > 其他好文 > 详细

boost.log(六)格式化

时间:2015-05-07 12:24:21      阅读:132      评论:0      收藏:0      [点我收藏+]

标签:

    如果你尝试运行上一节中的例子,你会发现只有日志记录消息(没有时间戳等属性信息)会被写入到文件。这是因为boost.log库没有设置格式化。即使你添加了属性到boost.log的core或者是记录器中,记录值也不会被输出,除非你指定了这些值的格式。

回到在前面教程一个例子:
  1. #include <iostream>
  2. #include <boost/log/utility/setup/file.hpp>
  3. #include <boost/log/sinks/basic_sink_frontend.hpp>
  4. #include <boost/log/trivial.hpp>
  5. #include <boost/log/core.hpp>
  6. void init()
  7. {
  8. boost::log::add_file_log
  9. (
  10. boost::log::keywords::file_name = "sample_%N.log",
  11. boost::log::keywords::rotation_size = 10 * 1024 * 1024,
  12. boost::log::keywords::time_based_rotation = boost::log::sinks::file::rotation_at_time_point(0, 0, 0),
  13. boost::log::keywords::format = "[%TimeStamp%]: %Message%"
  14. );
  15. boost::log::core::get()->set_filter(boost::log::trivial::severity >= boost::log::trivial::info);
  16. }
    在使用add_file_log函数的情况下,该函数的格式参数允许指定的日志记录格式。如果你喜欢手动设置接收器,记录器frontends供的set_formatter成员函数就是用于这一目的。

格式可以以多种方式来指定,下面进一步描述。

Lambda风格格式化

你可以创建这样一个lambda风格的表达格式:
  1. #include <iostream>
  2. #include <boost/log/utility/setup/file.hpp>
  3. #include <boost/log/sinks/basic_sink_frontend.hpp>
  4. #include <boost/log/trivial.hpp>
  5. #include <boost/log/core.hpp>
  6. #include <boost/log/expressions.hpp>
  7. void init()
  8. {
  9. boost::log::add_file_log
  10. (
  11. boost::log::keywords::file_name = "sample_%N.log",
  12. boost::log::keywords::format =
  13. (
  14. boost::log::expressions::stream
  15. << boost::log::expressions::attr<unsigned int>("LineID")
  16. << ":<" << boost::log::trivial::severity << ">"
  17. << ">" << boost::log::expressions::smessage
  18. )
  19. );
  20. boost::log::core::get()->set_filter(boost::log::trivial::severity >= boost::log::trivial::info);
  21. }

    这里boost::log::expressions::stream是一个日志记录中流格式的占位符。而其它插入参数,如属性和消息,都是在操纵把什么样的属性以什么样的形式保存到流中。我们在过滤表达式中看到了严重等级的占位符(boost::log::trivial::severity),在这里它被用于格式化。这很好统一:你可以在过滤器和格式化中使用同样的占位符。属性占位符类似于严重级别占位符,因为它代表着属性值。不同的是严重级别占位符的名称是“Severity”,类型为boost::log::trivial::severity_level,而属性占位符可以用来表示任何的属性。例如,它可以用下面例子使用属性占位符来替换严重级别占位符:
  1. boost::log::expressions::attr< boost::log::trivial::severity_level >("Severity");
[提示]如前一节所示,你可以像严重级别属性那样定义属性占位符。作为一个好处是模板语法简单,允许集中定义所有属性占位符(名称和值的类型)的信息。这使得编码更不易出错,因此推荐通过上述模板的方式了来定义新的属性。

    还有其它格式化操作(formatter manipulators)提供了时间、日期和其它类型的高级支持。一些操作接收自定义其行为的额外参数,这些大多数参数的命名可以通过Boost.Parameter的方式。

让我们看看在手动初始化接收器的时候它是怎么做的:
  1. #include <fstream>
  2. #include <iomanip>
  3. #include <iostream>
  4. #include <boost/log/core.hpp>
  5. #include <boost/smart_ptr.hpp>
  6. #include <boost/log/trivial.hpp>
  7. #include <boost/log/expressions.hpp>
  8. #include <boost/log/expressions/attr.hpp>
  9. #include <boost/log/utility/setup/file.hpp>
  10. #include <boost/log/sinks/basic_sink_frontend.hpp>
  11. #include <boost/log/sinks/text_ostream_backend.hpp>
  12. void init()
  13. {
  14. typedef boost::log::sinks::synchronous_sink< boost::log::sinks::text_ostream_backend > text_sink;
  15. boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();
  16. sink->locked_backend()->add_stream(boost::make_shared<std::ofstream>("sample.log"));
  17. sink->set_formatter
  18. (
  19. boost::log::expressions::stream
  20. << std::hex << std::setw(8) << std::setfill(‘0‘) << boost::log::expressions::attr< unsigned int >("LineID")
  21. << ": <" << boost::log::trivial::severity
  22. << "> " << boost::log::expressions::smessage
  23. );
  24. boost::log::core::get()->add_sink(sink);
  25. }

你可以看到它能够在表达式中绑定格式更改操作。这些操作会随后影响到日记记录时属性值的格式。

Boost.Format 风格格式化

作为替代方法,您可以定义具有类似于 Boost.Format 语法的格式化程序上文所述的格式化程序可以这样写
  1. #include <fstream>
  2. #include <iomanip>
  3. #include <iostream>
  4. #include <boost/log/core.hpp>
  5. #include <boost/smart_ptr.hpp>
  6. #include <boost/log/trivial.hpp>
  7. #include <boost/log/expressions.hpp>
  8. #include <boost/log/expressions/attr.hpp>
  9. #include <boost/log/utility/setup/file.hpp>
  10. #include <boost/log/sinks/basic_sink_frontend.hpp>
  11. #include <boost/log/sinks/text_ostream_backend.hpp>
  12. void init()
  13. {
  14. typedef boost::log::sinks::synchronous_sink<boost::log::sinks::text_ostream_backend > text_sink;
  15. boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();
  16. sink->locked_backend()->add_stream(boost::make_shared< std::ofstream >("sample.log"));
  17. sink->set_formatter
  18. (
  19. boost::log::expressions::format("%1%: <%2%> %3%")
  20. % boost::log::expressions::attr< unsigned int >("LineID")
  21. % boost::log::trivial::severity
  22. % boost::log::expressions::smessage
  23. );
  24. boost::log::core::get()->add_sink(sink);
  25. }

格式占位符接受所有带有参数位置规范的被格式化的格式字符串。请注意目前仅支持位置格式。相同的格式规范可以用于与add_file_log和类似的函数。

专用格式化器

    Log库提供了大量专业的格式化器,如日期,时间和命名范围。这些格式化器提供控制格式化值的扩展。例如,它是能够与Boost.DateTime的日期和时间格式兼容的字符格式
  1. #include <fstream>
  2. #include <iomanip>
  3. #include <iostream>
  4. #include <boost/log/core.hpp>
  5. #include <boost/smart_ptr.hpp>
  6. #include <boost/log/trivial.hpp>
  7. #include <boost/log/expressions.hpp>
  8. #include <boost/log/expressions/attr.hpp>
  9. #include <boost/log/utility/setup/file.hpp>
  10. #include <boost/log/sinks/basic_sink_frontend.hpp>
  11. #include <boost/log/sinks/text_ostream_backend.hpp>
  12. void init()
  13. {
  14. boost::log::add_file_log
  15. (
  16. boost::log::keywords::file_name = "sample_%N.log",
  17. boost::log::keywords::format =
  18. (
  19. boost::log::expressions::stream
  20. << boost::log::expressions::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S")
  21. << ": <" << boost::log::trivial::severity
  22. << "> " << boost::log::expressions::smessage
  23. )
  24. );
  25. }

同样的格式化器也可以在Boost.Format 风格格式化中使用。

字符串模板格式化器

我们可以接收一个文本模板作为格式化器。在这种情况下,为了解析模板并重建相应的格式化器,会调用boost.log库的解析代码
  1. void init()
  2. {
  3. boost::log::add_file_log
  4. (
  5. boost::log::keywords::file_name = "sample_%N.log",
  6. boost::log::keywords::format = "[%TimeStamp%]: %Message%"
  7. );
  8. }

    在这里,格式参数接收这样一个格式模板,该模板可以包含多个附带百分号(%)的占位符。每个占位符必须包含属性名称来替代某个属性,%Message%占位符将被替换日志记录消息。

[注意]文本格式化模板不能被接收器backendsset_formatter函数接受,但你可以使用parse_formatter函数来做这件事情,这里有更多的介绍。

自定义格式设置功能

你可以根据接收器backends支持的格式化设置添加一个自定义的格式化器。格式化器实际上是支持以下签名的函数对象:
  1. void(boost::log::record_view const& rec, boost::log::basic_formatting_ostream< CharT >& strm);
这里CharT是目标字符类型,每当一个日志记录视图rec通过过滤、日志将被存储时,格式化器会被调用。

[注意]记录视图和记录器非常相似,区别在于记录视图是不可变,并实现浅拷贝。格式化器和接收器只能操作记录视图而不能修改它。

格式化记录应该通过STL兼容的输出流strm来插入组成,下面是一个例子:
  1. #include <fstream>
  2. #include <iomanip>
  3. #include <iostream>
  4. #include <boost/log/core.hpp>
  5. #include <boost/smart_ptr.hpp>
  6. #include <boost/log/trivial.hpp>
  7. #include <boost/log/expressions.hpp>
  8. #include <boost/log/expressions/attr.hpp>
  9. #include <boost/log/utility/setup/file.hpp>
  10. #include <boost/log/sinks/basic_sink_frontend.hpp>
  11. #include <boost/log/sinks/text_ostream_backend.hpp>
  12. void my_formatter(boost::log::record_view const& rec, boost::log::formatting_ostream& strm)
  13. {
  14. strm << boost::log::extract< unsigned int >("LineID", rec) << ": ";
  15. strm << "<" << rec[boost::log::trivial::severity] << "> ";
  16. strm << rec[boost::log::expressions::smessage];
  17. }
  18. void init()
  19. {
  20. typedef boost::log::sinks::synchronous_sink< boost::log::sinks::text_ostream_backend > text_sink;
  21. boost::shared_ptr<text_sink > sink = boost::make_shared< text_sink >();
  22. sink->locked_backend()->add_stream(
  23. boost::make_shared< std::ofstream >("sample.log"));
  24. sink->set_formatter(&my_formatter);
  25. boost::log::core::get()->add_sink(sink);
  26. }
  27. int main()
  28. {
  29. init();
  30. BOOST_LOG_TRIVIAL(debug) << "sadsaas";
  31. system("pause");
  32. return 0;
  33. }

boost.log(六)格式化

标签:

原文地址:http://www.cnblogs.com/zhangpanyi/p/4484303.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!