【问题标题】:Boost.Log - how to configure text_file_backend with append and rotateBoost.Log - 如何使用追加和旋转配置 text_file_backend
【发布时间】:2018-09-08 12:57:12
【问题描述】:

如何创建附加到现有文件但也有轮换的 text_file_backend? 我这样做了,但每次运行程序时都会创建一个新文件。

  1. App.log
  2. App.log00000
  3. App.log00001
  4. 等等等等....

    boost::log::add_file_log
    (
        boost::log::keywords::auto_flush          = true,
        boost::log::keywords::target              = "Log",        
        boost::log::keywords::file_name           = "App.log",                                                  // file name pattern  eg: keywords::file_name = "app%m%d%Y_%H%M%S_%5N.log",    
        boost::log::keywords::open_mode           = std::ios::out | std::ios::app,                              // append mode 
        boost::log::keywords::rotation_size       = 10 * 1024 * 1024,                                           // rotate files every 10 MBytes
        boost::log::keywords::time_based_rotation = boost::log::sinks::file::rotation_at_time_point(0, 0, 0),   // ...or at midnight
    .....
    

还有什么我可以尝试的吗?

谢谢

【问题讨论】:

  • 请让示例独立。经验告诉我这将在启动时轮换。但是,检查您的特定样本是否确实表现出令人惊讶的行为实在是太乏味了

标签: c++ logging boost


【解决方案1】:

使用target 参数,您将目标目录配置为不同于最初写入日志文件的目录(file_name 参数),这意味着在轮换时文件将被移动。由于文件名不包含可以区分文件的占位符,因此新文件与之前轮换后留在目标目录中的文件发生冲突,并附加了一个反后缀以避免冲突。

仅当接收器后端打开由file_name 标识的文件并且该文件已经存在时,附加才有效。它不会使文件在旋转时附加到目标目录中的现有文件,这是不可能的。由于在您的情况下,旋转每次都会将文件移开,因此永远不会发生追加。

为了使追加和旋转都起作用,您必须确保 (a) 接收器后端写入的前一个文件保留在同一目录中,并且与新接收器尝试打开的名称相同,并且 (b)文件名包含一些占位符,因此每次旋转都会生成一个新文件名。这些是相互矛盾的要求,但某些配置可以满足它们。例如,您可以将目标目录配置为与后端写入日志文件的位置相同,文件名包含日期并在每天午夜轮换。

boost::log::add_file_log
(
    boost::log::keywords::auto_flush          = true,
    boost::log::keywords::target              = "Log",        
    boost::log::keywords::file_name           = "Log/App_%Y%m%d.log",
    boost::log::keywords::open_mode           = std::ios::out | std::ios::app,
    boost::log::keywords::time_based_rotation = boost::log::sinks::file::rotation_at_time_point(0, 0, 0)
);

请注意,文件计数器和文件大小旋转不适用于追加,因为它们往往违反我列出的要求之一。

【讨论】:

  • 我看到 boost (sourceforge.net/p/boost-log/discussion/710022/thread/a5b15460) 不支持附加到最后一个旋转的日志文件。由于这个讨论很老,只是想检查一下,现在支持吗?如果有怎么实现?
  • 支持,但前提是新打开的文件名与上次写入的文件名完全相同。您需要将std::ios_base::app 传递给text_file_backend::set_open_mode (boost.org/doc/libs/1_68_0/libs/log/doc/html/boost/log/sinks/…)。
  • 我通过对文件名使用 %N% 修饰符来使用基于大小的旋转。我正在使用logging::add_file_log 打开文件接收器。我设置了target(与日志文件相同的文件夹)、file_name(名称_%N%.log)、rotation_size(10MB)、auto_flush(真)和open_modestd::ios_base::app)。使用此设置如何打开最后修改的文件?我需要使用基于时间的轮换来让它工作吗?
  • 如果您在启动时不扫描较早的文件,则文件计数器将为 0,因此如果存在与计数器 0 的模式匹配的文件,则将附加该文件。这可能不是您想要的,如果您的应用程序的先前运行中存在具有更大计数器值的文件,则肯定不是。如果您扫描文件,初始计数器值将在找到的文件中最后一个计数器之后,因此不会发生追加。这意味着计数器不太适合追加。在这种情况下,文件名模式中的日期/时间而不是计数器可能会有所帮助。
  • 如果我不使用计数器作为文件名,文件轮换将不会发生。它忽略rotation_size 并继续写入同一个日志文件。我的第一个要求是file rotation 应该可以工作。其次,它应该append 重新启动进程时的最后一个日志文件。看起来我无法通过此配置满足第二个要求。当进程重新启动时,我将使用新的日志文件。
【解决方案2】:

您需要将keywords::enable_final_rotation 设置为false(例如here),以便在您的进程退出时不旋转。
这样,下次您的进程启动时,如果文件由于大小/时间规则而没有旋转,它将附加到它。

另外,我建议使用模式设置keywords::target_file_name(例如"App_%Y%m%d_%H%M%S_%5N.log"),以便旋转文件具有不同的名称(在这种情况下包含日期和索引)。
如果您不这样做,您将拥有最多 1 个旋转文件 (Log/App.log),该文件将被下一个旋转文件覆盖。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-15
    • 1970-01-01
    • 1970-01-01
    • 2012-07-27
    • 2014-11-08
    • 1970-01-01
    • 2018-01-06
    • 1970-01-01
    相关资源
    最近更新 更多