Skip to content

Rotation counter reaches only 0 when rotating in the same directory #245

@livingsilver94

Description

@livingsilver94

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions