c++ - Boost Logging File - Stack Overflow

There is a small problem related to boost logging. I have written my own classes for various loggers. I

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();
}

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();
}

Share edited Mar 3 at 12:04 Ahmed AEK 20k3 gold badges17 silver badges43 bronze badges asked Mar 3 at 11:09 user29207775user29207775 613 bronze badges 2
  • It would help if you posted a small reproducer that actually shows the problem. – Andrey Semashev Commented Mar 3 at 14:47
  • 1 Regarding the code you've already posted, you should be aware that add_file_log always adds a new sink, so if you create multiple instances of FileLocalLoggerWithAttribute they will all create their own sinks. This could be a problem is they all write to the same log file. Also, add_attribute tries to add a new attribute, if it doesn't exist in the logger's attribute set, and fails if it already exists. So, multiple calls to setLoggingEnabled will not update the LoggingEnabled value. But since set_filter overwrites the filter, that value is not used anyway. – Andrey Semashev Commented Mar 3 at 14:53
Add a comment  | 

1 Answer 1

Reset to default 1

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

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745097616a4611076.html

相关推荐

  • c++ - Boost Logging File - Stack Overflow

    There is a small problem related to boost logging. I have written my own classes for various loggers. I

    15小时前
    20

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信