c++boost-log

Boost Log incorrect target directory


I have observed the following behavior: Boost Log always writes log files to the binary folder (folder which contains the executable) first and move them to the configured target directory keywords::target = "<directory>".

Does anyone have the same issue or did I do something wrong?

Many thanks for your help in advance.

Here is what I have done:

#include <boost/shared_ptr.hpp>

#include <boost/lambda/lambda.hpp>

#include <boost/log/core/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sinks.hpp>
#include <boost/log/sources/severity_channel_logger.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/manipulators/add_value.hpp>
#include <boost/log/utility/setup/file.hpp>

#include <string>
#include <thread>

using RollingFileSink = boost::log::sinks::asynchronous_sink<boost::log::sinks::text_file_backend>;

//using eBoostPredefinedLogLevel = boost::log::trivial::severity_level;
using SeverityLoggerMt = boost::log::sources::severity_channel_logger_mt< boost::log::trivial::severity_level>;
using tSinkFrontEndFilter = boost::log::expressions::channel_severity_filter_actor<std::string,  boost::log::trivial::severity_level>;

BOOST_LOG_ATTRIBUTE_KEYWORD(eSeverityLevel, "Severity",  boost::log::trivial::severity_level)
BOOST_LOG_ATTRIBUTE_KEYWORD(LogChannel, "Channel", std::string)

void setLogFormat(boost::log::record_view const& a_rec, boost::log::formatting_ostream& a_strm);
void createRollingFileSink();

int main()
{
    using namespace std;
    using namespace boost::log;

    createRollingFileSink();

    unique_ptr<SeverityLoggerMt> pBoostLogger = make_unique<SeverityLoggerMt>(boost::log::keywords::channel = "ChannelOne");

    for (int i = 0; i < 200; i++)
    {
        BOOST_LOG_SEV(*pBoostLogger, trivial::severity_level::trace) << "Trace log Nr." << to_string(i);
        this_thread::sleep_for(500ms);
        BOOST_LOG_SEV(*pBoostLogger, trivial::severity_level::debug) << "Debug log Nr." << to_string(i);
        this_thread::sleep_for(500ms);
        BOOST_LOG_SEV(*pBoostLogger, trivial::severity_level::info) << "Info log Nr." << to_string(i);
        this_thread::sleep_for(500ms);
        BOOST_LOG_SEV(*pBoostLogger, trivial::severity_level::warning) << "Warn log Nr." << to_string(i);
        this_thread::sleep_for(500ms);
        BOOST_LOG_SEV(*pBoostLogger, trivial::severity_level::error) << "Error log Nr." << to_string(i);
        this_thread::sleep_for(500ms);
        BOOST_LOG_SEV(*pBoostLogger, trivial::severity_level::fatal) << "Fatal log Nr." << to_string(i);
        this_thread::sleep_for(500ms);
    }

    return 0;
}

void createRollingFileSink()
{
    using namespace boost::log;
    using namespace std;

    boost::shared_ptr<RollingFileSink> pSinkFrontEnd;
    boost::shared_ptr<sinks::text_file_backend> pSinkBackend;

    pSinkBackend = boost::make_shared<sinks::text_file_backend>
    (
        keywords::file_name = "LogFile%3N.log",
        keywords::rotation_size = 16*1024,
        keywords::auto_flush = true,
        keywords::enable_final_rotation = true
    );
    pSinkFrontEnd = boost::make_shared<RollingFileSink>(pSinkBackend);

    pSinkFrontEnd->locked_backend()->set_file_collector
    (
        sinks::file::make_collector
        (
            keywords::target = "c:\\TestProjects\\BoostLogMoveLogsfile\\build\\Debug\\logs",
            keywords::max_size = 150*1024*1024, 
            keywords::min_free_space = 512*1024*1024, 
            keywords::max_files = 60
        )
    );
    tSinkFrontEndFilter frontendFilter = expressions::channel_severity_filter(LogChannel, eSeverityLevel);
    frontendFilter["ChannelOne"] =  trivial::severity_level::trace;
    pSinkFrontEnd->set_filter( frontendFilter );
    pSinkFrontEnd->locked_backend()->scan_for_files();

    pSinkFrontEnd->locked_backend()->set_open_handler
    (
        boost::lambda::_1 << "Application: boostlogmovelogsfile" << "\n" << "---------------------------------" << "\n"
    );
    pSinkFrontEnd->set_formatter(&setLogFormat);

    core::get()->add_sink(pSinkFrontEnd);
}

void setLogFormat(boost::log::record_view const& a_rec, boost::log::formatting_ostream& a_strm)
{
    using namespace boost;

    a_strm << "[";
    a_strm << "log level=" << a_rec[log::trivial::severity];
    a_strm << "] ";
    a_strm << a_rec[boost::log::expressions::smessage];
}

What I have observed is that a log file (e.g. 'LogFile000.log') will be written in c:\\TestProjects\\BoostLogMoveLogsfile\\build\\Debug first. When the rotation happens 'LogFile000.log' will be move into c:\\TestProjects\\BoostLogMoveLogsfile\\build\\Debug\\logs and 'LogFile001.log' will be written in c:\\TestProjects\\BoostLogMoveLogsfile\\build\\Debug so on and so forth.


Solution

  • This is expected behavior. The target parameter denotes the target storage where the rotated log files will be placed (see the docs). The file that is being actively written is specified in the file_name parameter. Since you specify a relative path in this parameter (a single file name), that path is resolved relative to the current directory of your process, which is likely where you start the application from.

    If you want to write the active log file in a specific location, you should specify it as an absolute path in the file_name parameter.