I'm using Boost(1.55.0) Logging in my C++ application. I have been able to generate log of this format
[2014-Jul-15 10:47:26.137959]: <debug> A regular message
I want to be able to add source file name and line number where the log is generated.
[2014-Jul-15 10:47:26.137959]: <debug> [filename:line_no] A regular message
example:
[2014-Jul-15 10:47:26.137959]: <debug> [helloworld.cpp : 12] A regular message
Source Code:
#include <boost/log/core.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sinks/text_file_backend.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/attributes/attribute.hpp>
#include <boost/log/attributes/attribute_cast.hpp>
#include <boost/log/attributes/attribute_value.hpp>
#include <boost/make_shared.hpp>
#include <boost/property_tree/ptree.hpp>
namespace logging = boost::log;
namespace src = boost::log::sources;
namespace sinks = boost::log::sinks;
namespace keywords = boost::log::keywords;
void init()
{
logging::add_file_log
(
keywords::file_name = "sample_%N.log", /*< file name pattern >*/
keywords::rotation_size = 10*1024*1204, /*< rotate files every 10 MiB... >*/
keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0), /*< ...or at midnight >*/
keywords::format =
(
boost::log::expressions::stream
<< boost::log::expressions::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d_%H:%M:%S.%f")
<< ": <" << boost::log::trivial::severity << "> "
<< boost::log::expressions::smessage
)
);
}
int main(int, char*[])
{
init();
logging::add_common_attributes();
using namespace logging::trivial;
src::severity_logger< severity_level > lg;
BOOST_LOG_SEV(lg, debug) << "A regular message";
return 0;
}
As user2943014 pointed out, using scopes prints the line number where you opened that scope, not the line number where you emitted a log message using BOOST_LOG_SEV.
You can use attributes to log the line numbers etc at the place you actually logged.
Register global attributes in your logging initialization function:
Setting these attributes in your logging macro:
Not exactly beautiful, but it works and it was a long way for me. It's a pity boost doesn't offer this feature out of the box.
As Horus pointed out, you can use attributes to log file and line numbers. However it is best to avoid using multi-statements macros to avoid problems with expressions like this:
You can do better creating a macro that leverages the underlying behavior of the Boost Log library. For example, BOOST_LOG_SEV is:
Using BOOST_LOG_STREAM_WITH_PARAMS you can set and get more attributes, like this:
The complete source code is:
This generate a log like this:
Define
Add
to your
keywords::format = (...)
ininit
.Then add
after
add_common_attributes()
inmain
.Then just before the
BOOST_LOG_SEV
line addBOOST_LOG_NAMED_SCOPE("whatever")
.BOOST_LOG_NAMED_SCOPE("whatever")
creates a "scope" named "whatever". The scope is implemented by a unused variable that contains the scope name and the file and the line where the scope was defined.The
format_named_scope
line specifies how a scope should be formatted in the log line. %f is the file, %l is the line and %n is the scope name.Note that the file line that appears in the log record is the line where the macro
BOOST_LOG_NAMED_SCOPE
appears and not the line of theBOOST_LOG_SEV
macro.I am not aware of simple method to record the file and line without using the
BOOST_LOG_NAMED_SCOPE
.