user29207775
user29207775

Reputation: 41

Boost Logging File

There is a small problem related to boost logging. I have written my own classes for various loggers. I will present one of them below.

class FileLocalLoggerWithAttribute
{
public:
    FileLocalLoggerWithAttribute(std::string filename = "app.log", bool isEnabled = true);

    void log(logging::trivial::severity_level level, std::string message,  std::string who_is_sender, const std::string& functionName); 
    void setLoggingEnabled(bool enabled);

private:
    src::severity_logger<logging::trivial::severity_level> logger_;
    std::string filename_;
};

and its implementation is below

FileLocalLoggerWithAttribute::FileLocalLoggerWithAttribute(std::string filename, bool isEnabled)
    : filename_(filename),
    logger_()
{

    logging::add_file_log(
        keywords::file_name = filename_,
        keywords::rotation_size = 10 * 1024 * 1024,
        keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0),
        keywords::format =
        (
           
           expr::stream 
            << expr::format_date_time< boost::posix_time::ptime>("TimeStamp", "%Y-%m-%d %H:%M:%S") 
            << ": <" << logging::trivial::severity 
            <<  "> [src: " << expr::attr<std::string>("Who") << "] " 
            <<  "[Function: " << expr::attr<std::string>("FunctionName") << "] "
            << expr::message
        )
    );
    setLoggingEnabled(isEnabled);
}

void FileLocalLoggerWithAttribute::log(logging::trivial::severity_level level, std::string message, 
            std::string who_is_sender, const std::string& functionName)
{
    BOOST_LOG_SEV(logger_, level) << logging::add_value("Who", who_is_sender) << logging::add_value("FunctionName", functionName) << message;
}

void FileLocalLoggerWithAttribute::setLoggingEnabled(bool enabled)
{
    logger_.add_attribute("LoggingEnabled", attrs::constant<bool>(enabled));

    logging::core::get()->set_filter(expr::attr<bool>("LoggingEnabled") == true);
     logging::core::get()->set_filter(logging::trivial::severity >= logging::trivial::info);

}

If we run some small test code for logging, then there are no problems.

#include "../Logger.hpp"
int main() {
    FileLocalLoggerWithAttribute l("www.log", true);

    l.log(logging::trivial::info, "Hello world", "Host",  __func__);
    l.log(logging::trivial::info, "Hello world", "Client",  __func__);
    l.log(logging::trivial::info, "Hello world", "WEB",  __func__);
    l.log(logging::trivial::info, "Hello world", "SERVER",  __func__);
    l.log(logging::trivial::info, "Hello world", "DEMODULATOR",  __func__);
  return 0;
}

But if I want to add a logger to my rather large (multithreaded project), then a problem arises. At the moment, I have no way to finish the program execution (There is no exit condition, the application is console-based, multithreaded, asynchronous) without making an emergency stop. I usually stop ctrl-C. But in this case, the logger file turns out to be empty. The code is exactly the same.

#include "Logger.hpp"
int main(int argc, char* argv[])
{   
    // Logger Init
    // Init Read/WRITE OPERATION
    ...
    io_context.run();
}

Upvotes: 1

Views: 41

Answers (1)

sehe
sehe

Reputation: 393664

I don't know how you get the problem you describe. You claim "the code is exactly the same", yet it cannot be unless you share the l instance by reference among your IO code.

I imagine the sink doesn't get flushed in the end.

Here's some fixes:

  • the setLoggingEnabled didn't work for several reasons
  • the filename_ field was initialized after logger_. I reordered the declarations to match
  • TimeStamp attribute was never added
  • adding explicit flush (also from destructor)

Hopefully this gets you a little further:

Live On Coliru

#include <boost/log/attributes.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sinks/text_file_backend.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/manipulators.hpp>
#include <boost/log/utility/setup.hpp>
namespace logging = boost::log;
namespace src     = boost::log::sources;

class FileLocalLoggerWithAttribute {
  public:
    using severity_level = logging::trivial::severity_level;

    FileLocalLoggerWithAttribute(std::string filename = "app.log", bool isEnabled = true);

    void log(severity_level level, std::string message, std::string who_is_sender,
             std::string const& functionName);
    void setLoggingEnabled(bool enabled);

    void flush() { sink_->flush(); }

    ~FileLocalLoggerWithAttribute() { 
        sink_->flush();
        logging::core::get()->remove_sink(sink_);
    }

  private:
    std::string                          filename_;
    src::severity_logger<severity_level> logger_;

    boost::shared_ptr<                          //
        logging::sinks::synchronous_sink<       //
            logging::sinks::text_file_backend>> //
        sink_;
};

FileLocalLoggerWithAttribute::FileLocalLoggerWithAttribute(std::string filename, bool isEnabled)
    : filename_(filename), logger_() {

    namespace keywords = boost::log::keywords;
    namespace sinks    = boost::log::sinks;
    namespace expr     = boost::log::expressions;
    sink_              = logging::add_file_log( //
        keywords::file_name = filename_, keywords::rotation_size = 10 * 1024 * 1024,
        keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0),
        keywords::format              = expr::stream                    //
            << expr::format_date_time<boost::posix_time::ptime>(        //
                               "TimeStamp",                             //
                               "%Y-%m-%d %H:%M:%S")                     //
            << ": <" << logging::trivial::severity                      //
            << "> [src: " << expr::attr<std::string>("Who") << "] "     //
            << "[Function: " << expr::attr<std::string>("FunctionName") //
            << "] "                                                     //
            << expr::message);                                          //

    sink_->set_filter(expr::attr<bool>("LoggingEnabled") == true &&
                      logging::trivial::severity >= logging::trivial::info);
    setLoggingEnabled(isEnabled);
}

void FileLocalLoggerWithAttribute::log(logging::trivial::severity_level level, std::string message,
                                       std::string who_is_sender, std::string const& functionName) {
    BOOST_LOG_SEV(logger_, level)                                                         //
        << logging::add_value("TimeStamp", boost::posix_time::second_clock::local_time()) //
        << logging::add_value("Who", std::move(who_is_sender))                            //
        << logging::add_value("FunctionName", functionName)                               //
        << std::move(message);
}

void FileLocalLoggerWithAttribute::setLoggingEnabled(bool enabled) {
    namespace attrs = boost::log::attributes;
    auto aa = logger_.get_attributes();
    auto it         = aa.find("LoggingEnabled");
    if (it != aa.end())
        logger_.remove_attribute(it);
    logger_.set_attributes(aa);

    logger_.add_attribute("LoggingEnabled", attrs::constant<bool>(enabled));
}

int main() {
    FileLocalLoggerWithAttribute l("www.log", true);

    l.log(logging::trivial::info, "Hello world", "Host", __func__);
    l.log(logging::trivial::info, "Hello world", "Client", __func__);
    l.setLoggingEnabled(false);
    l.log(logging::trivial::info, "Hello world", "WEB", __func__);
    l.setLoggingEnabled(true);
    l.log(logging::trivial::info, "Hello world", "SERVER", __func__);
    l.log(logging::trivial::info, "Hello world", "DEMODULATOR", __func__);
    l.flush();
}

Printing

g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp -lboost_{system,thread,log,filesystem} && ./a.out; tail www.log
2025-03-03 15:46:10: <info> [src: Host] [Function: main] Hello world
2025-03-03 15:46:10: <info> [src: Client] [Function: main] Hello world
2025-03-03 15:46:10: <info> [src: SERVER] [Function: main] Hello world
2025-03-03 15:46:10: <info> [src: DEMODULATOR] [Function: main] Hello world

Upvotes: 0

Related Questions