Reputation: 799
I'm trying to find a simplest way to change the output of TimeStamp. This is how I initialize the log library
boost::log::add_common_attributes();
boost::log::register_simple_formatter_factory<SeverityLevel, char>("Severity");
boost::log::register_simple_formatter_factory<boost::posix_time::ptime, char>("TimeStamp");
boost::log::add_file_log(
boost::log::keywords::file_name = strFileName,
boost::log::keywords::open_mode = std::ios_base::out | std::ios_base::app,
boost::log::keywords::format = "[%TimeStamp%] {%Severity% @ %Channel%} %Message%",
boost::log::keywords::auto_flush = true
);
I, also, add following declarations
enum class SeverityLevel {
Debug = 0,
Info,
Warning,
Error,
Critical
};
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", SeverityLevel)
BOOST_LOG_ATTRIBUTE_KEYWORD(timestamp, "TimeStamp", boost::posix_time::ptime)
std::ostream& operator <<(std::ostream& objStream, SeverityLevel eLevel);
boost::log::formatting_ostream& operator <<(boost::log::formatting_ostream& objStream, boost::log::to_log_manip<SeverityLevel, tag::severity> const& objManipulator);
std::ostream& operator <<(std::ostream& objStream, boost::posix_time::ptime objTime);
boost::log::formatting_ostream& operator <<(boost::log::formatting_ostream& objStream, boost::log::to_log_manip<boost::posix_time::ptime, tag::timestamp> const& objManipulator);
Of course, I implement those operators, but their implementation is not important for the question.
In the result the operator related to Severity "std::ostream& operator <<(std::ostream& objStream, SeverityLevel eLevel)" is called as it's supposed to, when I write a log entry, but the operator related to TimeStamp is not. What am I doing wrong here?
Why I need this is to customize the way how timestamp is written. I know there are other ways to do it completely differently by setting sink formatters, for example. I would like to use the string format template instead as it is shown in this example.
Upvotes: 1
Views: 40
Reputation: 393134
First, you ask for "the simplest way" - I think it's the one from the docs:
void init()
{
logging::add_file_log
(
keywords::file_name = "sample_%N.log",
// This makes the sink to write log records that look like this:
// YYYY-MM-DD HH:MI:SS: <normal> A normal severity message
// YYYY-MM-DD HH:MI:SS: <error> An error severity message
keywords::format =
(
expr::stream
<< expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S")
<< ": <" << logging::trivial::severity
<< "> " << expr::smessage
)
);
}
Other than that you say:
I implement those operators, but their implementation is not important for the question.
The implementation isn't, but the place where they are defined is. Operators are found using Argument Dependent Lookup. It's important for them to be in the namespace that declares your argument type.
This might explain that your own enum SeverityLevel
is working for you, but not boost::posix_time::ptime
. I donot suggest you override operator<<(ostream&
for ptime
. Instead consider using the output facets from the DateTime library
Here's a proof of concept that demonstrates that the ADL trick will work:
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/log/common.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/utility/setup.hpp>
namespace MyLib {
enum class SeverityLevel { Debug, Info, Warning, Error, Critical };
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", SeverityLevel)
BOOST_LOG_ATTRIBUTE_KEYWORD(timestamp, "TimeStamp", boost::posix_time::ptime)
std::ostream& operator<<(std::ostream& os, SeverityLevel l) { //
return os << "[Severity:" << static_cast<int>(l) << "]";
}
} // namespace MyLib
namespace boost::posix_time { // DO NOT DO THIS IN PRODUCTION CODE
std::ostream& operator<<(std::ostream& os, boost::posix_time::ptime) {
return os << "[TODO:" << __LINE__ << "]";
}
} // namespace boost::posix_time
using MyLib::SeverityLevel;
void init_logging(std::string const& strFileName) {
namespace l = boost::log;
namespace kw = l::keywords;
l::add_common_attributes();
l::register_simple_formatter_factory<SeverityLevel, char>("Severity");
l::register_simple_formatter_factory<boost::posix_time::ptime, char>("TimeStamp");
l::add_file_log( //
kw::file_name = strFileName, //
kw::open_mode = std::ios_base::out | std::ios_base::app, //
kw::format = "[%TimeStamp%] {%Severity% @ %Channel%} %Message%", //
kw::auto_flush = true //
);
}
int main() {
init_logging("test.log");
boost::log::sources::severity_logger<SeverityLevel> lg;
BOOST_LOG(lg) << "A trace severity message";
}
Logging e.g.
[[TODO:21]] {[Severity:0] @ } A message
[[TODO:21]] {[Severity:0] @ } A message
[[TODO:21]] {[Severity:0] @ } A message
[[TODO:21]] {[Severity:0] @ } A message
[[TODO:21]] {[Severity:0] @ } A message
Upvotes: 0