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

Retrieving ETA (estimated time of arrival) with Google Distance Matrix API and public transit as transport mode -

android - ConstraintLayout: Realign baseline constraint in case if dependent view visibility was set to GONE -

c# - Populating Gridview inside Listview ItemTemplate On Web User Control from Code Behind -