Reputation: 41
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
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:
setLoggingEnabled
didn't work for several reasonsfilename_
field was initialized after logger_
. I reordered the declarations to matchTimeStamp
attribute was never addedflush
(also from destructor)Hopefully this gets you a little further:
#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