Boost Log设置旋转和最大文件大小会导致在事先调用Remove_All_Sinks()时添加第二个接收器

时间:2019-02-05 16:37:03

标签: c++ boost-log

使用Boost日志进行记录(duh)-我已成功初始化:

BOOST_LOG_GLOBAL_LOGGER_INIT(logger, logger_t) {
    logger_t lg;
    logging::add_common_attributes();
    boost::shared_ptr< file_sink > sink(new file_sink(
        boost::log::keywords::file_name = "appLog_%N.log",
        boost::log::keywords::rotation_size = 2 * 1024 * 1024,
        boost::log::keywords::max_size = 10 * 1024 * 1024,
        boost::log::keywords::scan_method = 
        boost::log::sinks::file::scan_method::scan_matching,
        boost::log::keywords::open_mode = std::ios_base::app,
        boost::log::keywords::auto_flush = true
    ));

    sink->set_formatter(
        expr::stream
        << expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%dT%H:%M:%S.%fz")
        << ": [" << logging::trivial::severity
        << "]\t" << expr::smessage
    );

    sink->locked_backend()->set_file_collector(boost::log::sinks::file::make_collector(
        boost::log::keywords::target = "",                      /*< the target directory >*/
        boost::log::keywords::max_size = 10 * 1024 * 1024,          /*< maximum total size of the stored files, in bytes >*/
        boost::log::keywords::min_free_space = 1 * 1024 * 1024,   /*< minimum free space on the drive, in bytes >*/
        boost::log::keywords::max_files = 10                       /*< maximum number of stored files >*/
    ));

    sink->locked_backend()->scan_for_files(boost::log::sinks::file::scan_method::scan_matching, true);

    logging::core::get()->add_sink(sink);

    logging::core::get()->set_filter
    (
        logging::trivial::severity >= logging::trivial::info
    );

    return lg;
}

但是,在读入并处理了应用程序的配置文件(包括指定用于记录的 rotation_size max_size 的值)之后,在创建一个指定了rotation_size和max_size值的新接收器只是在现有接收器的顶部添加了一个接收器,该接收器已全局初始化(导致每个消息记录两次)。

更新日志大小的功能如下:

void setLoggerSizes(int rotationSize, int maxSize)
{
    //INFO << "";

    logging::core::get()->remove_all_sinks();

    logging::add_common_attributes();

    boost::shared_ptr< file_sink > sink(new file_sink(
        boost::log::keywords::file_name = "appLog_%N.log",
        boost::log::keywords::rotation_size = rotationSize * 1024 * 1024,
        boost::log::keywords::max_size = maxSize * 1024 * 1024,
        boost::log::keywords::scan_method = boost::log::sinks::file::scan_method::scan_matching,
        boost::log::keywords::open_mode = std::ios_base::app,
        boost::log::keywords::auto_flush = true
    ));

    sink->set_formatter(
        expr::stream
        << expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%dT%H:%M:%S.%fz")
        << ": [" << logging::trivial::severity
        << "]\t" << expr::smessage
    );

    sink->locked_backend()->set_file_collector(
        boost::log::sinks::file::make_collector(
            boost::log::keywords::target = "",
            boost::log::keywords::max_size = maxSize * 1024 * 1024,
            boost::log::keywords::min_free_space = 1 * 1024 * 1024
        )
    );

    sink->locked_backend()->scan_for_files();   

    logging::core::get()->add_sink(sink);
}

但是,如果我在函数的开头添加INFO << "";,这似乎会强制删除所有接收器,并且在添加具有正确文件大小的接收器时,会导致单个接收器(因此)仅将邮件的一个副本传递到日志)。

因此,我的问题是:

  1. INFO << "";为什么会发生这种情况?对于为什么添加该行会真正强制删除所有在下一行中调用的接收器并没有逻辑意义,因此导致只记录一条消息。而不包括INFO行,就像logging::core::get()->remove_all_sinks();调用被忽略一样,并且以正确文件大小添加的接收器将添加到初始化接收器的顶部,并导致每个消息的两个副本被记录。
  2. 如果我现在不这样做,如何在维护全局记录器的同时正确设置旋转度和最大尺寸?

作为参考,这是Logger.h文件:

#pragma once

#include <boost/log/expressions.hpp>
#include <boost/log/sources/global_logger_storage.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup.hpp>

#define FATAL  BOOST_LOG_SEV(logger::get(), boost::log::trivial::fatal)
#define WARNING  BOOST_LOG_SEV(logger::get(), boost::log::trivial::warning)
#define INFO BOOST_LOG_SEV(logger::get(), boost::log::trivial::info)
#define DEBUG BOOST_LOG_SEV(logger::get(), boost::log::trivial::debug)
#define TRACE BOOST_LOG_SEV(logger::get(), boost::log::trivial::trace)

typedef boost::log::sources::severity_logger_mt<boost::log::trivial::severity_level> logger_t;
typedef boost::log::sinks::synchronous_sink< boost::log::sinks::text_file_backend > file_sink;

BOOST_LOG_GLOBAL_LOGGER(logger, logger_t)

void setLoggerSizes(int rotationSize, int maxSize);

1 个答案:

答案 0 :(得分:0)

您看到的问题很可能是由于程序中日志记录语句的执行顺序所致。

当程序第一次请求全局记录器时,BOOST_LOG_GLOBAL_LOGGER_INIT和类似的BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT的主体将执行一次(请参见here)。因此,由于您是从INFO宏中请求记录器,因此在调用remove_all_sinks并进一步初始化日志记录库之前,将执行该正文。当您注释该行时,该初始化将推迟到您的第一个执行的日志记录语句(大概在setLoggerSizes返回之后执行)中进行。因此,remove_all_sinks无效,因为在该调用时没有要删除的接收器。

_INIT宏实际上是用来初始化 logger 的,而不是初始化整个日志库的(即接收器,过滤器等)。您可以从这些宏中初始化库,但是,正如您所发现的那样,它的用处是相当有限的(基本上,除非您只有一个全局记录器,否则它可能无法按预期工作,这也是您唯一的记录器)可以在整个应用程序中使用,并且无需在初始化日志记录后对其进行更新)。正确的方法是在一个函数中单独初始化日志记录库,该函数将在main中提前调用,并使用_INIT宏仅初始化记录器。