如何在C++程序中全局统一使用Boost Log?
如何在整个程序中优雅复用Boost Log配置
嘿,我完全懂你的困扰——刚接触Boost Log的时候,确实容易纠结怎么在多个类里复用已经配置好的日志,总不能每个类都传logger对象吧?别担心,其实Boost Log设计的时候就考虑到了全局复用的场景,咱们不用搞复杂的传递,几步就能搞定!
首先得明确一个关键点:你在init()函数里配置的日志sink和filter,都是绑定到**全局的日志核心(logging::core::get())**上的。所有后续创建的logger实例,都会自动继承这个核心的配置,不用重复设置。
你之前用src::logger失败的原因
你说尝试过src::logger但没成功,问题出在你的全局filter:
logging::core::get()->set_filter( logging::trivial::severity >= logging::trivial::info );
这个filter要求日志必须带有severity属性,但普通的src::logger是不带severity级别的,所以你的日志会被直接过滤掉!必须用src::severity_logger<severity_level>才能匹配这个filter,这点很重要。
改造你的KGDataFactory类
咱们直接在类里添加一个severity_logger成员,然后在成员函数里直接用就行,不用传任何对象:
修改后的头文件
#include "KGSQLManager.h" #include "KGResult.h" #include "stdafx.h" // 确保包含Boost Log的必要头文件 #include <boost/log/trivial.hpp> #include <boost/log/sources/severity_logger.hpp> namespace KeyGeo { class KGDataFactory { private: // 声明severity logger成员,类型要和main里的一致 boost::log::sources::severity_logger<boost::log::trivial::severity_level> lg; SQLWCHAR *connStr; std::vector<KGResult> results; public: KGDataFactory(); KGSQLManager SQLManager; void parseSourceGeo(); // 不需要initLogs了,全局已经初始化完成 // void initLogs(); }; }
成员函数的日志使用示例
在parseSourceGeo里直接用BOOST_LOG_SEV宏就行,和main里的用法一模一样:
#include "KGDataFactory.h" namespace KeyGeo { KGDataFactory::KGDataFactory() { // 构造函数里也可以打日志 using namespace boost::log::trivial; BOOST_LOG_SEV(lg, info) << "KGDataFactory initialized"; } void KGDataFactory::parseSourceGeo() { using namespace boost::log::trivial; BOOST_LOG_SEV(lg, info) << "Starting to parse source geo data"; // 模拟业务代码,比如遇到警告 BOOST_LOG_SEV(lg, warning) << "Missing optional geo field in record 123"; // 遇到错误 BOOST_LOG_SEV(lg, error) << "Failed to parse geo coordinate: invalid format"; } }
额外补充:补全控制台输出配置
你说需求是同时输出到文件和控制台,但你的init()里只加了文件sink,咱们补全这个配置:
void init() { // 文件sink配置(保持你原来的) logging::add_file_log( keywords::file_name = "KGLog_%N.log", keywords::rotation_size = 10 * 1024 * 1024, keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0), keywords::format = "[%TimeStamp%]: %Message%", keywords::open_mode = std::ios_base::app, keywords::auto_flush = true ); // 添加控制台sink logging::add_console_log( std::cout, keywords::format = "[%TimeStamp%]: %Severity%: %Message%" ); // 全局filter保持不变 logging::core::get()->set_filter( logging::trivial::severity >= logging::trivial::info ); }
其他优雅的小技巧
- 如果不想每个类都定义logger成员,也可以在函数里临时创建:
void some_utility_function() { boost::log::sources::severity_logger<boost::log::trivial::severity_level> lg; BOOST_LOG_SEV(lg, info) << "This works too!"; } - 要是想给不同类的日志加上标识(比如类名),可以给logger添加属性,比如:
这样日志里就会显示哪个类输出的,排查问题更方便。// 在KGDataFactory构造函数里添加 BOOST_LOG(lg) << boost::log::add_value("Class", "KGDataFactory"); // 然后修改format为 "[%TimeStamp%] [%Class%]: %Severity%: %Message%"
放心用吧,这样整个程序里的日志都会自动复用你在init()里配置的输出和过滤规则,不用再到处传递logger对象啦!
内容的提问来源于stack exchange,提问作者divbot
相关产品推荐
相关产品推荐

