LoginSignup
11
9

More than 5 years have passed since last update.

Boost.Logの使い方(2. ログの収集)

Last updated at Posted at 2015-03-03
  1. 概略
  2. ログの収集
  3. ログの出力
  4. cmakeによるコンパイル

今回はログの収集についてです。

状況設定

ログを取るためにライブラリを使用する必要があるのは、複数のモジュールがあるときに
特定のモジュールからのログを選り分けたりする必要がある場合です。
最小の状況設定として以下の場合を考えます。

CMakeLists.txt
mod1/CMakeLists.txt
     func.hpp
     func1.cpp
     func2.cpp
     logger.cpp
client.cpp

あるモジュールmod1client.cppから使う場合を考えます。
また全てcmakeを使用してコンパイルします。

尚文章中に出現する略したnamespaceは以下の通りです:

namespace logging = boost::log;
namespace keywords = logging::keywords;
namespace sinks = logging::sinks;
namespace src = logging::sources;
namespace attrs = logging::attributes;
namespace expr = logging::expressions;

またサンプルコードはtermoshtt/boost_log_sampleにあります。

loggerの定義

自作loggerを作る事によって、そのloggerによって収集されるログに情報を付加できます。
以下で深刻度付きのloggerを生成します

mod1/func.hpp
namespace mod1 {
enum severity_level { debug, info, warning, error, critical };
BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(
    logger,                                                 // loggerの名称
    boost::log::sources::severity_logger_mt<severity_level> // loggerの型
    );
} // namespace mod1

これでmod1::loggerが定義されます。
これは例えば以下のように使います。

mod1/func1.cpp
namespace mod1 {
void func1() {
  auto &lg = logger::get();
  BOOST_LOG_SEV(lg, info) << "info in mod1::func1";
}
} // namespace mod1

loggerの実体は::get()で取得します。
BOOST_LOG_SEVは深刻度と一緒にログを記録するためのマクロです。
infomod1::infoな事に注意してください。

Tag, Scopeの追加

Boost.Logでは別のloggerで収集されたログは全て同じようにsinkに送られます。
つまりデフォルトではどのloggerから出力されたのかわかりません。
そこでloggerに、そのloggerで収集されたログに情報を付加する設定をします。

mod1/logger.cpp
namespace mod1 {
void init() {
  auto &lg = logger::get();
  lg.add_attribute("Tag", attrs::constant<std::string>("mod1"));
  lg.add_attribute("Scope", attrs::named_scope());
}
} // namespace mod1

モジュール自体の初期化コードでloggerを設定します。
これでmod1::loggerを通して収集されたログにはタグ"mod1"が付きます。

またログがどの関数で収集されたか、さらに言えばどのif文等のどのスコープで出力されたか、
というのは重要な情報である場合が多いです。
これを保持するのがScopeです。
これは常に値が一定("mod1")のタグと異なり、収集されるログ毎に値が変化します。

mod1/func1.cpp
namespace mod1 {

void func1(bool flag) {
  BOOST_LOG_FUNCTION(); // Scopeに関数名(void func1(boo))を登録する
  auto &lg = logger::get();
  if (flag) {
    BOOST_LOG_NAMED_SCOPE("true case"); // Scopeに入った事を記録する
    BOOST_LOG_SEV(lg, info) << "flag is true";
  } else {
    BOOST_LOG_NAMED_SCOPE("false case"); // Scopeに入った事を記録する
    BOOST_LOG_SEV(lg, info) << "flag is false";
  }
  BOOST_LOG_SEV(lg, error) << "Some error occurs!!";
}

} // namespace mod1

まとめ

これでモジュール中でログを収集する事が可能になりました。
trivialの場合と比べるとloggerを作る必要があるため、少し面倒ですが、
といっても数行追加するだけで済みました。
付加情報はloggingライブラリには必須なので、是非導入しましょう。
次回は収集したログを出力する方法をまとめます。

11
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
9