Boost 日志 设置属性
结构图
简 介
- 每条日志记录都可以有很多与之关联的属性
- 属性可以是任何与日志记录产生条件有关的信息,如在代码中的位置、当前日期和时间等
- 属性除了可以固定值之外,也可以是一个值生成器
- 根据作用域分类:日志源级 < 线程级 < 全局级
- 日志记录生成时三类属性合并在一起并传递给槽
- 同一作用域内的属性名必须不同,不同作用域内的属性名可以相同
- 不同作用域内若存在相同名称的属性,则使用最具体作用域的属性
常用属性
- 几乎在所有程序中都要用的属性,如时间戳
- 添加方法:logging::add_common_attributes();
- 行号、时间戳、进程ID和线程ID(除单线程程序)属性被全局注册
- 某些属性会在日志源创建时自动注册,如severity_logger
更多属性细节
void add_common_attributes()
{
boost::shared_ptr< logging::core > core = logging::core::get();
core->add_global_attribute("LineID", attrs::counter< unsigned int >(1));
core->add_global_attribute("TimeStamp", attrs::local_clock());
// other attributes skipped for brevity
}
- counter, local_clock都是属性类
- 属性类都实现attribute接口
- 日志库很多其他属性类
示例1
#include <ostream>
#include <fstream>
#include <iomanip>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/sources/basic_logger.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
namespace logging = boost::log;
namespace src = boost::log::sources;
namespace expr = boost::log::expressions;
namespace sinks = boost::log::sinks;
namespace attrs = boost::log::attributes;
namespace keywords = boost::log::keywords;
// We define our own severity levels
enum severity_level
{
normal,
notification,
warning,
error,
critical
};
BOOST_LOG_ATTRIBUTE_KEYWORD(line_id, "LineID", unsigned int)
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", severity_level)
BOOST_LOG_ATTRIBUTE_KEYWORD(scope, "Scope", attrs::named_scope::value_type)
// The operator puts a human-friendly representation of the severity level to the stream
std::ostream& operator<< (std::ostream& strm, severity_level level)
{
static const char* strings[] =
{
"normal",
"notification",
"warning",
"error",
"critical"
};
if (static_cast<std::size_t>(level) < sizeof(strings) / sizeof(*strings))
strm << strings[level];
else
strm << static_cast<int>(level);
return strm;
}
void logging_function()
{
BOOST_LOG_NAMED_SCOPE("named_scope_logging");
// The logger implicitly adds a source-specific attribute 'Severity'
// of type 'severity_level' on construction
src::severity_logger< severity_level > slg;
BOOST_LOG_SEV(slg, normal) << "A regular message";
BOOST_LOG_SEV(slg, warning) << "Something bad is going on but I can handle it";
BOOST_LOG_SEV(slg, critical) << "Everything crumbles, shoot me now!";
}
void init()
{
typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;
boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();
sink->locked_backend()->add_stream(
boost::make_shared< std::ofstream >("sample.log"));
sink->set_formatter
(
expr::stream
<< std::hex << std::setw(8) << std::setfill('0') << line_id << std::dec << std::setfill(' ')
<< ": <" << severity << ">\t"
<< "(" << scope << ")\t"
<< expr::smessage
);
logging::core::get()->add_sink(sink);
// Add attributes
logging::add_common_attributes();
logging::core::get()->add_global_attribute("Scope", attrs::named_scope());
}
int main()
{
init();
logging_function();
}
函数属性
core->add_global_attribute("Scope", attrs::named_scope());
void named_scope_logging()
{
BOOST_LOG_NAMED_SCOPE("named_scope_logging");
src::severity_logger< severity_level > slg;
BOOST_LOG_SEV(slg, normal) << "Hello from the function named_scope_logging!";
}
- 函数属性:当获取其值时会调用某些函数对象
- 上面的代码使每个日志记录在日志中包含作用域名称
日志源级别属性
void tagged_logging()
{
src::logger lg;
BOOST_LOG(lg) << "普通日志记录";
lg.add_attribute("Tag", attrs::constant< std::string >("编程小强"));
BOOST_LOG(lg) << "带标签的日志记录";
}
- 特定于日志源的属性与全局属性一样有用
- 严重级别和通道名称就很适合成为日志源级属性
- 可以如上面代码一样向日志添加更多属性
示例2
#include <ostream>
#include <fstream>
#include <iomanip>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/sources/logger.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
namespace logging = boost::log;
namespace src = boost::log::sources;
namespace expr = boost::log::expressions;
namespace sinks = boost::log::sinks;
namespace attrs = boost::log::attributes;
namespace keywords = boost::log::keywords;
//定义属性关键字
BOOST_LOG_ATTRIBUTE_KEYWORD(line_id, "LineID", unsigned int)
BOOST_LOG_ATTRIBUTE_KEYWORD(tag_attr, "Tag", std::string)
void tagged_logging()
{
src::logger lg;
BOOST_LOG(lg) << "普通日志记录";
lg.add_attribute("Tag", attrs::constant< std::string >("Version 1.0"));
BOOST_LOG(lg) << "带标签的日志记录";
}
void init()
{
typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;
boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();
sink->locked_backend()->add_stream(
boost::make_shared< std::ofstream >("sample.log"));
sink->set_formatter
(
expr::stream
<< std::hex << std::setw(8) << std::setfill('0') << line_id << std::dec << std::setfill(' ') << "\t"
<< expr::if_(expr::has_attr(tag_attr)) //添加标签部分的格式化
[
expr::stream << "[" << tag_attr << "] "
]
<< expr::smessage
);
logging::core::get()->add_sink(sink);
//添加属性
logging::add_common_attributes();
}
int main()
{
init();
tagged_logging();
}
时间线属性
void timed_logging()
{
BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
src::severity_logger< severity_level > slg;
BOOST_LOG_SEV(slg, normal) << "Starting to time nested functions";
logging_function();
BOOST_LOG_SEV(slg, normal) << "Stopping to time nested functions";
}
- 属性的另一个很好的用途是能够标记应用程序不同部分生成的日志记录,以突出显示与单个流程相关的活动。
- 上面函数中生成的记录包含一个“时间线” 属性:从该属性被注册后到生成日志时高精度的时间戳
- 通过“时间线”属性,可以确定程序各个部分执行花费的时间
- 离开该函数之后,“时间线”属性会被自动注销
示例3
#include <ostream>
#include <fstream>
#include <iomanip>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/sources/logger.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/attributes/scoped_attribute.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
namespace logging = boost::log;
namespace src = boost::log::sources;
namespace expr = boost::log::expressions;
namespace sinks = boost::log::sinks;
namespace attrs = boost::log::attributes;
namespace keywords = boost::log::keywords;
//定义属性关键字
BOOST_LOG_ATTRIBUTE_KEYWORD(line_id, "LineID", unsigned int)
BOOST_LOG_ATTRIBUTE_KEYWORD(timeline, "Timeline", attrs::timer::value_type)
void nested_logging(src::logger & lg)
{
Sleep(100);
BOOST_LOG(lg) << "睡眠100ms";
Sleep(200);
BOOST_LOG(lg) << "睡眠200ms";
}
void timed_logging()
{
BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
src::logger lg;
BOOST_LOG(lg) << "开始对嵌套函数计时";
nested_logging(lg);
BOOST_LOG(lg) << "结束对嵌套函数计时";
}
void init()
{
typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;
boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();
sink->locked_backend()->add_stream(
boost::make_shared< std::ofstream >("sample.log"));
sink->set_formatter
(
expr::stream
<< std::hex << std::setw(8) << std::setfill('0') << line_id << std::dec << std::setfill(' ') << "\t"
<< expr::if_(expr::has_attr(timeline))
[
expr::stream << "[" << timeline << "] "
]
<< expr::smessage
);
logging::core::get()->add_sink(sink);
//添加属性
logging::add_common_attributes();
}
int main()
{
init();
src::logger lg;
BOOST_LOG(lg) << "普通日志记录";
timed_logging();
}
定义属性占位符
BOOST_LOG_ATTRIBUTE_KEYWORD(line_id, "LineID", unsigned int)
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", severity_level)
BOOST_LOG_ATTRIBUTE_KEYWORD(tag_attr, "Tag", std::string)
BOOST_LOG_ATTRIBUTE_KEYWORD(scope, "Scope", attrs::named_scope::value_type)
BOOST_LOG_ATTRIBUTE_KEYWORD(timeline, "Timeline", attrs::timer::value_type)
- 定义描述应用程序使用的特定属性的关键字很有用
- 关键字将参与过滤和格式化表达式,如使用的严重级别占位符。
- 上面的程序为前面的示例中使用的某些属性定义占位符
- BOOST_LOG_ATTRIBUTE_KEYWORD宏定义属性关键字
- 第一个参数:占位符名称;第二个参数:属性名称;最后一个参数:属性值类型
- 属性占位符可以在模板表达式和库的其他一些上下文中使用。