How to write encoder line number in buffer 2.0?

Can the LineID attribute be used for this? I hope I could use sink :: set_formatter to do this instead of using

__LINE__ 

and

 __FILE__ 

in each log statement.

+6
source share
6 answers

I struggled with this until I found this fragment

 #define LFC1_LOG_TRACE(logger) \ BOOST_LOG_SEV(logger, trivial::trace) << "(" << __FILE__ << ", " << __LINE__ << ") " 

Works like a charm

+7
source

The LineID attribute is a sequence number that increments for each registration message. Therefore, you cannot use this.

You can use attributes to record line numbers, etc. This allows you to flexibly format using the format string, whereas when using Chris' answer your format is fixed.

Register global attributes in your registration initialization:

 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>("")); 

Configure these attributes in your logging protocol:

 #define logInfo(methodname, message) do { \ LOG_LOCATION; \ BOOST_LOG_SEV(_log, boost::log::trivial::severity_level::info) << message; \ } while (false) #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 quite pretty, but it works, and for me it was a long way. This pathetic boost does not offer this feature out of the box.

Do {...} while (false) - make the macro semantically neutral.

+5
source

The solution shown by Chris works, but if you want to customize the format or choose what information appears in each receiver, you need to use mutable constant attributes:

  logging::core::get()->add_global_attribute("File", attrs::mutable_constant<std::string>("")); logging::core::get()->add_global_attribute("Line", attrs::mutable_constant<int>(0)); 

Then you create a custom macro that includes these new attributes:

 // 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_global_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 following complete source code creates two receivers. The first uses the File and Line attributes, the second does not.

 #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_global_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_global_attribute("File", attrs::mutable_constant<std::string>("")); logging::core::get()->add_global_attribute("Line", attrs::mutable_constant<int>(0)); // A file log with time, severity, filename, line and message 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 ) ); // A console log with only time and message logging::add_console_log ( std::clog, keywords::format = ( expr::stream << expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S") << " | " << 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; } 

CUSTOM_LOG(lg, debug) << "A regular message"; operator CUSTOM_LOG(lg, debug) << "A regular message"; generates two outputs by writing a log file with this format ...

 2015-10-15_15:25:12.743153: <debug> [main.cpp:61] A regular message 

... and prints the following to the console:

 2015-10-15 16:58:35 | A regular message 
+3
source

Another option is to add line and file attributes to each log entry after they are created. This is possible since in newer versions. Attributes added later do not participate in filtering.

Assuming severity_logger is identified with a variable logger:

 boost::log::record rec = logger.open_record(boost::log::keywords::severity = <some severity value>); if (rec) { rec.attribute_values().insert(boost::log::attribute_name("Line"), boost::log::attributes::constant<unsigned int>(__LINE__).get_value()); ... other stuff appended to record ... } 

The above would, of course, be wrapped in a convenient macro.

You can later show this attribute using custom formatting for the receiver:

 sink->set_formatter( ...other stuff... << expr::attr<unsigned int>("Line") << ...other stuff... ); 

Unlike the previous answer, this approach requires more custom code and cannot use stand-alone buffering macros.

+1
source

For posterity — I made this set of macros for very simple logging queries that served me well — for simple logging tasks. But they illustrate how to do this in general, and the concept works easily with Boost. They must be local to a single file (which runs in multiple processes, sometimes in multiple threads in multiple processes). They are made for relative simplicity, not speed. They are safe to embed if statements, etc., so as not to steal another. At the beginning of the function in which you want to log, you call

 GLogFunc("function name"); 

You can then do this to write the complete line:

 GLogL("this is a log entry with a string: " << some_string); 

They also -

 #define GLogFunc(x) std::stringstream logstr; \ std::string logfunc; \ logfunc = x #define GLog(x) do { logstr << x; } while(0) #define GLogComplete do { \ _log << "[PID:" << _my_process << " L:" << __LINE__ << "] ((" << logfunc << ")) " << logstr.str() << endl; \ logstr.str(""); \ _log.flush(); \ } while(0) #define GLogLine(x) do { GLog(x); GLogComplete; } while(0) #define GLogL(x) GLogLine(x) #define GLC GLogComplete 

You can also create a journal on several lines ...

 GLog("I did this."); // later GLog("One result was " << some_number << " and then " << something_else); // finally GLog("And now I'm done!"); GLogComplete; 

Regardless of the _log stream (I open it as a file in the constructor of the class, which in this case is guaranteed to be safe), it receives the following output:

 [PID:4848 L:348] ((SetTextBC)) ERROR: bad argument row:0 col:-64 

And they can be conditionally disabled, and the entire performance evaluation canceled by a symbol during compilation as follows:

 #ifdef LOGGING_ENABLED ... do the stuff above ... #else #define GLogFunc(x) #define GLog(x) #define GLogComplete #define GLogLine(x) #define GLogL(x) #endif 
0
source

Here is my solution.

Installation code

 auto formatter = expr::format("[ %3% %1%:%2% :: %4%]") % expr::attr< std::string >("File") % expr::attr< uint32_t >("Line") % expr::attr< boost::posix_time::ptime >("TimeStamp") % expr::smessage ; /* stdout sink*/ boost::shared_ptr< sinks::text_ostream_backend > backend = boost::make_shared< sinks::text_ostream_backend >(); backend->add_stream( boost::shared_ptr< std::ostream >(&std::clog, NullDeleter())); // Enable auto-flushing after each log record written backend->auto_flush(true); // Wrap it into the frontend and register in the core. // The backend requires synchronization in the frontend. typedef sinks::synchronous_sink< sinks::text_ostream_backend > sink2_t; boost::shared_ptr< sink2_t > sink_text(new sink2_t(backend)); logging::add_common_attributes(); sink_text->set_formatter(formatter); 

Magazine Usage Code (Short Version):

 rec.attribute_values().insert("File", attrs::make_attribute_value(std::string(__FILE__))); \ 

full version:

 #define LOG(s, message) { \ src::severity_logger< severity_level > slg; \ logging::record rec = slg.open_record(keywords::severity = s); \ if (rec) \ { \ rec.attribute_values().insert("File", attrs::make_attribute_value(boost::filesystem::path(__FILE__).filename().string())); \ rec.attribute_values().insert("Line", attrs::make_attribute_value(uint32_t(__LINE__))); \ logging::record_ostream strm(rec); \ strm << message; \ strm.flush(); \ slg.push_record(boost::move(rec)); \ } \ 

} \

If I define a global attribute (e.g. people advise earlier), i.e.

 logging::core::get()->add_global_attribute("File", attrs::mutable_constant<std::string>("")); 

then I get an empty file / style.

0
source

All Articles