Boost使用旋转记录多个文件

时间:2016-04-30 12:21:55

标签: c++ logging boost

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

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

所以我的想法是实现一个日志类并为每个组件做一个瞬间并将它们存储在一个映射中,这样我就可以使用map来获取正确的logger实例(根据名称)并登录到正确的文件。

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

这是我的代码草稿:

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;
};

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();
}

有可能实现我想要的目标吗?

1 个答案:

答案 0 :(得分:1)

请参阅this回复。除此之外,它还介绍了如何使用通道和过滤器来实现您的目标。