Boost 日志 'text_file_backend' - 按需轮换文件
Boost log 'text_file_backend' - rotate file on demand
我想涵盖当我的进程崩溃或只是没有正常关闭并且日志没有轮换时的情况。
2个具体案例:
- 如果我为我的日志文件使用固定名称(例如
keywords::file_name = "app.log"
)并且进程没有管理在关闭时轮换日志(假设它崩溃了),那么当它重新启动时,它将从崩溃的实例中覆盖我的 app.log
。这很糟糕,因为该日志特别有趣。
- 如果我为我的日志文件使用自定义名称(例如
keywords::file_name = "app_%Y%m%d_%H%M%S_%5N.log"
)并且该进程在关闭时无法轮换日志,那么当它重新启动时它将创建一个新的 app_YMD_HMS_5N.log
同时将上一个日志文件保留在同一文件夹中 (~/logs
) 而不是将其移至历史记录 (bl::keywords::target = "~/logs/history"
)。这也很糟糕,因为 logs
文件夹变得混乱,并且因为 只有 旋转文件夹 e.i。目标 (logs/history
) 受到 max_size
约束的监控,因此 logs
文件夹可能会不受控制地增长。
在调查之后,我得出的结论是我会做以下事情:
- 为日志文件取一个固定名称(例如
keywords::file_name = "app.log"
)
- 为轮换的日志文件设置一个带有日期和索引的自定义名称,以便能够拥有多个日志文件(例如
keywords::target_file_name = "app_%Y%m%d_%H%M%S_%5N.log"
。
- 打开日志文件进行附加 (
keywords::open_mode = std::ios_base::app
)。
- 打开日志文件后,立即在
text_file_backend
上调用 rotate_file()
以轮换 non empty
app.log
(如果之前的应用实例没有管理正确关闭记录器)。
问题是rotate_file()
没有效果。我调用的时候日志文件没有轮换
我做错了什么吗?
以下是我设置文件同步的方法:
// File log
auto file_sink = bl::add_file_log(bl::keywords::target = "history",
bl::keywords::file_name = "app.log"),
bl::keywords::target_file_name= "app_%Y%m%d_%H%M%S_%5N.log"),
bl::keywords::rotation_size = 25 * 1024 * 1024,
bl::keywords::max_size = 250 * 1024 * 1024,
bl::keywords::auto_flush = true,
bl::keywords::open_mode = std::ios_base::app,
bl::keywords::max_files = 10);
file_sink->set_formatter(log_fmt);
file_sink->set_filter(bl::trivial::severity >= level);
// In case the previous log was not rotated on shutdown (it's not empty), rotate it now
file_sink->locked_backend()->rotate_file(); // NOT DOING ANYTHING!
为了保持一致性,我还考虑在关闭时禁用旋转 (keywords::enable_final_rotation = false
),以便仅在启动时旋转日志文件,而不管我的应用程序如何终止(崩溃、kill -9、正确关闭。 ..) 但要做到这一点,我首先需要能够在启动时轮换日志。
正如 Andrey Semashev 所提到的,为了 rotate_file()
正常工作,您首先需要记录一些内容,以便实际打开日志文件。
考虑到这一点,我在记录器初始化期间(在应用程序启动时)执行以下操作:
- 关闭时禁用轮换 (
keywords::enable_final_rotation = false
) - 对于没有崩溃的情况,我们不会进行额外的空文件轮换(在所有情况下轮换都是在启动或点击 collector limits
).
- 打开文件进行追加 (
bl::keywords::open_mode = std::ios_base::app
)
- 记录类似“按需旋转记录器”的内容
- 调用
rotate_file()
- 这将在打开日志文件后进行轮换。
外观如下:
// File log
auto file_sink
= bl::add_file_log(bl::keywords::target = "history",
bl::keywords::file_name = "app.log",
bl::keywords::target_file_name = "app_%Y%m%d_%H%M%S_%5N.log",
bl::keywords::rotation_size = 10 * 1024 * 1024,
bl::keywords::open_mode = std::ios_base::app, // Open for append and immediately rotate
bl::keywords::enable_final_rotation = false // Rotate only on startup to cover also the crash / kill cases
);
// Log something so the logger opens the file
BOOST_LOG_TRIVIAL(info) << "Rotating logs on startup";
// Do the rotation on demand
file_sink->locked_backend()->rotate_file();
我想涵盖当我的进程崩溃或只是没有正常关闭并且日志没有轮换时的情况。
2个具体案例:
- 如果我为我的日志文件使用固定名称(例如
keywords::file_name = "app.log"
)并且进程没有管理在关闭时轮换日志(假设它崩溃了),那么当它重新启动时,它将从崩溃的实例中覆盖我的app.log
。这很糟糕,因为该日志特别有趣。 - 如果我为我的日志文件使用自定义名称(例如
keywords::file_name = "app_%Y%m%d_%H%M%S_%5N.log"
)并且该进程在关闭时无法轮换日志,那么当它重新启动时它将创建一个新的app_YMD_HMS_5N.log
同时将上一个日志文件保留在同一文件夹中 (~/logs
) 而不是将其移至历史记录 (bl::keywords::target = "~/logs/history"
)。这也很糟糕,因为logs
文件夹变得混乱,并且因为 只有 旋转文件夹 e.i。目标 (logs/history
) 受到max_size
约束的监控,因此logs
文件夹可能会不受控制地增长。
在调查之后,我得出的结论是我会做以下事情:
- 为日志文件取一个固定名称(例如
keywords::file_name = "app.log"
) - 为轮换的日志文件设置一个带有日期和索引的自定义名称,以便能够拥有多个日志文件(例如
keywords::target_file_name = "app_%Y%m%d_%H%M%S_%5N.log"
。 - 打开日志文件进行附加 (
keywords::open_mode = std::ios_base::app
)。 - 打开日志文件后,立即在
text_file_backend
上调用rotate_file()
以轮换non empty
app.log
(如果之前的应用实例没有管理正确关闭记录器)。
问题是rotate_file()
没有效果。我调用的时候日志文件没有轮换
我做错了什么吗?
以下是我设置文件同步的方法:
// File log
auto file_sink = bl::add_file_log(bl::keywords::target = "history",
bl::keywords::file_name = "app.log"),
bl::keywords::target_file_name= "app_%Y%m%d_%H%M%S_%5N.log"),
bl::keywords::rotation_size = 25 * 1024 * 1024,
bl::keywords::max_size = 250 * 1024 * 1024,
bl::keywords::auto_flush = true,
bl::keywords::open_mode = std::ios_base::app,
bl::keywords::max_files = 10);
file_sink->set_formatter(log_fmt);
file_sink->set_filter(bl::trivial::severity >= level);
// In case the previous log was not rotated on shutdown (it's not empty), rotate it now
file_sink->locked_backend()->rotate_file(); // NOT DOING ANYTHING!
为了保持一致性,我还考虑在关闭时禁用旋转 (keywords::enable_final_rotation = false
),以便仅在启动时旋转日志文件,而不管我的应用程序如何终止(崩溃、kill -9、正确关闭。 ..) 但要做到这一点,我首先需要能够在启动时轮换日志。
正如 Andrey Semashev 所提到的,为了 rotate_file()
正常工作,您首先需要记录一些内容,以便实际打开日志文件。
考虑到这一点,我在记录器初始化期间(在应用程序启动时)执行以下操作:
- 关闭时禁用轮换 (
keywords::enable_final_rotation = false
) - 对于没有崩溃的情况,我们不会进行额外的空文件轮换(在所有情况下轮换都是在启动或点击collector limits
). - 打开文件进行追加 (
bl::keywords::open_mode = std::ios_base::app
) - 记录类似“按需旋转记录器”的内容
- 调用
rotate_file()
- 这将在打开日志文件后进行轮换。
外观如下:
// File log
auto file_sink
= bl::add_file_log(bl::keywords::target = "history",
bl::keywords::file_name = "app.log",
bl::keywords::target_file_name = "app_%Y%m%d_%H%M%S_%5N.log",
bl::keywords::rotation_size = 10 * 1024 * 1024,
bl::keywords::open_mode = std::ios_base::app, // Open for append and immediately rotate
bl::keywords::enable_final_rotation = false // Rotate only on startup to cover also the crash / kill cases
);
// Log something so the logger opens the file
BOOST_LOG_TRIVIAL(info) << "Rotating logs on startup";
// Do the rotation on demand
file_sink->locked_backend()->rotate_file();