I've got a pretty minimal sample project for boost.log running on Xcode 5, which goes like this:
#include <iostream>
#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/formatters/date_time.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/log/utility/setup/console.hpp>
namespace logging = boost::log;
namespace keywords = boost::log::keywords;
namespace src = boost::log::sources;
namespace expr = boost::log::expressions;
int main(int argc, const char *argv[])
{
logging::add_file_log
(
keywords::file_name = "Out_%N.log",
keywords::format =
(
expr::stream
<< expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S")
<< ": [" << logging::trivial::severity
<< "] " << expr::smessage
)
);
logging::core::get()->set_filter(logging::trivial::severity >= logging::trivial::debug);
logging::add_common_attributes();
src::severity_logger< logging::trivial::severity_level > logger;
BOOST_LOG_SEV(logger, logging::trivial::warning) << "a warning message";
return 0;
}
Now everything runs fine with a command line project.
However as soon as I use the snipped in a real-world project with the default Xcode precompiled header file I'm getting compiler errors in boost/type_traits/detail/has_binary_operator.hpp and boost/lexical_cast.hpp.
Precompiled header test_prefix.pch:
//
// Prefix header for all source files in project
//
#include <Carbon/Carbon.h>
Already wasted hours fiddling with compiler settings and project configuration in Xcode so any feedback is appreciated!
You likely need to #define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0 prior to including Carbon/Carbon.h in your prefix header. See https://svn.boost.org/trac/boost/ticket/6219 for more information.
Related
My code is a basic HelloWorld but fails to compile when I use cout<<endl.
I'm using Microsoft visual studio fresh download and created a console application for my first test project.
// Test1ConsoleApplication.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <string>
#include <iostream>
//#include <ostream>
using namespace std;
int main()
{
string s = "hello world!!";
cout << "lets see: " << s << endl;
return 0;
}
It generates a
"C1001" at line 1.
Replacing "endl" with ""\n"" works though.
You don't need the precompiled header #include <stdafx.h> so you can safely get rid of it. Also get rid of using namespace std; because it pollutes the global namespace. Try something like this. There's no reason it shouldn't work.
#include <string>
#include <iostream>
using std::string;
using std::cout;
using std::endl;
int main()
{
string s = "hello world!!";
cout << "lets see: " << s << endl;
return 0;
}
In Visual Studio you can disable use of the precompiled header in the project settings.
I do not see what the problem is. Both options compile and execute for me.
RexTester cppOnline
// Test1ConsoleApplication.cpp : Defines the entry point for the console application.
//
//#include "stdafx.h"
#include <string>
#include <iostream>
//#include <ostream>
using namespace std;
int main()
{
string s = "hello world!!";
cout << "lets see: " << s << endl;
cout << "lets see: " << s << "\n";
return 0;
}
So idk what was causing the error but it was fixed after pasting imports to the "stdafx.h" header file and then delete them...
#include<sstream>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <cassert>
#include <cmath>
#include <fstream>
#include <time.h>
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/types_c.h"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/video/tracking.hpp"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "opencv2/calib3d/calib3d.hpp"
using namespace std;
using namespace cv;
int main(int argc, char **argv)
{
VideoCapture cap("test2.mp4");
assert(cap.isOpened());
cap>>prev;
VideoWriter outputVideo;
if (!outputVideo.isOpened())outputVideo.open("compare.mp4" , CV_FOURCC('X','V','I','D'), 24,cvSize(cur.rows, cur.cols*2+10), true);
outputVideo<< prev;
while(true) {
stringstream ss;
string name = "cropped_";
string type = ".jpg";
ss<<name<<(chk)<<type;
string filename = ss.str();
ss.str("");
imwrite(filename, canvas);
outputVideo<< canvas;
prev = cur.clone();//cur.copyTo(prev);
prev_ref = cur_ref.clone();//cur.copyTo(prev);
cur_grey.copyTo(prev_grey);
cout << "Frame: " << k << "/" << max_frames << " - good optical flow: " << prev_corner2.size() << endl;
k++;
}
Question:It is a small description of my code.Now when I try to write my canvas(variable of type Mat in OpenCV) for creating a video.It's giving an error.Even if I try for .avi file or .mp4 file it doesn't write/create a video.Please help me out.It shows an error "[mp4 # 0xa0aac0] Tag XVID/0x44495658 incompatible with output codec id '13' error ".I am using ubuntu 14.04 with intel core processor-i5
I have a program that is running as a service for a long time. I use BOOST_LOG_TRIVIAL(info) << "Message" for logging various events. I would like to cooperate with logrotate and reopen my log file after rotation. In theory the screenplay works as follows:
My program starts, some logging happens
Log is renamed from something.log to something.log.1 by an other program like logrotate or by me manually.
My program continues to log to the something.log.1 file.
I send SIGHUP (or something) to my program so I can reopen the log file. But I don't know how to.
My prepared example so far (may not be necessary):
#include <iostream>
#include <stdexcept>
#include <csignal>
#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/setup/console.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/support/date_time.hpp>
inline
void setupLogging(std::string const &logFileName)
{
namespace logging = boost::log;
namespace src = boost::log::sources;
namespace expr = boost::log::expressions;
namespace keywords = boost::log::keywords;
logging::add_common_attributes();
auto format = expr::stream
<< expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S.%f")
<< " progname " << logging::trivial::severity
<< ": " << expr::smessage;
auto fileOutput = logging::add_file_log(
keywords::file_name = logFileName, keywords::format = format
, keywords::auto_flush = true, keywords::open_mode = std::ios::app
);
auto consoleOutput = logging::add_console_log(
std::cerr, keywords::format = format, keywords::auto_flush = true
);
BOOST_LOG_TRIVIAL(debug) << "CHECKPOINT # setupLogging() after log initialization.";
}
void my_signal_handler(int signal)
{
BOOST_LOG_TRIVIAL(info) << "my_signal_handler BEGIN";
/* REOPEN LOG HERE */
BOOST_LOG_TRIVIAL(info) << "my_signal_handler END";
}
int main()
{
setupLogging("logrotate.test.log");
if(signal(SIGHUP, my_signal_handler) == SIG_ERR)
{
BOOST_LOG_TRIVIAL(error) << "Failed to register signal handler";
return 1;
} else
BOOST_LOG_TRIVIAL(info) << "Signal handler registered.";
BOOST_LOG_TRIVIAL(info) << "CHECKPOINT 0";
for(size_t i=1; i<100; ++i)
{
boost::this_thread::sleep_for( boost::chrono::seconds(1) );
BOOST_LOG_TRIVIAL(info) << "CHECKPOINT " << i;
}
return 0;
}
Compiling:
LINK="-lboost_system -lboost_date_time -lboost_log -lboost_log_setup -lboost_thread -lboost_chrono -lpthread"
g++ -std=c++11 -Wextra -DBOOST_LOG_DYN_LINK -pedantic -O3 logrotate_test.cpp -o logrotate_test $LINK
Source code representation of Adam's answer
namespace detail666777888
{
using namespace boost;
using namespace boost::log;
typedef shared_ptr< sinks::synchronous_sink< sinks::text_file_backend > > T;
}
typedef detail666777888::T SPFileSink;
SPFileSink logFileSink;
void setupLogging(...){
... logFileSink = logging::add_file_log ...
}
void my_sighup_handler(int /*signal*/)
{
BOOST_LOG_TRIVIAL(info) << "my_sighup_handler START";
auto oldLFS = logFileSink;
setupLogging("logrotate.test.log");
boost::log::core::get()->remove_sink(oldLFS);
BOOST_LOG_TRIVIAL(info) << "my_sighup_handler FINISH";
}
I was facing the same problem and found a quite straightforward solution: Just initialize the text_file_backend with a single filename (no pattern whatsoever) and call text_file_backend::rotate_file(). This will close the current file and open a new one with the same name.
// create sink
auto backend = boost::make_shared< boost::log::sinks::text_file_backend >(
boost::log::keywords::file_name = "my.log",
boost::log::keywords::open_mode = std::ios_base::out | std::ios_base::app
);
auto sink = boost::make_shared<sinks::synchronous_sink<boost::log::sinks::text_file_backend>>(backend);
boost::log::core::get()->add_sink(sink);
// ... do some logging
// move log file and...
// reopen log file
sink->locked_backend()->rotate_file();
// ... do more logging
I open the log file with std::ios_base::app to prevent the logfile from being truncated if the file exists.
This solution has the advantage that no files need to be copied and log records will neither be lost nor duplicated.
Just use copytruncate logrotate option.
From manual:
Truncate the original log file in place after creating a copy, instead
of moving the old log file and optionally creating a new one. It can
be used when some program cannot be told to close its logfile and thus
might continue writing (appending) to the previous log file forever.
Note that there is a very small time slice between copying the file
and truncating it, so some logging data might be lost. When this
option is used, the create option will have no effect, as the old log
file stays in place.
http://linux.die.net/man/8/logrotate
EDIT:
Try this. Take a look at add_file_log[1] function source code. Then:
remember the object you have added with add_file_log (it returns sink)
when you receive the signal remove_sink[2] and add new one sink with add_file_log[1] -- (logs entries may leak when they are generated by other thread)
[1] http://www.boost.org/doc/libs/1_55_0/boost/log/utility/setup/file.hpp
[2] http://www.boost.org/doc/libs/1_55_0/boost/log/core/core.hpp
I use boost log to output my logs in two separate files, the problem is that i need these outputs to be written instantly, but boost waits 200+ lines to output it in the files. I don't want to have an ultra fast output but two times in a second or each second can be great.
Is there a way to manage this time or the number of lines between each write ?
My h (BoostLogging.h) :
#ifndef AUDIO_RECO_MODULES_COMMON_BOOSTLOGGING_H_
#define AUDIO_RECO_MODULES_COMMON_BOOSTLOGGING_H_
#include <cstddef>
#include <string>
#include <ostream>
#include <fstream>
#include <iomanip>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/phoenix/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/sources/basic_logger.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/sources/severity_channel_logger.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/attributes/scoped_attribute.hpp>
#include <boost/log/utility/value_ref.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
namespace logging = boost::log;
namespace src = boost::log::sources;
namespace expr = boost::log::expressions;
namespace sinks = boost::log::sinks;
namespace attrs = boost::log::attributes;
namespace keywords = boost::log::keywords;
enum severity_level {
TRACE,
DEBUG,
INFO,
WARNING,
ERROR,
FATAL,
NODE
};
BOOST_LOG_ATTRIBUTE_KEYWORD(line_id, "LineID", unsigned int)
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", severity_level)
BOOST_LOG_ATTRIBUTE_KEYWORD(tag_attr, "Tag", std::string)
std::ostream& operator<<(std::ostream& strm, severity_level level);
void InitBoostLog(severity_level logging_level, std::string module_name);
#endif //AUDIO_RECO_MODULES_COMMON_BOOSTLOGGING_H_
The source (BoostLogging.cc) :
#include <BoostLogging.h>
std::ostream& operator<<(std::ostream& strm, severity_level level) {
static const char* strings[] = {
"trace",
"debug",
"info",
"warning",
"error",
"fatal",
"node"
};
if (static_cast< std::size_t >(level) < sizeof(strings) / sizeof(*strings))
strm << strings[level];
else
strm << static_cast< int >(level);
return strm;
}
void InitBoostLog(severity_level logging_level, std::string module_name) {
// Setup the common formatter for all sinks
logging::formatter fmt = expr::stream
<< std::setw(6) << std::setfill('0') << line_id << std::setfill(' ')
<< ": <" << severity << ">\t"
<< expr::if_(expr::has_attr(tag_attr))
[
expr::stream << "[" << tag_attr << "] "
]
<< expr::smessage;
// Initialize sinks
boost::shared_ptr<logging::core> core = logging::core::get();
typedef sinks::synchronous_sink <sinks::text_ostream_backend> text_sink;
boost::shared_ptr<text_sink> sink = boost::make_shared<text_sink>();
sink->locked_backend()->add_stream(
boost::make_shared<std::ofstream>("arm-" + module_name + ".log"));
sink->set_formatter(fmt);
sink->set_filter(severity != NODE && severity >= logging_level);
core->add_sink(sink);
sink = boost::make_shared<text_sink>();
sink->locked_backend()->add_stream(
boost::make_shared<std::ofstream>("arm-" + module_name + "-node.log"));
sink->set_filter(severity == NODE);
core->add_sink(sink);
// Add attributes
logging::add_common_attributes();
}
you can enable auto-flushing for your backend as described here: http://boost-log.sourceforge.net/libs/log/doc/html/log/detailed/sink_backends.html
Enabling auto flushing as #Andy T suggested is the good way to do it, before adding the sink to the core we need to enable the auto-flushing.
sink->locked_backend()->add_stream(
boost::make_shared<std::ofstream>("arm-" + module_name + ".log"));
sink->set_formatter(fmt);
sink->set_filter(severity != NODE && severity >= logging_level);
sink->locked_backend()->auto_flush(true); // HERE
core->add_sink(sink);
sink = boost::make_shared<text_sink>();
sink->locked_backend()->add_stream(
boost::make_shared<std::ofstream>("arm-" + module_name + "-node.log"));
sink->set_filter(severity == NODE);
sink->locked_backend()->auto_flush(true); // AND HERE
core->add_sink(sink);
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 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:
if (something)
LOG_FILE_LINE(debug) << "It's true"; // Only the first statement is conditional!
You can do better creating a macro that leverages the underlying behavior of the Boost Log library. For example, BOOST_LOG_SEV is:
#define BOOST_LOG_SEV(logger, lvl) BOOST_LOG_STREAM_SEV(logger, lvl)
#define BOOST_LOG_STREAM_SEV(logger, lvl)\
BOOST_LOG_STREAM_WITH_PARAMS((logger), (::boost::log::keywords::severity = (lvl)))
Using BOOST_LOG_STREAM_WITH_PARAMS you can set and get more attributes, like this:
// New macro that includes severity, filename and line number
#define CUSTOM_LOG(logger, sev) \
BOOST_LOG_STREAM_WITH_PARAMS( \
(logger), \
(set_get_attrib("File", path_to_filename(__FILE__))) \
(set_get_attrib("Line", __LINE__)) \
(::boost::log::keywords::severity = (boost::log::trivial::sev)) \
)
// Set attribute and return the new value
template<typename ValueType>
ValueType set_get_attrib(const char* name, ValueType value) {
auto attr = logging::attribute_cast<attrs::mutable_constant<ValueType>>(logging::core::get()->get_thread_attributes()[name]);
attr.set(value);
return attr.get();
}
// Convert file path to only the filename
std::string path_to_filename(std::string path) {
return path.substr(path.find_last_of("/\\")+1);
}
The complete source code is:
#include <boost/log/trivial.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/setup/console.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/attributes/mutable_constant.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/attributes/mutable_constant.hpp>
namespace logging = boost::log;
namespace attrs = boost::log::attributes;
namespace expr = boost::log::expressions;
namespace src = boost::log::sources;
namespace keywords = boost::log::keywords;
// New macro that includes severity, filename and line number
#define CUSTOM_LOG(logger, sev) \
BOOST_LOG_STREAM_WITH_PARAMS( \
(logger), \
(set_get_attrib("File", path_to_filename(__FILE__))) \
(set_get_attrib("Line", __LINE__)) \
(::boost::log::keywords::severity = (boost::log::trivial::sev)) \
)
// Set attribute and return the new value
template<typename ValueType>
ValueType set_get_attrib(const char* name, ValueType value) {
auto attr = logging::attribute_cast<attrs::mutable_constant<ValueType>>(logging::core::get()->get_thread_attributes()[name]);
attr.set(value);
return attr.get();
}
// Convert file path to only the filename
std::string path_to_filename(std::string path) {
return path.substr(path.find_last_of("/\\")+1);
}
void init() {
// New attributes that hold filename and line number
logging::core::get()->add_thread_attribute("File", attrs::mutable_constant<std::string>(""));
logging::core::get()->add_thread_attribute("Line", attrs::mutable_constant<int>(0));
logging::add_file_log (
keywords::file_name = "sample.log",
keywords::format = (
expr::stream
<< expr::format_date_time<boost::posix_time::ptime>("TimeStamp", "%Y-%m-%d_%H:%M:%S.%f")
<< ": <" << boost::log::trivial::severity << "> "
<< '[' << expr::attr<std::string>("File")
<< ':' << expr::attr<int>("Line") << "] "
<< expr::smessage
)
);
logging::add_common_attributes();
}
int main(int argc, char* argv[]) {
init();
src::severity_logger<logging::trivial::severity_level> lg;
CUSTOM_LOG(lg, debug) << "A regular message";
return 0;
}
This generate a log like this:
2015-10-15_15:25:12.743153: <debug> [main.cpp:61] A regular message
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:
using namespace boost::log;
core::get()->add_global_attribute("Line", attributes::mutable_constant<int>(5));
core::get()->add_global_attribute("File", attributes::mutable_constant<std::string>(""));
core::get()->add_global_attribute("Function", attributes::mutable_constant<std::string>(""));
Setting these attributes in your logging macro:
#define logInfo(methodname, message) \
LOG_LOCATION; \
BOOST_LOG_SEV(_log, boost::log::trivial::severity_level::trace) << message
#define LOG_LOCATION \
boost::log::attribute_cast<boost::log::attributes::mutable_constant<int>>(boost::log::core::get()->get_global_attributes()["Line"]).set(__LINE__); \
boost::log::attribute_cast<boost::log::attributes::mutable_constant<std::string>>(boost::log::core::get()->get_global_attributes()["File"]).set(__FILE__); \
boost::log::attribute_cast<boost::log::attributes::mutable_constant<std::string>>(boost::log::core::get()->get_global_attributes()["Function"]).set(__func__);
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.
I would suggest to use the boost::log::add_value() function.
Define:
#define LOG_LOCATION(LEVEL, MSG) \
BOOST_LOG_SEV(logger::get(), LEVEL) \
<< boost::log::add_value("Line", __LINE__) \
<< boost::log::add_value("File", __FILE__) \
<< boost::log::add_value("Function", __FUNCTION__) << MSG
And then you can format it as follows:
boost::log::add_common_attributes();
boost::log::register_simple_filter_factory<boost::log::trivial::severity_level, char>("Severity");
boost::log::register_simple_formatter_factory<boost::log::trivial::severity_level, char>("Severity");
auto syslog_format(
boost::log::expressions::stream <<
"[" << boost::log::expressions::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S") <<
"] [" << boost::log::expressions::attr<boost::log::attributes::current_thread_id::value_type>("ThreadID") <<
"] [" << std::left << std::setw(7) << std::setfill(' ') << boost::log::trivial::severity <<
"] " << boost::log::expressions::smessage <<
" (" << boost::log::expressions::attr<std::string>("Filename") <<
":" << boost::log::expressions::attr<int>("Line") <<
":" << boost::log::expressions::attr<std::string>("Function") <<
")"
);
boost::log::add_file_log(
boost::log::keywords::file_name = "sys_%d_%m_%Y.%N.log",
boost::log::keywords::format = syslog_format
);
No need to add global attributes, and you can format it easily as seen above. I find this is a good compromise between other's solutions and the raw __FILE__ __LINE__ approach.
Full example here.
Define
namespace attrs = boost::logging::attributes;
namespace expr = boost::logging::expressions;
Add
<< expr::format_named_scope("Scope", keywords::format = "[%f:%l]")
to your keywords::format = (...) in init.
Then add
logging::core::get()->add_global_attribute("Scope", attrs::named_scope());
after add_common_attributes() in main.
Then just before the BOOST_LOG_SEV line add BOOST_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 the BOOST_LOG_SEV macro.
I am not aware of simple method to record the file and line without using the BOOST_LOG_NAMED_SCOPE.