2017-08-24 10 views
0

私はBoost Logを初めて使い始めました。 私はロガーを作成し、そのレベルに警告(警告、情報、トレースなど)を割り当てようとしています。パフォーマンスの理由から、このロガーに送信されたログのうち、シンクレベルではなく、ロギングコアレベルのです。例えば (擬似コード):Boostログを使用してログソースごとに重大度を設定するにはどうすればよいですか?

logger lg; 
lg.setLevel(Warn); 
BOOST_LOG_TRIVIAL(trace) << "A trace severity message"; // Will be filtered 
BOOST_LOG_TRIVIAL(warn) << "A warning severity message"; // Won't be filtered 

私は、これはブーストログで達成することができますかなり確信しているが、いくつかの理由で、私はこれを行うことができませんでした。ありがとう、

オマー。

答えて

1

Boost.Logのロガー(ソース)レベルにフィルタはありません。フィルターは、グローバル(ロギングコア内)またはシンクごとに設定でき、すべてのソースからのログレコードは一様に処理されます。

channelsを使用して、各ロガーにチャネルを割り当て、チャネルと重大度に基づいてフィルタリングすることで、必要な動作を実装できます。

BOOST_LOG_ATTRIBUTE_KEYWORD(a_severity, "Severity", LogSeverity) 
BOOST_LOG_ATTRIBUTE_KEYWORD(a_channel, "Channel", std::string) 

typedef sources::severity_channel_logger< LogSeverity, std::string > logger_type; 

logger_type lg_a(keywords::channel = "A"); 
logger_type lg_b(keywords::channel = "B"); 

core::get()->set_filter 
(
    (a_channel == "A" && a_severity >= LogSeverity::info) || 
    (a_channel == "B" && a_severity >= LogSeverity::warning) 
); 

ライブラリには、簡略化するために使用できるa specialized filterもあります。あなたが実際にチャンネルごとに1つだけのロガーを持つように限定されるものではない

auto min_severity = expressions::channel_severity_filter(a_channel, a_severity); 
min_severity["A"] = LogSeverity::info; 
min_severity["B"] = LogSeverity::warning; 

core::get()->set_filter(min_severity); 

注 - 複数のものを作成し、それぞれが同じように扱われますからレコードをログに記録することができます。

+0

各レコードは、シンクに達する前にLoggingコアでかなりの処理が行われますか? これは、チャンネルごとに複数のシンクがある場合、上記のフィルタがそれぞれに適用されるか、チャンネルに関連するすべてのシンクにグローバルに適用できることを意味しますか? – omer

+0

フィルタリング段階では、フィルタ以外のレコード処理はありません。ログメッセージの構成を含む他のすべての処理は、少なくとも1つのシンクがレコードを受け入れた後に行われます(つまり、このシンクのフィルタリングがパスされた後)。グローバルフィルタが最初に適用され、シンク固有のフィルタが次に順番に適用されます。だから私の例では、フィルタはグローバルであり、シンクにかかわらずレコードごとに1回だけ適用されます。シンク固有のフィルタを設定すると、そのような各フィルタは、グローバルフィルタ*を通過したレコードごとに1回適用されます。 –

+0

コメントありがとう! しかし、Andrey氏は、豊富な機能とBoost.Logの柔軟性がパフォーマンスに大きな影響を及ぼす可能性があることを憂慮しています(私のプロジェクトでは高速パケット処理が必要なため、パフォーマンスは重要な要件です)。パフォーマンステストが行​​われたか、それともさらに良いのですか?他のC++ロギングフレームワークとのパフォーマンス比較ですか? ありがとうございます! – omer

1

私は自分のコードの小さなスニペットの下にここで...あなたが参照としてthis linkを使用

を示唆しています。この小さなスニペットでは、同期バックエンドを使用しましたが、非同期バックエンドを自由に使用できます。

log.hpp

#pragma once 

#include <boost/log/common.hpp> 
#include <boost/log/sources/severity_logger.hpp> 

enum class LogSeverity { 
    trace, debug, info, warning, error, fatal 
}; 

extern boost::log::sources::severity_logger<LogSeverity> g_logger; 

void log_set_filter(LogSeverity level); 
void init_logger(); 

#define LOG_TRACE BOOST_LOG_SEV(g_logger, LogSeverity::trace) 
#define LOG_DEBUG BOOST_LOG_SEV(g_logger, LogSeverity::debug) 
#define LOG_INFO BOOST_LOG_SEV(g_logger, LogSeverity::info) 
#define LOG_WARNING BOOST_LOG_SEV(g_logger, LogSeverity::warning) 
#define LOG_ERROR BOOST_LOG_SEV(g_logger, LogSeverity::error) 
#define LOG_FATAL BOOST_LOG_SEV(g_logger, LogSeverity::fatal) 

log.cpp

#include "bumper-common/log.hpp" 
#include <boost/log/common.hpp> 
#include <boost/log/sources/severity_logger.hpp> 
#include <boost/log/sinks/sync_frontend.hpp> 
#include <boost/log/sinks/text_ostream_backend.hpp> 
#include <boost/log/core.hpp> 
#include <boost/log/expressions.hpp> 
#include <boost/log/attributes.hpp> 
#include <boost/log/utility/setup/common_attributes.hpp> 
#include <boost/log/support/date_time.hpp> 
#include <boost/core/null_deleter.hpp> 
#include <iomanip> 
#include <iostream> 

using namespace boost::log; 

using LogTextSink = sinks::synchronous_sink<sinks::text_ostream_backend>; 

LogSeverity g_logLevel = LogSeverity::info; 
sources::severity_logger<LogSeverity> g_logger; 

BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", LogSeverity) 
BOOST_LOG_ATTRIBUTE_KEYWORD(timestamp, "TimeStamp", boost::posix_time::ptime) 
BOOST_LOG_ATTRIBUTE_KEYWORD(log_thread_id, "ThreadID", attributes::current_thread_id::value_type) 

std::ostream& operator<< (std::ostream& strm, LogSeverity level) 
{ 
    static const std::array<std::string, 6> strings 
    { 
     std::string{"trace"}, 
     std::string{"debug"}, 
     std::string{"info"}, 
     std::string{"warn"}, 
     std::string{"error"}, 
     std::string{"fatal"} 
    }; 

    strm << strings[static_cast<std::size_t>(level)]; 

    return strm; 
} 

void init_logger() 
{ 
    boost::shared_ptr<std::ostream> stream{&std::cout, 
     boost::null_deleter{}}; 

    auto loggerSink = boost::make_shared<LogTextSink>(); 

    add_common_attributes(); 

    loggerSink->locked_backend()->add_stream(stream); 
    loggerSink->locked_backend()->auto_flush(true); 

    loggerSink->set_filter(severity >= g_logLevel); 

    loggerSink->set_formatter(expressions::stream 
     << "[" << expressions::format_date_time(timestamp, "%H:%M:%S.%f") << "] [" 
     << std::setw(5) << std::left << severity << "] [" 
     << log_thread_id << "] " 
     << expressions::smessage 
    ); 

    boost::log::core::get()->add_sink(loggerSink); 
} 

void log_set_filter(LogSeverity level) 
{ 
    g_logLevel = level; 
} 

これはあなたを助けることができると思います。私はこのライブラリで多くの問題を抱えています。だから私は強くあなたが前に投稿したドキュメントを読むことを提案する。

+0

答えをありがとう! コードスニペットが正しく理解されている場合、レベルフィルタリングはシンクレベルで行われます(loggerSink-> set_filter(severity> = g_logLevel))。ロギングコアレベルでこのフィルタを実行する方法はありますか?パフォーマンスは私にとって非常に重要です。可能な限り早い時期にログを除外したいと思います。 – omer

+0

@omer私はここで同じ質問をしました:https://stackoverflow.com/questions/16102128/how-to-redirect-boost-log-to-file –

+0

速度が重要な場合は、他のロギングライブラリを使用することを検討してください:https ://github.com/gabime/spdlogまたは類似の –

関連する問題