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
Post a Comment