Reputation: 135
I want to setup only one Boost Log V2 sink (Boost 1.75.0) to filter out few lines from the log records producing the application. The goal would be to have a log file containing only these lines (e.g.: users who logged in), while another sink logs out every records
I have tried to configure the filter property of the sink in the configuration file to match to a tag presence, like this:
[Sinks.FileSink]
Destination=TextFile
Filter="%USER%"
FileName="log.log"
MaxSize=10000000
Format="[%TimeStamp%] - %Message%"
Asynchronous=false
AutoFlush=true
Where the %USER%
tag would be the filter criteria, if it is present, log the line, otherwise not...
I tried to add as value attribute:
... << boost::log::add_value("USER", true) << "message..."
and also register it before logger from file:
boost::log::core::get()->add_global_attribute("USER", boost::log::attributes::mutable_constant(true));
boost::log::init_from_stream(config);
None of them work
For me, the strange behavioral was that filter pattern works if I filter for severity, like this: Filter="%Severity%"
Can anybody help me how to filter only really few lines from application and forward them into file?
Thank you
Update:
a minimal example that wants to demonstrator what I want to achieve:
#include <boost/log/utility/setup/from_stream.hpp>
#include <boost/log/attributes/mutable_constant.hpp>
int main(int argc, char *argv_char[]) {
std::stringstream config;
config << R"([Core])" << std::endl;
config << R"(DisableLogging=false)" << std::endl;
config << R"(Filter="%Severity% >= trace")" << std::endl;
config << R"([Sinks.Sink])" << std::endl;
config << R"(Destination=Console)" << std::endl;
//config << R"(Filter="%CMD% = \"YES\"")" << std::endl;
config << R"(Filter="%CMD% = \"NO\"")" << std::endl;
config << R"(FileName="commands.log")" << std::endl;
config << R"(Format="%Message%")" << std::endl;
config << R"(Asynchronous=false)" << std::endl;
config << R"(AutoFlush=true)" << std::endl;
boost::log::core::get()->add_global_attribute("CMD", boost::log::attributes::mutable_constant<std::string>("NO"));
boost::log::init_from_stream(config);
BOOST_LOG_TRIVIAL(debug) << "Non-visible message";
BOOST_LOG_TRIVIAL(debug) << boost::log::add_value("CMD", "YES") << "Visible message";
return 0;
}
If I replace the filter condition to %CMD% = "YES", the desired log line is missing on the output
Update 2:
// Codes above didn't changed
boost::log::init_from_stream(config);
boost::log::sources::logger logger;
logger.add_attribute("CMD", boost::log::attributes::constant<std::string>("YES"));
BOOST_LOG(logger) << "A log message from logger";
boost::log::sources::logger loggerScoped;
BOOST_LOG_SCOPED_LOGGER_ATTR(loggerScoped, "CMD", boost::log::attributes::constant<std::string>("YES"));
BOOST_LOG(loggerScoped) << "A log message from loggerScoped";
BOOST_LOG_TRIVIAL(debug) << "Non-visible message";
BOOST_LOG_TRIVIAL(debug) << boost::log::add_value("CMD", "YES") << "Visible message";
return 0;
Upvotes: 0
Views: 575
Reputation: 10614
As stated in the documentation, add_value
manipulator has no effect on filtering as it is being executed after filtering is done. In your code sample, you're setting a global string attribute "CMD" with a value of "NO", and that is what is being tested by the filters for both log records. When you change the filter to require the value of "YES", both log records get suppressed.
If you want to selectively disable some log records, you should use other means for registering the attribute, so that it is in effect at the point of filtering. For example, you could add the attribute to a logger (by calling add_attribute
on the logger) and use that logger to emit log records you want to suppress. Or you could use scoped attributes to mark log records that are being emitted in a given region of code. Below is an updated code example:
#include <string>
#include <sstream>
#include <boost/log/core.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup/from_stream.hpp>
#include <boost/log/utility/manipulators/add_value.hpp>
#include <boost/log/attributes/mutable_constant.hpp>
#include <boost/log/attributes/scoped_attribute.hpp>
#include <boost/log/sources/logger.hpp>
int main(int argc, char *argv_char[]) {
std::stringstream config;
config << R"([Core])" << std::endl;
config << R"(DisableLogging=false)" << std::endl;
//config << R"(Filter="%Severity% >= trace")" << std::endl;
config << R"([Sinks.Sink])" << std::endl;
config << R"(Destination=Console)" << std::endl;
config << R"(Filter="%CMD% = \"YES\"")" << std::endl;
config << R"(Format="%Message%")" << std::endl;
config << R"(Asynchronous=false)" << std::endl;
config << R"(AutoFlush=true)" << std::endl;
boost::log::core::get()->add_global_attribute("CMD", boost::log::attributes::mutable_constant<std::string>("NO"));
boost::log::init_from_stream(config);
boost::log::sources::logger logger;
logger.add_attribute("CMD", boost::log::attributes::constant<std::string>("YES"));
BOOST_LOG(logger) << "A log message from logger";
{
boost::log::sources::logger loggerScoped;
BOOST_LOG_SCOPED_LOGGER_ATTR(loggerScoped, "CMD", boost::log::attributes::constant<std::string>("YES"));
BOOST_LOG(loggerScoped) << "A log message from loggerScoped";
}
BOOST_LOG_TRIVIAL(debug) << "Non-visible message";
BOOST_LOG_TRIVIAL(debug) << boost::log::add_value("CMD", "YES") << "Still non-visible message";
return 0;
}
Upvotes: 0