I want to rotate log files at startup, not when the application closes.
The idea is to have runtime.log as the current file, and runtime%N.log as previous log files, in the same directory, e.g. ./log. When the application starts, runtime.log is renamed into runtime%N.log and a new runtime.log is created. Obviously, %N is replaced with whatever value the counter holds.
I couldn't figure out a way to do that with pure Boost.Log API, so I added a manual rotate_file() call if the previous log file (created in a previous execution) exists.
Now, I said the current and old log files must reside in the same directory. Using the code below as a reproducible example, you can see that the maximum value the counter reaches is... zero. If you instead replace keywords::target = directory with, say, keywords::target = ".", the counter is able to go beyond zero, but of course the old log files are placed in a different directory which is not what I want to do. I'm not sure whether this is a bug or a misuse of Boost.Log.
You can compile the code below by running g++ -lboost_filesystem -lboost_log -lboost_date_time -lboost_thread -DBOOST_LOG_DYN_LINK=1 test.cpp
#include <boost/log/attributes.hpp>
#include <boost/log/common.hpp>
#include <boost/log/core.hpp>
#include <boost/log/exceptions.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sinks.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/sources/severity_feature.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <filesystem>
using namespace boost::log;
enum class Severity {
Verbose = 1,
Info = 2,
Error = 255,
};
std::ostream& operator<<(std::ostream& s, Severity sev) {
s << (int)sev;
return s;
}
BOOST_LOG_ATTRIBUTE_KEYWORD(timestamp, "Timestamp", attributes::local_clock)
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", Severity)
BOOST_LOG_ATTRIBUTE_KEYWORD(context, "Context", std::string_view)
BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(logger, sources::severity_logger_mt<Severity>)
auto initFile(Severity minSev, const std::filesystem::path& directory) -> void
{
namespace exp = expressions;
// Register the sink backend that writes on files.
auto sink = add_file_log(
keywords::auto_flush = true,
keywords::file_name = directory / "runtime.log",
keywords::target_file_name = directory / "runtime%N.log",
keywords::enable_final_rotation = false,
keywords::open_mode = std::ios_base::app,
keywords::target = directory,
keywords::format =
(exp::stream << "[" << exp::format_date_time<boost::posix_time::ptime>("Timestamp", "%Y-%m-%dT%H:%M:%S")
<< "] " << severity << ": "
<< exp::if_(exp::has_attr(context))[exp::stream << "<" << context << ">: "] << exp::smessage));
auto core = core::get();
core->add_global_attribute("Timestamp", attributes::local_clock());
core->set_filter(severity <= minSev);
sink->locked_backend()->scan_for_files();
if (std::filesystem::exists(directory / "runtime.log")) {
BOOST_LOG_SEV(logger::get(), Severity::Error) << L"ROTATING AT STARTUP";
sink->locked_backend()->rotate_file();
}
}
int main(int argc, char** argv) {
static const std::filesystem::path directory = "log";
initFile(Severity::Error, directory);
BOOST_LOG_SEV(logger::get(), Severity::Error) << "TERMINATING";
}
This was performed on Fedora using GCC with Boost 1.83.0.
I want to rotate log files at startup, not when the application closes.
The idea is to have
runtime.logas the current file, andruntime%N.logas previous log files, in the same directory, e.g../log. When the application starts,runtime.logis renamed intoruntime%N.logand a newruntime.logis created. Obviously,%Nis replaced with whatever value the counter holds.I couldn't figure out a way to do that with pure Boost.Log API, so I added a manual
rotate_file()call if the previous log file (created in a previous execution) exists.Now, I said the current and old log files must reside in the same directory. Using the code below as a reproducible example, you can see that the maximum value the counter reaches is... zero. If you instead replace
keywords::target = directorywith, say,keywords::target = ".", the counter is able to go beyond zero, but of course the old log files are placed in a different directory which is not what I want to do. I'm not sure whether this is a bug or a misuse of Boost.Log.You can compile the code below by running
g++ -lboost_filesystem -lboost_log -lboost_date_time -lboost_thread -DBOOST_LOG_DYN_LINK=1 test.cppThis was performed on Fedora using GCC with Boost 1.83.0.