2017-04-07 20 views
0

私は基本的なboost example from hereに取り組んでいます。私は自分のアプリケーションに必要なものを設定していますが、私は立ち往生しています。私は今どこにいるのですか:Boost :: log:レベルに基づいた異なるフォーマット(HTMLフォーマット)

#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; 
} 

私はフォーマットを重大度に依存させたいと思います。これは、私のログ出力がHTMLであるためです。例えば、メッセージは、私は、ファイルに次のようにメインアップがなければならない出力に出力します。

<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> 

が、これは私がそこに持っている単純なモデルでは可能ですか?何がかかりますか?

sink->set_formatter()ifの条件を挿入します。私はそこでC++ 11ラムダを使うこともできませんでした。

答えて

1

あなたが望むことを実行するにはいくつかの方法があります。最も直接的なアプローチは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 
); 

しかし、このアプローチはかなり面倒なことや、次善の性能を持つことができます。

より良い解決策は、関数をフォーマッタに挿入することです。ここでは例です:

はここ
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()) 
); 

or_noneは属性がprefix_formattersuffix_formatterでそれをチェックする必要が故に、ログレコードに存在しない場合value_refは空になります。

最後に、HTMLを記述しているので、出力の予約文字を自動的にエスケープシーケンスに変換したいと思うでしょう。 XML character decoratorがこれを手伝ってくれます。

+0

ありがとうございました。私はそれを実装しようとしています。その 'string_view'はブースト1.55ではありません、そうですか?私はDebian Jessieにあり、 '/ usr /'ディレクトリ全体でgrepで見つけることができませんでした。 –

+0

いいえ、後で追加されました。代わりに 'boost :: string_ref'や' std :: string'を使うことができます。 –

+0

ありがとうございました。私はそれを知らなかった。実際に今朝私は 'string_view'について読んで、それが何であるかを学びました。一方、私は自分の問題に対する解決策を見つけ、別の答えでそれを書いた。私はあなたから多くを学んだので、これを+1しています:)もう一度ありがとう! –

0

は、私は、カスタムフォーマッタを、このようにそれを行うことができました:どうやらstring_viewは新しいものであると私はというのが私のブーストでそれを見つけることができなかったため

#include <fstream> 
#include <iomanip> 
#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> 
#include "boost/log/utility/setup.hpp" 
#include "boost/log/support/date_time.hpp" 
#include <boost/log/expressions/formatters/xml_decorator.hpp> 

namespace b_logging = boost::log; 
namespace b_srcs = b_logging::sources; 
namespace b_expr = b_logging::expressions; 
namespace b_sinks = b_logging::sinks; 

b_logging::formatting_ostream& severity_wrap_prefix(b_logging::formatting_ostream& strm, const b_logging::trivial::severity_level& sev) 
{ 
    if  (sev == b_logging::trivial::severity_level::trace) 
     strm << "<font color='gray'>"; 
    else if(sev == b_logging::trivial::severity_level::debug) 
     strm << "<font color='#808080'>"; 
    else if(sev == b_logging::trivial::severity_level::info) 
     strm << "<font color='green'>"; 
    else if(sev == b_logging::trivial::severity_level::warning) 
     strm << "<font color='orange'>"; 
    else if(sev == b_logging::trivial::severity_level::error) 
     strm << "<font color='red'>"; 
    else if(sev == b_logging::trivial::severity_level::fatal) 
     strm << "<strong><font color='red'>"; 
    else 
     strm << "<UNKNOWN SEVERITY LEVEL>"; 
    return strm; 
} 

b_logging::formatting_ostream& severity_wrap_suffix(b_logging::formatting_ostream& strm, const b_logging::trivial::severity_level& sev) 
{ 
    if  (sev == b_logging::trivial::severity_level::trace) 
     strm << "</font><br>"; 
    else if(sev == b_logging::trivial::severity_level::debug) 
     strm << "</font><br>"; 
    else if(sev == b_logging::trivial::severity_level::info) 
     strm << "</font><br>"; 
    else if(sev == b_logging::trivial::severity_level::warning) 
     strm << "</font><br>"; 
    else if(sev == b_logging::trivial::severity_level::error) 
     strm << "</font><br>"; 
    else if(sev == b_logging::trivial::severity_level::fatal) 
     strm << "</strong></font><br>"; 
    else 
     strm << "<UNKNOWN SEVERITY LEVEL>"; 
    return strm; 
} 

std::string ptime_to_string(const boost::posix_time::ptime& time) 
{ 
    std::stringstream str; 
    boost::posix_time::time_facet *facet = new boost::posix_time::time_facet("%d.%m.%Y-%H:%M:%S-UTC"); 
    str.imbue(std::locale(str.getloc(), facet)); 
    str << time; 
    return str.str(); 
} 

void init() 
{ 
    b_logging::core::get()->add_global_attribute("TimeStamp", b_logging::attributes::utc_clock()); 
    typedef b_sinks::synchronous_sink<b_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>("sample.htm")); 

    sink->set_formatter([&](b_logging::record_view const& rec, b_logging::formatting_ostream& strm) 
    { 
     const b_logging::trivial::severity_level& sev = *b_logging::extract<b_logging::trivial::severity_level>("Severity", rec); 

     const boost::posix_time::ptime &pt = *b_logging::extract<boost::posix_time::ptime>("TimeStamp", rec); 

     severity_wrap_prefix(strm,sev); 
     strm << ptime_to_string(pt) << ": " 
        << rec[b_expr::smessage]; 
     strm << b_expr::xml_decor[b_expr::stream << b_expr::smessage]; 
     severity_wrap_suffix(strm,sev); 
    }); 

    b_logging::core::get()->add_sink(sink); 
} 


int main(int, char*[]) 
{ 
    std::cout<<"Start"<<std::endl; 
    init(); 
    b_logging::add_common_attributes(); 

    using namespace b_logging::trivial; 
    b_srcs::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; 
} 

アンドレイのソリューションは、私のために動作しませんでしたDebian Jessie、Boost 1.55が付属しています。

関連する問題