Boost通过旋转记录多个文件

Boost Log multiple files with rotation

本文关键字:文件 记录 旋转 Boost      更新时间:2023-10-16

我的应用程序有几个组件,我希望每个组件都将日志写入一个单独的文件。

我想使用"文本多文件后端",但根据文档,它不支持文件旋转。

因此,我的想法是实现一个日志类,为每个组件创建一个即时消息,并将它们存储在映射中,这样我就可以使用映射来获得正确的记录器实例(根据名称)并记录到正确的文件中。

我已经这样做了,但这对我来说不起作用,我可以在所有文件中看到相同的消息(似乎这是一个全局记录器)。

这是我的代码草案:

logger.h

struct LogInfo{
    std::string log_path;
    LogLevel log_level;
    long log_file_size;
    int log_file_amount;
};
LogLevel stringToLogLevel(const std::string &fileType);
class Logger {
public:
    Logger(const LogInfo &log_info, const std::string &component_name);
    void writeToLog(LogLevel log_level, const std::string &scope, const std::string &message);
private:
    void scanForFiles(const std::string &path, const std::string &component_name);
    std::string pid;
    std::string log_file_name;
    boost::log::sources::severity_logger<boost::log::trivial::severity_level> boost_severity_logger;
};

记录器.cpp

using namespace boost::log;
using namespace std;
namespace fs = boost::filesystem;
LogLevel stringToLogLevel(const string &fileType) {
    if (fileType == "TRACE")
        return LOGLEVEL_TRACE;
    if (fileType == "DEBUG")
        return LOGLEVEL_DEBUG;
    if (fileType == "INFO")
        return LOGLEVEL_INFO;
    if (fileType == "WARNING")
        return LOGLEVEL_WARNING;
    if (fileType == "ERROR")
        return LOGLEVEL_ERROR;
    throw invalid_argument("Unknown file type");
}
trivial::severity_level logLevelToBoostLogLevel(const LogLevel log_level) {
    if (log_level == LOGLEVEL_TRACE)
        return trivial::trace;
    if (log_level == LOGLEVEL_DEBUG)
        return trivial::debug;
    if (log_level == LOGLEVEL_INFO)
        return trivial::info;
    if (log_level == LOGLEVEL_WARNING)
        return trivial::warning;
    if (log_level == LOGLEVEL_ERROR)
        return trivial::error;
    throw invalid_argument("Unknown log type");
}
Logger::Logger(const LogInfo &log_info, const string &component_name) {
    scanForFiles(log_info.log_path, component_name);
    stringstream s;
    s << log_info.log_path << component_name << "_%N.log";
    add_file_log(
        keywords::file_name = s.str(),
        keywords::rotation_size = log_info.log_file_size,
        keywords::max_size = log_info.log_file_amount * log_info.log_file_size,
        keywords::target = log_info.log_path,
        keywords::open_mode = std::ios::out | std::ios::app,
        keywords::auto_flush = true,
        keywords::format =
        expressions::format("[%1%] [%2%] [%3%] [%4%] %5%")
        % expressions::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S.%f")
        % expressions::attr<unsigned int>("ThreadID")
        % expressions::attr<string>("Scope")
        % trivial::severity
        % expressions::smessage
    );
    trivial::severity_level requested_level = logLevelToBoostLogLevel(log_info.log_level);
    core::get()->set_filter(
        trivial::severity >= requested_level
    );
    add_common_attributes();
}
void Logger::writeToLog(LogLevel log_level, const std::string &scope, const std::string &message) {
    BOOST_LOG_SCOPED_THREAD_ATTR("ThreadID", attributes::constant<unsigned int>(OS::getTid()));
    BOOST_LOG_SCOPED_THREAD_ATTR("Scope", attributes::constant<string>(scope));
    BOOST_LOG_SEV(this->boost_severity_logger, logLevelToBoostLogLevel(log_level))<< message.c_str();
}

有可能实现我想要的吗?

请参阅此回复。除其他外,它还描述了如何使用通道和过滤器来实现您想要的内容。

要分离日志文件,您可以在添加的日志文件中添加过滤器,这样文件旋转就可以正常工作,并且每个组件都有自己的日志文件:

logging::add_file_log(
        keywords::file_name = s.str(),
        keywords::rotation_size = log_info.log_file_size,
        keywords::max_size = log_info.log_file_amount * log_info.log_file_size,
        keywords::filter = expr::attr< std::string >([ATTRIBUTE/TAG]) == [ex. COMPONENT_NAME],
        keywords::target = log_info.log_path,
        keywords::open_mode = std::ios::out | std::ios::app,
        keywords::auto_flush = true,
        keywords::format =
        expressions::format("[%1%] [%2%] [%3%] [%4%] %5%")
        % expressions::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S.%f")
        % expressions::attr<unsigned int>("ThreadID")
        % expressions::attr<string>("Scope")
        % trivial::severity
        % expressions::smessage
    );

在记录时,应该设置属性,这样消息就会写在相应的日志文件上,例如:

void Logger::writeToLog(LogLevel log_level, const std::string &scope, const std::string &message) {
...
BOOST_LOG_SCOPED_THREAD_TAG([ATT/TAG], [VALUE]); // Add Component name here
    BOOST_LOG_SEV(this->boost_severity_logger, logLevelToBoostLogLevel(log_level))<< message.c_str();
}