c++ - Boost::log: Different formatting based on level (HTML formatted) -


i'm working on basic boost example here. i'm configuring need application, i'm stuck. here's now:

#include <fstream> #include <iomanip> #include <boost/date_time/posix_time/posix_time_types.hpp> #include <boost/log/support/date_time.hpp> #include <boost/smart_ptr/shared_ptr.hpp> #include <boost/smart_ptr/make_shared_object.hpp> #include <boost/log/core.hpp> #include <boost/log/trivial.hpp> #include <boost/log/expressions.hpp> #include <boost/log/sinks/sync_frontend.hpp> #include <boost/log/sinks/text_ostream_backend.hpp> #include <boost/log/sources/severity_logger.hpp> #include <boost/log/sources/record_ostream.hpp> #include <boost/log/utility/setup/common_attributes.hpp> #include <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/posix_time/posix_time_io.hpp>  namespace logging = boost::log; namespace src = boost::log::sources; namespace expr = boost::log::expressions; namespace sinks = boost::log::sinks; namespace keywords = boost::log::keywords;  void init() {     typedef sinks::synchronous_sink<sinks::text_ostream_backend> text_sink;     boost::log::core::get()->add_global_attribute("timestamp", boost::log::attributes::utc_clock());     boost::shared_ptr<text_sink> sink = boost::make_shared<text_sink>();      sink->locked_backend()->add_stream(         boost::make_shared<std::ofstream>("log.html"));      sink->set_formatter     (         expr::stream             << expr::format_date_time<boost::posix_time::ptime>("timestamp", "%y.%m.%d-%h:%m:%s-utc")             << ": <" << logging::trivial::severity << "> " << expr::smessage     );      logging::core::get()->add_sink(sink); }   int main(int, char*[]) {     std::cout<<"start"<<std::endl;     init();     logging::add_common_attributes();      using namespace logging::trivial;     src::severity_logger< severity_level > lg;      boost_log_sev(lg, trace) << "a trace severity message";     boost_log_sev(lg, debug) << "a debug severity message";     boost_log_sev(lg, info) << "an informational severity message";     boost_log_sev(lg, warning) << "a warning severity message";     boost_log_sev(lg, error) << "an error severity message";     boost_log_sev(lg, fatal) << "a fatal severity message";      std::cout<<"end"<<std::endl;     return 0; } 

i have formatting depend on severity level. because logging output html. example, messages print in main there should output file:

<font color='black'>a trace severity message</font> <font color='gray'>a debug severity message</font> <font color='blue'>an informational severity message</font> <font color='orange'>a warning severity message</font> <font color='red'>an error severity message</font> <strong><font color='red'>a fatal severity message</font></strong> 

is possible simple model have there? take?

inserting if condition sink->set_formatter(). couldn't use c++11 lambda in there.

there number of ways want. direct approach use conditional formatter:

sink->set_formatter (     expr::stream         << expr::if_(logging::trivial::severity <= logging::trivial::severity_level::trace)            [                expr::stream << "<font color='black'>"            ]            .else_            [                expr::stream << expr::if_(logging::trivial::severity <= logging::trivial::severity_level::debug)                [                     // ...                ]            ]         << expr::format_date_time<boost::posix_time::ptime>("timestamp", "%y.%m.%d-%h:%m:%s-utc")         << ": <" << logging::trivial::severity << "> " << expr::smessage ); 

however, approach can rather tedious , have suboptimal performance.

a better solution inject function formatter. here's example:

boost::string_view prefix_formatter(     logging::value_ref< logging::trivial::severity_level, logging::trivial::tag::severity > const& level) {     if (level)     {         switch (level.get())         {         case logging::trivial::severity_level::trace:             return "<font color='black'>";         case logging::trivial::severity_level::debug:             return "<font color='gray'>";         // ...         }     }      return boost::string_view(); }  boost::string_view suffix_formatter(     logging::value_ref< logging::trivial::severity_level, logging::trivial::tag::severity > const& level) {     if (level)     {         switch (level.get())         {         case logging::trivial::severity_level::trace:             return "</font>";         // ...         }     }      return boost::string_view(); }  sink->set_formatter (     expr::stream         << boost::phoenix::bind(&prefix_formatter, logging::trivial::severity.or_none())         << expr::format_date_time<boost::posix_time::ptime>("timestamp", "%y.%m.%d-%h:%m:%s-utc")         << ": <" << logging::trivial::severity << "> " << expr::smessage         << boost::phoenix::bind(&suffix_formatter, logging::trivial::severity.or_none()) ); 

here, or_none makes value_ref empty if attribute not present in log record, hence need check in prefix_formatter , suffix_formatter.

finally, since you're writing html, want automatically convert reserved characters in output escape sequences. xml character decorator can this.


Comments

Popular posts from this blog

c# - Update a combobox from a presenter (MVP) -

How to understand 2 main() functions after using uftrace to profile the C++ program? -

How to put a lock and transaction on table using spring 4 or above using jdbcTemplate and annotations like @Transactional? -